Web Based Uptime Report - Last Patch Date and Reboot Time

<######################################################################
Uptime Report
This Script gathers the report of system boot time using WMI query to remote servers and generates HTML output. 

.NOTES    
Name: Uptime_Report.ps1

Version : 1.2
Update  : Check on Address Resolution Status
		: Check on WMI Query Status
Date	: 04-Oct-2018

Version	: 1.1
Date	: 24-Jan-2018

.ServerList
Add List of Servers in RADWS.txt file and keep on same directory

.EXAMPLE 
Uptime_Report.ps1
######################################################################>

<#------------------

Get server status code

--------------------#>

$Now = Get-Date
Function GetStatusCode
{ 
	Param([int] $StatusCode)  
	switch($StatusCode)
	{
		0		{"ONLINE"}
		11001	{"Buffer Too Small"}
		11002   {"Destination Net Unreachable"}
		11003   {"Destination Host Unreachable"}
		11004   {"Destination Protocol Unreachable"}
		11005   {"Destination Port Unreachable"}
		11006   {"No Resources"}
		11007   {"Bad Option"}
		11008   {"Hardware Error"}
		11009   {"Packet Too Big"}
		11010   {"Request Timed Out"}
		11011   {"Bad Request"}
		11012   {"Bad Route"}
		11013   {"TTL Expired Transit"}
		11014   {"TimeToLive Expired Reassembly"}
		11015   {"Parameter Problem"}
		11016   {"Source Quench"}
		11017   {"Option Too Big"}
		11018   {"Bad Destination"}
		11032   {"Negotiating IPSEC"}
		11050   {"General Failure"}
		default {"Failed"}
	}
}

<#------------------

Get Up time and Up days

--------------------#>

Function GetUpTime
{
	param([string] $LastBootTime)
	$Now = Get-Date
	$Uptime = (Get-Date) - [System.Management.ManagementDateTimeconverter]::ToDateTime($LastBootTime)
	"$($Uptime.Days) Days; $($Uptime.Hours) Hrs; $($Uptime.Minutes) Mins; $($Uptime.Seconds) Secs" 
    "$($Uptime.Days)"
}

$ServerList = Get-Content "C:\wamp64\apps\uptime\RADWS.txt"
$SlNo = 0
$Result = @()

Foreach($ServerName in $ServerList)
{
	$SlNo = $SlNo + 1
	#$pingStatus.StatusCode = $null
	$pingStatus = Get-WmiObject -Query "Select * from win32_PingStatus where Address='$ServerName'"
	$Uptime = $null
    $OS = $null
    $LastPatch = $null
    $LastBoot = $null
    $SerialNumber = $null
	if($pingStatus.StatusCode -eq 0)
	{
		try {
			$OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ServerName -ErrorAction Stop
			$Uptime = GetUptime( $OperatingSystem.LastBootUpTime )
            $LastBoot = [System.Management.ManagementDateTimeconverter]::ToDateTime( $OperatingSystem.LastBootUpTime )
            $OS = $OperatingSystem | select -Expand Caption
            ##$LastPatch = (Get-HotFix -ComputerName $ServerName | sort installedon).InstalledOn[-1].ToShortdatestring()
            $LastPatch = (Get-HotFix -ComputerName $ServerName | sort installedon).InstalledOn[-1]
            $SerialNumber = (Get-WmiObject -Class Win32_Bios -ComputerName $ServerName | sort SerialNumber).SerialNumber
		}
		catch {
			$OS = "NA"
            $Uptime = @("NA", "NA")
            $LastBoot = "NA"
            $LastPatch = "NA"
            $SerialNumber = "NA"
		}
	
    	$Result += New-Object PSObject -Property @{
			SlNo = $SlNo
			ServerName = $ServerName
            SerialNumber = $SerialNumber
            OpertaingSystem = $OS
			IPV4Address = $pingStatus.IPV4Address
			Status = GetStatusCode( $pingStatus.StatusCode )
			Uptime = $Uptime[0]
            UpDays = $Uptime[1]
            LastPatch = $LastPatch
            LastBoot = $LastBoot
		}
	}
	else {
		$Result += New-Object PSObject -Property @{
            SlNo = $SlNo
            ServerName = $ServerName
            SerialNumber = "NA"
            OpertaingSystem = "NA"
            IPV4Address = $pingStatus.IPV4Address
            Status = "NA"
            Uptime = "NA"
            UpDays = "NA"
            LastBoot = "NA"
            LastPatch = "NA"
		}
	}
}

<#---------------------

Generate HTML report page

------------------------#>

if($Result -ne $null)
{
	<#$HTML = "<div class="'content'">"#>
    $HTML = "<p>
			Time : $($Now) <br>
         </p>"
    $HTML += "<div class="script-name"><p><u>RADIOLOGY RAD WORKSTATIONS STATUS REPORT</u></p></div>"
    $HTML += "<div class="back-btn"><button class='button' onclick='goBack()'>HOME</button></div>"
    $HTML += "<br><br>"
    $HTML += "<div>"
    $HTML += "<Table class="'sortable'">
    <TR>
    <TH><B>Sl No.</B></TH>
    <TH><B>Server Name</B></TH>
    <TH><B>Serial Number</B></TH>
    <TH><B>IP Address</B></TH>
    <TH><B>OS</B></TD>
    <TH><B>Ping Status</B></TH>
    <TH><B>Last Patched</B></TH>
    <TH><B>Last Reboot</B></TH>
    <TH><B>Uptime</B></TH>
    <TH><B>UpDays</B></TH>
    </TR>"
    Foreach($Entry in $Result)
    {
        $HTML += "
		<TD>$($Entry.SlNo)</TD>
		<TD><a href="/uptime/patch_lst.php?m=$($Entry.ServerName)">$($Entry.ServerName)</a></TD>
        <TD>$($Entry.SerialNumber)</TD>
        <TD>$($Entry.IPV4Address)</TD>"
        
        if($Entry.OpertaingSystem -clike '*Microsoft *'){
            $Entry.OpertaingSystem = $Entry.OpertaingSystem.Substring(10)
        }

        if($Entry.OpertaingSystem -clike '*2008*' -or $Entry.OpertaingSystem -clike '*Windows 7*')
        {
            $HTML += "<TD style="color:">"
        }
        else
		{
			$HTML += "<TD>"
		}
        
        $HTML += "$($Entry.OpertaingSystem)</TD>
		<TD>$($Entry.Status)</TD>
        <TD>$($Entry.LastPatch)</TD>
        <TD>$($Entry.LastBoot)</TD>
		<TD>$($Entry.Uptime)</TD>"

        if($Entry.UpDays -ne "NA")
        {
            $Days = [int]$Entry.UpDays
            if($Days -gt 20)
            {
                $HTML += "<TD style="color:">"
            }
            else
		    {
			    $HTML += "<TD>"
		    }
        }
        else
		{
			$HTML += "<TD>"
		}
        $HTML += "
        $($Entry.UpDays)</TD>
		</TR>"
    }
$HTML += "</Table></div></br></br></br>"
Write-Output $HTML
}

The above code can be invoked by a simple Php script on a web server.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SERVER STATUS REPORT</title>
<style type="text/css">

.content {
    max-width:100%;
    margin:auto;font-family:"Cambria", Arial, Helvetica, sans-serif;}

#disp-tbl {
    max-width: 1600px;
    font-size: 15px;
    margin:auto;
    font-family:"Cambria", Arial, Helvetica, sans-serif; margin-left: auto; margin-right: auto;
}

.script-name {
    font-family: Cambria;
    color: #ed8484;
    font-size: 34px;
    text-align: center;
    margin-top: 50px;
    margin-bottom: 50px;
}

.back-btn {
    font-family:Cambria;
    color:#ed8484;
    font-size:34px;
    text-align:right;
    margin-right:300px;
}

.button {
  background-color: #4CAF50;
  border: none;
  color: white;
  padding: 15px 25px;
  text-align: center;
  font-size: 16px;
  cursor: pointer;
}

.button:hover {
  background-color: green;
}

table.sortable thead {
    background-color:#ccc;
    color:#666666;
    font-weight: bold;
    cursor: default;
}

table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after { 
    content: " \25B4\25BE" 
}

table.sortable tbody tr:hover{
    background: #ccc;
}

table.sortable tbody tr:nth-child(2n) td {
  background: #eee;
}

table.sortable tbody tr:nth-child(2n+1) td {
  background: #fff;
}

header {
  background-color: #666;
  padding: 10px;
  text-align: center;
  font-size: 35px;
  color: white;
}

