From d4b9ed2d8975b1a20ea64404a893feea1886b8dc Mon Sep 17 00:00:00 2001 From: Tyler Hale Date: Tue, 14 Sep 2021 14:12:03 -0600 Subject: [PATCH] Initial commit --- Get-SystemStatus.ps1 | 416 +++++++++++++++++++++++++++++++++++++ Images/Example-Default.png | Bin 0 -> 10438 bytes Images/Example-HTML.png | Bin 0 -> 13929 bytes README.md | 110 +++++++++- 4 files changed, 521 insertions(+), 5 deletions(-) create mode 100644 Get-SystemStatus.ps1 create mode 100644 Images/Example-Default.png create mode 100644 Images/Example-HTML.png diff --git a/Get-SystemStatus.ps1 b/Get-SystemStatus.ps1 new file mode 100644 index 0000000..0529500 --- /dev/null +++ b/Get-SystemStatus.ps1 @@ -0,0 +1,416 @@ +<# + +.SYNOPSIS +Gets various information related to a running system's status for reporting. + +.DESCRIPTION +Gathers the follow information from a provided list of computers. +The collected data is then returned as a DataTable or can be exported to a variety of file formats. +Optional Metadata can be included to be included in the returned results/reports to assist in machine identification. + +Collected Data: Computer Name, Operating System, Operating System Build, Uptime, Recent Updates, Disk Space Utilization, Date Gathered +Optional Metadata: Organization, Role, UpdateWindow + +.PARAMETER ComputerName +Specifies a computer or set of computers that should be queried for their status. + +.PARAMETER CsvPath +Path to a CSV that contains the list computers that should be collected. +Optional metadata can be included that will be included in returned data. + +Columns: +Name* +Organization +Role +UpdateWindow + +*: Required + +.PARAMETER Credential +Credentials used for connecting to the specified computers to gather the machine's status information. + +.PARAMETER CredentialPath +Path to stored credentials that will be imported using Import-Clixml to allow for storing credentials using a secure method. + +.PARAMETER OutputType +Style of report that should be output. Defaults to JSON output but can be exported as a CSV or JSON. + +.PARAMETER OutputPath +Path to where the report should be saved. + +.PARAMETER Organization +Optional metadata that can be included in the returned results. + +.PARAMETER Role +Optional metadata that can be included in the returned results. + +.PARAMETER UpdateWindow +Optional metadata that can be included in the returned results. + +.NOTES + Version: 1.0 + Author: Tyler Hale + Creation Date: 2021.09.14 + +#> + +[CmdletBinding(DefaultParameterSetName = 'Local')] +param ( + [Parameter(Mandatory = $true, ParameterSetName = "CnDefaultCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CnDefaultCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CnCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CnCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CnStoredCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CnStoredCredReport")] + [ValidateScript( { Test-Connection $_ -Count 2 } )] + [alias('Cn')] + [string[]] + $ComputerName, + + [Parameter(Mandatory = $true, ParameterSetName = "CsvDefaultCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvDefaultCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvStoredCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvStoredCredReport")] + [ValidateNotNullOrEmpty()] + [ValidateScript( { Test-Path -Path $_ } )] + [string] + $CsvPath, + + [Parameter(Mandatory = $true, ParameterSetName = "CnCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CnCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvCredReport")] + [ValidateNotNull()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty, + + [Parameter(Mandatory = $true, ParameterSetName = "CnStoredCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CnStoredCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvStoredCred")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvStoredCredReport")] + [ValidateNotNullOrEmpty()] + [ValidateScript( { Test-Path -Path $_ })] + [string] + $CredentialPath, + + [Parameter(Mandatory = $false, ParameterSetName = "LocalReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CnDefaultCredReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CnCredReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CnStoredCredReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CsvDefaultCredReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CsvCredReport")] + [Parameter(Mandatory = $false, ParameterSetName = "CsvStoredCredReport")] + [ValidateSet("CSV", "JSON", "HTML")] + [string] + $OutputType = "JSON", + + [Parameter(Mandatory = $true, ParameterSetName = "LocalReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CnDefaultCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CnCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CnStoredCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvDefaultCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvCredReport")] + [Parameter(Mandatory = $true, ParameterSetName = "CsvStoredCredReport")] + [string] + $OutputPath, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string] + $Organization, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string] + $Role, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string] + $UpdateWindow +) + +############################################### [Script Settings] ################################################ + +# Define Default Columns +[System.Collections.ArrayList]$Columns = @( + "Computer Name", + "Operating System", + "Operating System Build", + "Uptime", + "Recent Updates", + "Disk Space Utilization", + "Date Gathered" +) + +# Define optional columns that will be removed if not provided +[System.Collections.ArrayList]$OptionalColumns = @( + "Role" + "Organization" + "UpdateWindow" +) + +# HTML Header for table formatting +$Head = @" + + + +"@ + +################################################## [Functions] ################################################### + +function Format-DataSizes ($Size) { + switch ($Size) { + { $_ -ge 1PB } { "{0:#.#'P'}" -f ($Size / 1PB); break } + { $_ -ge 1TB } { "{0:#.#'T'}" -f ($Size / 1TB); break } + { $_ -ge 1GB } { "{0:#.#'G'}" -f ($Size / 1GB); break } + { $_ -ge 1MB } { "{0:#.#'M'}" -f ($Size / 1MB); break } + { $_ -ge 1KB } { "{0:#'K'}" -f ($Size / 1KB); break } + default { "{0}" -f ($Size) + "B" } + } +} + +function Format-TimeSpan { + process { + "{0:00} Day(s) {1:00}:{2:00}:{3:00}" -f $_.Days, $_.Hours, $_.Minutes, $_.Seconds + } +} + +function Add-RowEntry { + [CmdletBinding()] + param ( + $Table, + $Name = $OperatingSystem.CSName, + $Role, + $Organization = $OperatingSystem.Organization, + $OperatingSystem, + $LogicalDisk, + $Updates, + $UpdateWindow, + $DateGathered, + $OptionalColumns + ) + + # Create a row + $Row = $Table.NewRow() + + # Define the computer name + $Row."Computer Name" = $Name + $Row."Date Gathered" = $DateGathered + + # OS + if ($null -ne ($OperatingSystem)) { + $Row."Operating System" = "$($OperatingSystem.Caption)" + $Row."Operating System Build" = "$($OperatingSystem.Version)" + $Row."Uptime" = "$((New-TimeSpan -Start ($OperatingSystem.LastBootUpTime) -End $DataGatheredDate) | Format-TimeSpan)" + } + + # Disk + if ($null -ne ($LogicalDisk)) { + [string]$DiskUsage = "" + $LogicalDisk | ForEach-Object { + if ($null -ne $_.Size) { + $FreeSpace = Format-DataSizes -Size $_.FreeSpace + $TotalSize = Format-DataSizes -Size $_.Size + $DiskUsage += "$($_.DeviceID) $($TotalSize) Total \ $($FreeSpace) Free - {0:P0}`n" -f ($_.FreeSpace / $_.Size) + } + } + $Row."Disk Space Utilization" = $DiskUsage.TrimEnd() + } + + # Updates + if ($null -ne ($Updates)) { + $Row."Recent Updates" = "" + $RecentUpdates = ($Updates | Sort-Object InstalledOn -Descending) | Select-Object -First 3 + foreach ($Update in $RecentUpdates) { + $Row."Recent Updates" += "$(($Update.InstalledOn | Select-String -Pattern "(.*)(?= 00:00:00)").Matches.Value) - $($Update.HotFixID)`n" + } + } + + # Optional Columns + foreach ($OptionalColumn in $OptionalColumns) { + if ($Table.Columns -match "$OptionalColumn") { + $Row."$OptionalColumn" = (Get-Variable -Name "$OptionalColumn").Value + } + } + + # Add the row to the table + $Table.Rows.Add($Row) +} + +############################################# [Internal Processing] ############################################## + +# Change to the script's current directory to include support for relative paths +Set-Location $PSScriptRoot + +# Determine execution scope based on parameter set +Write-Verbose "ParameterSetName: $($PSCmdlet.ParameterSetName)" +switch -Wildcard ($PSCmdlet.ParameterSetName) { + "Local*" { + $Computers = [PSCustomObject]@{ + Name = $env:COMPUTERNAME + Role = $Role + Organization = $Organization + UpdateWindow = $UpdateWindow + } + } + "Cn*" { + # If the only computer name provided is the current machine, + # Switch back to using the Local parameter set and drop the + # ComputerName variable to avoid needing additional permissions + if ($ComputerName -ne $env:COMPUTERNAME) { + $Computers = foreach ($Computer in $ComputerName) { + [PSCustomObject]@{ + Name = $Computer + Role = $Role + Organization = $Organization + UpdateWindow = $UpdateWindow + } + } + } + else { + $Computers = [PSCustomObject]@{ + Name = $env:COMPUTERNAME + Role = $Role + Organization = $Organization + UpdateWindow = $UpdateWindow + } + Remove-Variable ComputerName + } + } + "Csv*" { + $Computers = Import-Csv -Path $CsvPath + [string[]]$ComputerName = $Computers.Name + } +} + +# Add Optional Columns if they exist +foreach ($OptionalColumn in $OptionalColumns) { + switch ($OptionalColumn) { + "Organization" { [int]$ColumnPosition = 1 } + "Role" { [int]$ColumnPosition = 1 } + Default { [int]$ColumnPosition = $Columns.Count } + } + + if ($null -ne $Computers."$($OptionalColumn)") { + if ('' -ne ($Computers."$($OptionalColumn)" | Out-String).Trim()) { + $Columns.Insert($ColumnPosition, "$OptionalColumn") + } + } +} + +# If using stored credentials, import the credentials for future use +if ($PSCmdlet.ParameterSetName -like "*StoredCred*") { + $Credential = Import-Clixml -Path $CredentialPath +} + +# Build Remote Parameters splat variable +$RemoteParameters = @{} + +if ($null -ne $ComputerName) { + Write-Verbose "Adding $ComputerName to Remote Parameters splat variable" + $RemoteParameters['ComputerName'] = $ComputerName + $RemoteParameters['Authentication'] = "Kerberos" +} + +if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { + Write-Verbose "Adding provided credentials to Remote Parameters splat variable" + $RemoteParameters['Credential'] = $Credential + $RemoteParameters['Authentication'] = "Kerberos" +} + +# Create Table object +$Table = New-Object system.Data.DataTable "Report" +foreach ($Column in $Columns) { + $Table.Columns.Add((New-Object system.Data.DataColumn $Column, ([string]))) + $Table.Columns[$Column].DefaultValue = "Unknown" +} + +################################################## [Execution] ################################################### + +# Gather Cim Data + +Write-Verbose "Started Data gathering: $(Get-Date -Format o)" +$CimMasterSession = New-CimSession @RemoteParameters + +$CimMasterData = @{} +$CimMasterData["OS"] = Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $CimMasterSession +$CimMasterData["Drives"] = Get-CimInstance -ClassName "Win32_LogicalDisk" -Namespace "root\CIMV2" -CimSession $CimMasterSession +$CimMasterData["Updates"] = Get-CimInstance -ClassName "Win32_QuickfixEngineering" -CimSession $CimMasterSession + +$DataGatheredDate = Get-Date -Format o + +Write-Verbose "Finished Data gathering: $DataGatheredDate" +Remove-CimSession -CimSession $CimMasterSession + +foreach ($Computer in ($Computers | Sort-Object Name)) { + Write-Verbose "Processing $($Computer.Name) - $(Get-Date -Format o)" + + # Add Optional Parameters to the row as needed + $OptionalParameters = @{"OptionalColumns" = $OptionalColumns } + foreach ($OptionalColumn in $OptionalColumns) { + if ($null, '' -ne $Computer."$($OptionalColumn)") { + $OptionalParameters["$($OptionalColumn)"] = $Computer."$($OptionalColumn)" + } + } + + # Created the row based on the provided data + # Local execution sets the PSComputerName as null + if ($null -ne $ComputerName) { + Add-RowEntry -Table $Table ` + -Name $Computer.Name ` + -OperatingSystem ($CimMasterData.OS | Where-Object { $_.PSComputerName -eq "$($Computer.Name)" }) ` + -LogicalDisk ($CimMasterData.Drives | Where-Object { $_.PSComputerName -eq "$($Computer.Name)" }) ` + -Updates ($CimMasterData.Updates | Where-Object { $_.PSComputerName -eq "$($Computer.Name)" }) ` + -DateGathered $DataGatheredDate ` + @OptionalParameters + } + else { + Add-RowEntry -Table $Table ` + -Name $Computer.Name ` + -OperatingSystem ($CimMasterData.OS | Where-Object { $null -eq $_.PSComputerName }) ` + -LogicalDisk ($CimMasterData.Drives | Where-Object { $null -eq $_.PSComputerName }) ` + -Updates ($CimMasterData.Updates | Where-Object { $null -eq $_.PSComputerName }) ` + -DateGathered $DataGatheredDate ` + @OptionalParameters + } +} + +if ($PSCmdlet.ParameterSetName -like "*Report*") { + switch ($OutputType) { + "CSV" { $Table | Export-Csv -Path $OutputPath -NoTypeInformation } + "JSON" { $Table | Select-Object * -ExcludeProperty ItemArray, Table, RowError, RowState, HasErrors | ConvertTo-Json | Out-File -FilePath $OutputPath } + "HTML" { $Table | Select-Object -Property $Columns | ConvertTo-HTML -Head $Head -Body "

