Adding notes against server names in TXt file lookup

Hi All
I created the following script to check the last reboot time of servers to ensure they were all regularly being rebooted to pick up security patches.

cls 
$listitems="\\backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\SCM_Machine_List.txt,\\ backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\dbMotion_Machine_List.txt,\\backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\App_Support_Machine_List.txt"

$listitems = $listitems.Split(",")

foreach($list in $listitems) 
{
    $b=""
    $machines = ""
    $machines = Get-Content $list
    $d1=Get-Date
    $report = @() 
    $object = @() 
    
        foreach($machine in $machines) 
        { 
            Try
            {
                $machine 
                $d2 = gwmi win32_operatingsystem -ComputerName $machine | select @{LABEL='LastBootUpTime';EXPRESSION={$_.lastbootuptime}}
                $d2= $d2.LastBootUpTime
                $d2 = $d2.Substring(0, $d2.IndexOf("."))
                $d2 = [DateTime]::ParseExact($d2, 'yyyyMMddHHmmss', $null).ToString("dd MMM yyyy HH:mm:ss")

                $ts = New-TimeSpan -Start $d1 -End $d2
            
                $object = gwmi win32_operatingsystem -ComputerName $machine | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}, @{LABEL='Days';EXPRESSION={$ts.Days}}  
                $report += $object 
             }
            Catch
            {
                $b = "$b <br> $machine NOT FOUND, PLEASE INVESTIGATE & OTHER SERVERS MAY NOT HAVE BEEN CHECKED!"
                Continue
            }  
        } 
        #$report | Export-csv V:\Desktop\SERVER_REBOOT_CHECK\Reboot.csv
    
    
        $a = $report | Sort-Object LastBootUpTime | ConvertTo-Html -Fragment
   
    if ($a)
    {
        $Server = $env:COMPUTERNAME#this picks up the pcname
        $path = Split-Path $script:MyInvocation.MyCommand.Path 
        $filename = $script:MyInvocation.MyCommand.Name
        $path = "$path\$filename"
        $now = Get-Date
        $smtp = " BLANKED OUT " 
        #[String[]]$Recipients = "<BLANKED OUT>", "<BLANKED OUT>" #Use for multiple recipients
        $Recipients = " BLANKED OUT " #Use for single recipient
        $from = " BLANKED OUT "
        $subject = "Report on last reboot of servers (Machine '$Server' has run '$path')."  
        $list = $list.Substring($list.LastIndexOf("\")+1)
        $body  = "$list <br>$b<br> $a<br>(Machine '$Server' has run '$path' at '$now')<br>"
    
        Send-MailMessage    -From $from -To $Recipients -Subject "$subject" -Body "$body" -BodyAsHtml -Smtpserver $SMTP;
        #$body
    }
}

The script references 3 text files with lists of server names and returns the servers names with last reboot dates + number of days

We have a few servers that are on 2008 pending migration and therefore do not pickup an updates and no rebooted by our server team.

How can I had a note for my return list of users to add the OS version next to the server name without causing the script to fail?

E.g Text file 1 contains

Servername1
Servername2
Servername3
Servername4
Servername5

Can I add a note in brackets or something next to servername1 saying (2008) for example?

E.G.

Servername1 (2008)
Servername2 (2012)
Servername3 (2016)
Servername4 (2008)
Servername5 (2014)

App,
Welcome to the forums. :wave:t4:

I think you’re overcomplicating this task. If it’s really just checking the LastBootupTime of a bunch of servers this is all you need:

$ComputerName = 'Server01','Server02','Server03'
Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $ComputerName |
    Select-Object -Property PSComputerName,LastBootupTime

Of course you can import the names of the remote computers from a file or from the AD and you can export the output to a CSV file if needed. And you may add error handling and checking for availability of the computer before querying.

1 Like

Here is the script a bit cleaned up with some tips (not tested):

#Make the lists an array rather than a string and then split to turn them into an array
$listitems= "\\backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\SCM_Machine_List.txt",
            "\\backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\dbMotion_Machine_List.txt",
            "\\backserv\scm\development\Application Support\SCM\Scripts\WeeklyChecks\SERVER_REBOOT_CHECK_Email\App_Support_Machine_List.txt"

$report = foreach($list in $listitems) {
    foreach($machine in (Get-Content $list)) { 
        try {
            #Use Get-CimInstance, gwmi is deprecated
            #Missing -ErrorAction Stop for try\catch to work
            #Only one remote call to machine and get all data
            Get-CimInstance -ClassName win32_operatingsystem -ComputerName $machine -ErrorAction Stop | 
            Select-Object -Property CSName,
                                    Version,
                                    @{Name='LastBootUpTime';EXPRESSION={$_.lastbootuptime}},
                                    @{Name='Days';Expression={New-TimeSpan -Start $_.lastbootuptime -End (Get-Date) | Select-Object -ExpandProperty Days}},
                                    @{Name='Status';Expression={'Success'}},
                                    @{Name='List';Expression={$list.Substring($list.LastIndexOf("\")+1)}}
            }
        catch {
            #Rather than a text error, create an object schema that matches and capture the error. This can be filtered out with a | Where {$_.Status -ne 'Success}
            [PSCustomObject]@{
                CSName         = $machine
                Version        = $null
                LastBootUpTime = $null
                Days           = $null
                Status         = 'Failed: {0}' -f $_
                List           = $list.Substring($list.LastIndexOf("\")+1)
            }
        }  
    } 
}

#You now have one object that can be filtered on the list, errors, 
#etc to send 1 email rather than 3 or filter and send the reports
#outside the loop

$reportHtml = $report | Sort-Object LastBootUpTime | ConvertTo-Html -Fragment

#Here-String
$htmlBody = @"
<html>
    <head>
    </head>
    <body>
        $($reportHtml)

        Machine $($env:COMPUTERNAME) has run $(Split-Path $script:MyInvocation.MyCommand.Path)\$script:MyInvocation.MyCommand.Name at $(Get-Date)
    </body>
</html>
"@

if ($report) {
    #Splatting  
    $mailParams = @{
        From       = 'someone@company.com'
        To         = 'someone@company.com' 
        Subject    =  "Report on last reboot of servers (Machine '$Server' has run '$path')." 
        Body       = ($htmlBody | Out-String) 
        BodyAsHtml = $true 
        Smtpserver = 'smtprelay.company.com'  
    }

    Send-MailMessage @mailParams
}
1 Like