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 0000000..634e500
Binary files /dev/null and b/Images/Example-Default.png differ
diff --git a/Images/Example-HTML.png b/Images/Example-HTML.png
new file mode 100644
index 0000000..7967524
Binary files /dev/null and b/Images/Example-HTML.png differ
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)