nav {
  float: left;
  width: 10%;
  /*height: 300px;  only for demonstration, should be removed */
  background: #ccc;
  padding: 20px;
}

nav ul {
  list-style-type: none;
  padding: 0;
}

article {
  padding: 20px;
  width: 90%;
  /*//float: left;
  //background-color: #f1f1f1;
  //height: 300px;  only for demonstration, should be removed */
}

/* Clear floats after the columns */
section:after {
  content: "";
  display: table;
  clear: both;
}

/* Style the footer */
footer {
  background-color: #777;
  padding: 10px;
  text-align: center;
  color: white;
}

/* Responsive layout - makes the two columns/boxes stack on top of each other instead of next to each other, on small screens */
@media (max-width: 600px) {
  nav, article {
    width: 100%;
    height: auto;
  }
}

</Style>

<script>
    function goBack() {
        window.history.back();
        }
</script>

<script src="sorttable.js"></script>

</head>
<body>
<div class="'content'">
	<?php

		ini_set('max_execution_time', 6000);
 
		// If there was no submit variable passed to the script (i.e. user has visited the page without clicking submit), display the form:
		if(!isset($_POST["submit"]))
		{
    	?>
    			<div>
                    <form name="testForm" id="testForm" action="index.php" method="post" />
        			    <table>
                            <tr>
                                <td>PACS SERVER</td>
                                <td><input type="submit" name="submit" id="submit" value="SERVERS" /></br></td>
                            </tr>
                            <tr>
                                <td>PACS WORKSTATIONS</td>
                                <td><input type="submit" name="submit" id="submit" value="RAD WRKSTATIONS" /></br></td>
                            </tr>
                            <tr>
                                <td>CPACS TECH WORKSTATIONS</td>
                                <td><input type="submit" name="submit" id="submit" value="TECH WRKSTATIONS" /></br></td>
                            </tr>
                            <tr>
                                <td>PACS TECH WORKSTATIONS</td>
                                <td><input type="submit" name="submit" id="submit" value="TECH WRKSTATIONS" /></br></td>
                            </tr>
                            <tr>
                                <td>SSL CERTIFICATES</td>
                                <td><input type="submit" name="submit" id="submit" value="SERVER SSL CERT" /></br></td>
                            </tr>
                        </table>
    			    </form>
                </div>
    	<?php    
		}
	
		// Else if submit was pressed, check if all of the required variables have a value:
		elseif((isset($_POST["submit"])))
		{
    			if($_POST["submit"] == "PACS SERVERS")
                {       
                    $psScriptPath = "C:\wamp64\apps\uptime\get-uptime-SERVERS.ps1";
                }

                if($_POST["submit"] == "PACS RAD WRKSTATIONS")
                {       
                    $psScriptPath = "C:\wamp64\apps\uptime\get-uptime-RADWRKSTNS.ps1";
                }

                if($_POST["submit"] == "PACS TECH WRKSTATIONS")
                {       
                    $psScriptPath = "C:\wamp64\apps\uptime\get-uptime-TECHWRKSTNS.ps1";
                }

                if($_POST["submit"] == "CPACS TECH WRKSTATIONS")
                {       
                    $psScriptPath = "C:\wamp64\apps\uptime\get-uptime-CPACSWRKSTNS.ps1";
                }

                if($_POST["submit"] == "SERVER SSL CERT")
                {       
                    $psScriptPath = "C:\wamp64\apps\uptime\get-cert-date-SERVERS.ps1";
                }

                // Get the variables submitted by POST in order to pass them to the PowerShell script:
    			//$username = $_POST["username"];
    			// Best practice tip: We run out POST data through a custom regex function to clean any unwanted characters, e.g.:
    			// $username = cleanData($_POST["username"]);
         
    			// Path to the PowerShell script. Remember double backslashes:
    			//$psScriptPath = "C:\wamp64\apps\uptime\get-process.ps1";
    			//$psScriptPath = "C:\wamp64\apps\uptime\get-uptime-SERVERS.ps1";
 
    			// Execute the PowerShell script, passing the parameters:
    			$query = shell_exec("powershell -command $psScriptPath < NUL");
    			echo $query;    
		}

		// Else the user hit submit without all required fields being filled out:
		else
		{
    			$msg = "Sorry, you did not complete all required fields. Please go back and try again.";
    			echo $msg;	
		}
	?>
</div>
</body>
</html>