System Status Update

Date Gathered: $DataGatheredDate

" | Set-Content $OutputPath } + } +} +else { + $Table +} + diff --git a/Images/Example-Default.png b/Images/Example-Default.png new file mode 100644 index 0000000000000000000000000000000000000000..634e500845ef2600931d43fecaa1ae5aae0944c4 GIT binary patch literal 10438 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 literal 0 HcmV?d00001 diff --git a/Images/Example-HTML.png b/Images/Example-HTML.png new file mode 100644 index 0000000000000000000000000000000000000000..7967524180626290f0f324f8635af62afc0f92e7 GIT binary patch literal 13929 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 1a9a1b4..34ce141 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,110 @@ # Get-SystemStatus -Gets various information related to a running system's status for reporting. +Gathers the follow information from a provided list of computers. +The collected data is then returned as a DataTable or can be exported to a variety of file formats. +Optional Metadata can be included to be included in the returned results/reports to assist in machine identification. -## Requirements +Collected Data: Computer Name, Operating System, Operating System Build, Uptime, Recent Updates, Disk Space Utilization, Date Gathered +Optional Metadata: Organization, Role, UpdateWindow ## Variables -| Variable | Required | Default | Choices | Description | -| -------- | -------- | ------- | ------- | ----------- | -| | | | | | +### ComputerName Set + +| Variable | Required | Default | Choices | Description | +| -------------- | -------- | ------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- | +| ComputerName | Yes | | | Specifies a computer or set of computers that should be queried for their status | + +### CsvPath Set + +| Variable | Required | Default | Choices | Description | +| -------------- | -------- | ------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- | +| CsvPath | Yes | | | Specifies a computer or set of computers that should be queried for their status | + +### Credential Set + +| Variable | Required | Default | Choices | Description | +| ---------- | -------- | ------- | ------- | ----------------------------------------------------------------------------------------------------- | +| Credential | Yes | | | Credentials used for connecting to the specified computers to gather the machine's status information | + +### CredentialPath Set + +| Variable | Required | Default | Choices | Description | +| -------------- | -------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------- | +| CredentialPath | Yes | | | Path to stored credentials that will be imported using Import-Clixml to allow for storing credentials using a secure method | + +### Report Set + +| Variable | Required | Default | Choices | Description | +| -------------- | -------- | ------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- | +| OutputType | No | JSON | CSV, JSON, HTML | Style of report that should be output | +| OutputPath | Yes | | | Path to where the report should be saved | + +### Common Variables + +| Variable | Required | Default | Choices | Description | +| -------------- | -------- | ------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- | +| Organization | No | | | Optional metadata that can be included in the returned results | +| Role | No | | | Optional metadata that can be included in the returned results | +| UpdateWindow | No | | | Optional metadata that can be included in the returned results | + +## Syntax + +```powershell +Get-SystemStatus.ps1 [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName -CredentialPath [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName -CredentialPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName -Credential [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName -Credential [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -ComputerName [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath -CredentialPath [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath -CredentialPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath -Credential [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath -Credential [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 -CsvPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` + +```powershell +Get-SystemStatus.ps1 [-OutputType ] -OutputPath [-Organization ] [-Role ] [-UpdateWindow ] [] +``` ## Example @@ -17,3 +113,7 @@ Gets various information related to a running system's status for reporting. See LICENSE file for full license information. ## Screenshots + +![Example Default Execution](Images/Example-Default.png?raw=true) + +![Example Default Execution](Images/Example-HTML.png?raw=true)