Skip to content

Instantly share code, notes, and snippets.

@TheRickOlson
Last active February 10, 2016 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheRickOlson/68dd74b5e5699fc44da0 to your computer and use it in GitHub Desktop.
Save TheRickOlson/68dd74b5e5699fc44da0 to your computer and use it in GitHub Desktop.
January 2016 Script Puzzle
<#
.SYNOPSIS
Gets the uptime of one or more computers.
.PARAMETER Name
The name of the computer(s) that you want to run this command against. By default it will run against the local machine. You can pass multiple computers separated with comma, or pass objects to it via the pipe.
.EXAMPLE
Get-Uptime
With no parameters passed, this will get the uptime of the local machine
ComputerName : TS-SA-12345
StartTime : 2/10/2016 7:35:21 AM
Uptime (Days) : 0.3
Status : OK
MightNeedPatched : False
.EXAMPLE
Get-Uptime -Name SERVER1
Check the uptime of a single computer named SERVER1
ComputerName : SERVER1
StartTime : 1/31/2016 12:00:00 AM
Uptime (Days) : 10.3
Status : OK
MightNeedPatched : False
.EXAMPLE
Get-Uptime -Name SERVER1,SERVER2,SERVER3 | Format-Table -Autosize
This example passes three computer names to Get-Uptime named SERVER1, SERVER2 and SERVER3
ComputerName StartTime Uptime (Days) Status MightNeedPatched
------------ --------- ------------- ------ ----------------
SERVER1 1/31/2016 5:54:26 AM 10.3 OK False
SERVER2 1/31/2016 5:45:40 AM 10.3 OK False
SERVER3 OFFLINE False
.EXAMPLE
Get-ADComputer SERVER1 | Get-Uptime
In this example, we use Get-ADComputer (from the ActiveDirectory module) to get the SERVER1 computer object. Then we pass that object to Get-Uptime.
ComputerName : SERVER1
StartTime : 1/31/2016 12:00:00 AM
Uptime (Days) : 10.3
Status : OK
MightNeedPatched : False
.INPUTS
String. You can pass computer name via the $Name parameter to Get-Uptime
.OUTPUTS
System.Management.Automation.PSCustomObject
#>
function Get-Uptime{
# This sets the function up to accept objects as input
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline=$true,ValueFromPipelinebyPropertyName=$true)]
[string[]]$Name=$env:computername)
PROCESS {
foreach ($comp in $Name)
{
try {
# Pre-build our object
$outputObject = [Ordered]@{
'ComputerName' = $comp
'StartTime' = $null
'Uptime (Days)' = $null
'Status' = $null
'MightNeedPatched' = $false
}
#Test to see if the computer is alive
Write-Verbose -Message "[$comp]: Attempting to connect with computer."
if (-not(Test-Connection -ComputerName $comp -Count 1 -Quiet)) {
# Set the status to offline and throw an exception
$outputObject.Status = "OFFLINE"
throw "The computer [$($comp)] is offline."
}
# Set the status to OK
$outputObject.Status = "OK"
# Get the time object and calculate length of time since last boot
Write-Verbose -Message "[$comp]: Calculating uptime days."
$obj = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $comp
$time = $obj.ConvertToDateTime($obj.LocalDateTime) - $obj.ConvertToDateTime($obj.LastBootUpTime)
# Set the Start Time
$outputObject.StartTime = $obj.ConvertToDateTime($obj.LastBootUpTime)
# Set the Uptime (Days) parameter and format it to only extend one decimal point
$outputObject.'Uptime (Days)' = "{0:N1}" -f $time.TotalDays
# Make patching determination based on total days since last boot
Write-Verbose -Message "[$comp]: Checking if computer may need patching."
if ($time.TotalDays -gt '30') {
$outputObject.MightNeedPatched = $true
} else { $outputObject.MightNeedPatched = $false }
}
catch
{
# This assumes a problem with communicating to the computer object
Write-Verbose -Message $_.Exception.Message
}
finally
{
# output the object regardless of thrown error.
[pscustomobject]$outputObject
} # try
}# foreach
}# process
}# function
@poshcodebear
Copy link

3 quick tips:
1: if you name your Gist with a .ps1 extension, it will automatically add syntax highlighting
2: Unless you have a really good reason to, you should never clear the error counter (there are exceptions, certain cmdlets don't throw errors in a way try/catch can use, so you have to get creative). You should capture the error in your catch block and handle it there. Also, setting your error action to "SilentlyContinue" effectively makes your try/catch block useless.
3: You don't need to build a PSSession for this; Get-CimInstance and Get-WmiObject both have a -ComputerName argument that will work just fine and handle the session automatically (no set up or tear down needed)

@TheRickOlson
Copy link
Author

Thank you for the tips! I'll see if I can incorporate them all and maybe make the code a little cleaner, I appreciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment