diff --git a/scripts_wip/Win_Battery_Capacity_Check.ps1 b/scripts_wip/Win_Battery_Capacity_Check.ps1 new file mode 100644 index 00000000..f1cb0baf --- /dev/null +++ b/scripts_wip/Win_Battery_Capacity_Check.ps1 @@ -0,0 +1,53 @@ +<# +.Synopsis + Checks the battery full charge capacity VS the design capacity +.DESCRIPTION + This was written specifically for use as a "Script Check" in mind, where it the output is deliberaly light unless a warning or error condition is found that needs more investigation. + + If the total full charge capacity is less than the minimum capacity amount, an error is returned. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $false)] + [int]#The minimum battery full charge capacity (as a percentage of design capacity by default). Defaults to 85 percent. + $minimumBatteryCapacity = 85, + + [Parameter(Mandatory = $false)] + [switch]#Set the check condition to absolute mWh values instead of a percentage + $absoluteValues +) + +try{ + $searcher = New-Object System.Management.ManagementObjectSearcher("root\wmi","SELECT * FROM BatteryStaticData") + $batteryStatic = $searcher.Get() + #CIM approach threw errors when Get-WMIObject did not - WMI approach is not available in PSv7, so took .NET approach + $batteryCharge = Get-CimInstance -Namespace "root\wmi" -ClassName "BatteryFullChargedCapacity" -ErrorAction Stop +} catch { + Write-Output "No battery detected" + exit 0 +} + +if (-not $batteryStatic -or -not $batteryCharge) { + Write-Output "No battery detected" + exit 0 +} + +$chargeCapacity = $batteryCharge.FullChargedCapacity +$designCapacity = $batteryStatic.DesignedCapacity + +$available = [math]::Round(($chargeCapacity / $designCapacity) * 100,2) +$label = "%" +if ($absoluteValues) { + $available = $chargeCapacity + $label = "mWh" +} + +If($available -le $minimumBatteryCapacity) +{ + Write-Output "The battery needs investigating. Full charge capacity is below the threshold of $minimumBatteryCapacity $label ($available $label available of design capacity $designCapacity mWh." + Exit 1 +} else { + Write-Output "The battery is reporting ok. Full charge capacity is above the threshold of $minimumBatteryCapacity $label ($available $label available of design capacity $designCapacity mWh." + Exit 0 +} \ No newline at end of file diff --git a/scripts_wip/Win_CPU_Uptime_Check.ps1 b/scripts_wip/Win_CPU_Uptime_Check.ps1 new file mode 100644 index 00000000..1fb55d11 --- /dev/null +++ b/scripts_wip/Win_CPU_Uptime_Check.ps1 @@ -0,0 +1,26 @@ +<# +.Synopsis + Checks Uptime of the computer +.DESCRIPTION + This was written specifically for use as a "Script Check" in mind, where it the output is deliberaly light unless a warning or error condition is found that needs more investigation. + + If the totalhours of uptime of the computer is greater than or equal to the warning limit, an error is returned. +#> + +[cmdletbinding()] +Param( + [Parameter(Mandatory = $false)] + [int]#Warn if the uptime total hours is over this limit. Defaults to 2.5 days. + $maximumUptimeHoursWarningLimit = 60 +) + +$uptime = (get-Date) - (Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime) + #v7 introduces Get-Uptime, but using WMI is backwards compatiable with v5 + +If($uptime.TotalHours -ge $maximumUptimeHoursWarningLimit){ + "Uptime is over threshold ($($uptime.TotalHours)/$maximumUptimeHoursWarningLimit)" + Exit 1 +} + +"Uptime is below threshold ($($uptime.TotalHours)/$maximumUptimeHoursWarningLimit)" +Exit 0 \ No newline at end of file diff --git a/scripts_wip/Win_Disk_HealthCheck.ps1 b/scripts_wip/Win_Disk_HealthCheck.ps1 new file mode 100644 index 00000000..24993dc4 --- /dev/null +++ b/scripts_wip/Win_Disk_HealthCheck.ps1 @@ -0,0 +1,92 @@ +<# +.Synopsis + Outputs Drive Health +.DESCRIPTION + This was written specifically for use as a "Script Check" in mind, where it the output is deliberaly light unless a warning or error condition is found that needs more investigation. + + Uses the Windows Storage Reliabilty Counters first (the information behind Settings - Storage - Disks & Volumes - %DiskID% - Drive health) to report on drive health. + + Will exit if running on a virtual machine. + +.NOTES + Learing taken from "Win_Disk_SMART2.ps1" by nullzilla, and modified by: redanthrax +#> + +# Requires -Version 5.0 +# Requires -RunAsAdministrator +[cmdletbinding()] +Param( + [Parameter(Mandatory = $false)] + [int]#Warn if the temperature (in degrees C) is over this limit + $TemperatureWarningLimit = 55, + + [Parameter(Mandatory = $false)] + [int]#Warn if the "wear" of the drive (as a percentage) is above this + $maximumWearAllowance = 20, + + [Parameter(Mandatory = $false)] + [switch]#Outputs a full report, instead of warnings only + $fullReport +) + +BEGIN { + # If this is a virtual machine, we don't need to continue + $Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem' + if ($Computer.Model -like 'Virtual*') { + exit + } + } + +PROCESS { + Try{ + #Using Windows Storage Reliabilty Counters first (the information behind Settings - Storage - Disks & Volumes - %DiskID% - Drive health) + $physicalDisks = Get-PhysicalDisk -ErrorAction Stop + $storageResults = @() + foreach ($disk in $physicalDisks) { + $reliabilityCounter = $null + try { + $reliabilityCounter = $disk | Get-StorageReliabilityCounter -ErrorAction Stop + } + catch { + Write-Error "No Storage Reliability Counter for '$($disk.FriendlyName)'. This usually means the driver/controller isn't exposing it." + } + + $storageResults += [pscustomobject]@{ + FriendlyName = $disk.FriendlyName + SerialNumber = $disk.SerialNumber + BusType = $disk.BusType + HealthStatus = $disk.HealthStatus + OperationalStatus = ($disk.OperationalStatus -join ", ") + Temperature = $reliabilityCounter.Temperature + Wear = $reliabilityCounter.Wear + ReadErrorsTotal = $reliabilityCounter.ReadErrorsTotal + WriteErrorsTotal = $reliabilityCounter.WriteErrorsTotal + ReallocatedSectors = $reliabilityCounter.ReallocatedSectors + PowerOnHours = $reliabilityCounter.PowerOnHours + } + + If( + $disk.HealthStatus.ToLower() -ne "healthy" -or + ($disk.OperationalStatus | Where-Object -FilterScript { $_.ToLower() -ne "ok" }) -or + $reliabilityCounter.Wear -ge $maximumWearAllowance -or + $reliabilityCounter.Temperature -ge $TemperatureWarningLimit + ){ + Write-Error -Message "$($disk.FriendlyName) has conditions that require investigation. $storageResults" + } + } + + If($fullReport) { $storageResults } + + } catch { + Write-Error -Message "Get-PhysicalDisk failed. This can happen on older OS builds or restricted environments." + } +} + +END{ + if ($error) { + Write-Output $error + exit 1 + } + Write-Output "All drives report as healthy" + Exit 0 +} \ No newline at end of file diff --git a/scripts_wip/Win_Disk_SMART.ps1 b/scripts_wip/Win_Disk_SMART.ps1 index fa5ea446..c255e5a3 100644 --- a/scripts_wip/Win_Disk_SMART.ps1 +++ b/scripts_wip/Win_Disk_SMART.ps1 @@ -1,126 +1,215 @@ -# From nullzilla - -# Requires -Version 3.0 +# Requires -Version 4.0 # Requires -RunAsAdministrator - -# If this is a virtual machine, we don't need to continue -$Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem' -if ($Computer.Model -like 'Virtual*') { - exit -} - -$disks = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | Select-Object 'InstanceName') - -$Warnings = @() - -foreach ($disk in $disks.InstanceName) { - # Retrieve SMART data - $SmartData = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_ATAPISMartData' | Where-Object 'InstanceName' -eq $disk) - - [Byte[]]$RawSmartData = $SmartData | Select-Object -ExpandProperty 'VendorSpecific' - - # Starting at the third number (first two are irrelevant) - # get the relevant data by iterating over every 12th number - # and saving the values from an offset of the SMART attribute ID - [PSCustomObject[]]$Output = for ($i = 2; $i -lt $RawSmartData.Count; $i++) { - if (0 -eq ($i - 2) % 12 -and $RawSmartData[$i] -ne 0) { - # Construct the raw attribute value by combining the two bytes that make it up - [Decimal]$RawValue = ($RawSmartData[$i + 6] * [Math]::Pow(2, 8) + $RawSmartData[$i + 5]) - - $InnerOutput = [PSCustomObject]@{ - DiskID = $disk - ID = $RawSmartData[$i] - #Flags = $RawSmartData[$i + 1] - #Value = $RawSmartData[$i + 3] - Worst = $RawSmartData[$i + 4] - RawValue = $RawValue + +<# +.Synopsis + Outputs SMART data +.DESCRIPTION + Checks the system for a comprehensive list of SMART data. + Will exit on finding a virtual machine. + Use the -Warning flag to only get warnings instead of all data. + Use the -Pretty flag to make the output pretty. +.EXAMPLE + Win_Hardware_Disk_SMART +.EXAMPLE + Win_Hardware_Disk_SMART -Warning +.EXAMPLE + Win_Hardware_Disk_SMART -Warning -Pretty +.NOTES + Version: 1.0 + Author: nullzilla + Modified by: redanthrax +#> + +Param( + [Parameter(Mandatory = $false)] + [switch]$Warning, + + [Parameter(Mandatory = $false)] + [switch]$Pretty +) + +function Win_Hardware_Disk_SMART { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false)] + [switch]$Warning, + + [Parameter(Mandatory = $false)] + [switch]$Pretty + ) + + Begin { + # If this is a virtual machine, we don't need to continue + $Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem' + if ($Computer.Model -like 'Virtual*') { + exit + } + } + + Process { + Try { + $data = @{} + $disks = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | Select-Object 'InstanceName') + foreach ($disk in $disks.InstanceName) { + $SmartData = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_ATAPISMartData' | Where-Object 'InstanceName' -eq $disk) + [Byte[]]$RawSmartData = $SmartData | Select-Object -ExpandProperty 'VendorSpecific' + # Starting at the third number (first two are irrelevant) + # get the relevant data by iterating over every 12th number + # and saving the values from an offset of the SMART attribute ID + [PSCustomObject[]]$Output = for ($i = 2; $i -lt $RawSmartData.Count; $i++) { + if (0 -eq ($i - 2) % 12 -and $RawSmartData[$i] -ne 0) { + # Construct the raw attribute value by combining the two bytes that make it up + [Decimal]$RawValue = ($RawSmartData[$i + 6] * [Math]::Pow(2, 8) + $RawSmartData[$i + 5]) + + $InnerOutput = [PSCustomObject]@{ + ID = $RawSmartData[$i] + #Flags = $RawSmartData[$i + 1] + #Value = $RawSmartData[$i + 3] + Worst = $RawSmartData[$i + 4] + RawValue = $RawValue + } + + $InnerOutput + + } + } + + # View full table with + #$Output + + $diskData = [PSCustomObject]@{ + "Reallocated Sector Count" = ($Output | Where-Object ID -eq 5 | Select-Object -ExpandProperty RawValue) + "Spin Retry Count" = ($Output | Where-Object ID -eq 10 | Select-Object -ExpandProperty RawValue) + "Recalibration Retries" = ($Output | Where-Object ID -eq 11 | Select-Object -ExpandProperty RawValue) + "Used Reserved Block Count Total" = ($Output | Where-Object ID -eq 179 | Select-Object -ExpandProperty RawValue) + "Erase Failure Count" = ($Output | Where-Object ID -eq 182 | Select-Object -ExpandProperty RawValue) + "SATA Downshift Error Countor Runtime Bad Block" = ($Output | Where-Object ID -eq 183 | Select-Object -ExpandProperty RawValue) + "End-to-End error / IOEDC" = ($Output | Where-Object ID -eq 184 | Select-Object -ExpandProperty RawValue) + "Reported Uncorrectable Errors" = ($Output | Where-Object ID -eq 187 | Select-Object -ExpandProperty RawValue) + "Command Timeout" = ($Output | Where-Object ID -eq 188 | Select-Object -ExpandProperty RawValue) + "High Fly Writes" = ($Output | Where-Object ID -eq 189 | Select-Object -ExpandProperty RawValue) + "Temperature Celcius" = ($Output | Where-Object ID -eq 194 | Select-Object -ExpandProperty RawValue) + "Reallocation Event Count" = ($Output | Where-Object ID -eq 196 | Select-Object -ExpandProperty RawValue) + "Current Pending Sector Count" = ($Output | Where-Object ID -eq 197 | Select-Object -ExpandProperty RawValue) + "Uncorrectable Sector Count" = ($Output | Where-Object ID -eq 198 | Select-Object -ExpandProperty RawValue) + "UltraDMA CRC Error Count" = ($Output | Where-Object ID -eq 199 | Select-Object -ExpandProperty RawValue) + "Soft Read Error Rate" = ($Output | Where-Object ID -eq 201 | Select-Object -ExpandProperty RawValue) + "SSD Life Left" = ($Output | Where-Object ID -eq 231 | Select-Object -ExpandProperty RawValue) + "SSD Media Wear Out Indicator" = ($Output | Where-Object ID -eq 233 | Select-Object -ExpandProperty RawValue) + "Power On Hours" = ($Output | Where-Object ID -eq 9 | Select-Object -ExpandProperty RawValue) + "FailurePredictStatus" = ( + Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | + Select-Object PredictFailure, Reason + ) + "DiskDriveOkay" = ( + Get-CimInstance -ClassName 'Win32_DiskDrive' | + Select-Object -ExpandProperty Status + ) + "PhysicalDiskOkayAndHealthy" = ( + Get-PhysicalDisk | + Select-Object OperationalStatus, HealthStatus + ) + } + + $data.Add($disk, $diskData) + } + + #Only output warnings + if ($Warning) { + $warnings = @{} + $data.GetEnumerator() | Foreach-Object { + $diskWarnings = @{} + $_.Value.psobject.Members | ForEach-Object { + $item = $_ + switch ($_.Name) { + #Anything in this section will cause the script to return warning. + "Power On Hours" { if ($null -ne $item.Value -and $item.Value -gt 50000) { $diskWarnings.Add($item.Name, $item.Value) } } #Remove line or adjust 50000 number if you don't want Old drives to start returning Warnings + "Reallocated Sector Count" { if ($null -ne $item.Value -and $item.Value -gt 1) { $diskWarnings.Add($item.Name, $item.Value) } } + "Recalibration Retries" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Used Reserved Block Count Total" { if ($null -ne $item.Value -and $item.Value -gt 1) { $diskWarnings.Add($item.Name, $item.Value) } } + "Erase Failure Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "SATA Downshift Error Countor Runtime Bad Block" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "End-to-End error / IOEDC" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Reported Uncorrectable Errors" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Command Timeout" { if ($null -ne $item.Value -and $item.Value -gt 2) { $diskWarnings.Add($item.Name, $item.Value) } } + "High Fly Writes" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Temperature Celcius" { if ($null -ne $item.Value -and $item.Value -gt 50) { $diskWarnings.Add($item.Name, $item.Value) } } + "Reallocation Event Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Current Pending Sector Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Uncorrectable Sector Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "UltraDMA CRC Error Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } + "Soft Read Error Rate" { if ($null -ne $item.Value -and $item.Value -lt 95) { $diskWarnings.Add($item.Name, $item.Value) } } + "SSD Life Left" { if ($null -ne $item.Value -and $item.Value -lt 50) { $diskWarnings.Add($item.Name, $item.Value) } } + "SSD Media Wear Out Indicator" { if ($null -ne $item.Value -and $item.Value -lt 50) { $diskWarnings.Add($item.Name, $item.Value) } } + "FailurePredictStatus" { if ($item.Value | Where-Object PredictFailure -ne $False) { $diskWarnings.Add($item.Name, $item.Value) } } + "DiskDriveOkay" { if ($null -ne $item.Value -and $item.Value -ne 'OK') { $diskWarnings.Add($item.Name, $item.Value) } } + "PhysicalDiskOkayAndHealthy" { if ($item.Value | Where-Object { ($_.OperationalStatus -ne 'OK') -or ($_.HealthStatus -ne 'Healthy') }) { $diskWarnings.Add($item.Name, $item.Value) } } + } + } + + if ($diskWarnings.Count -gt 0) { + $warnings.Add($_.Key, $diskWarnings) + } + } + + if ($warnings.Count -gt 0) { + if ($Pretty) { + foreach ($key in $warnings.Keys) { + Write-Output "Disk: $key" + Write-Output $warnings[$key] + } + } + else { + $warnings + } + Write-Output "Done" + Exit 1 + } + } + else { + if ($Pretty) { + foreach ($key in $data.Keys) { + Write-Output "Disk: $key" + Write-Output $data[$key] + } + } + else { + $data + } } - - $InnerOutput + } + + Catch { + $exception = $_.Exception + Write-Output "Error: $exception" + Write-Output "Done" + Exit 1 } } - - # Reallocated Sectors Count - $Warnings += $Output | Where-Object ID -eq 5 | Where-Object RawValue -gt 1 | Format-Table - - # Spin Retry Count - $Warnings += $Output | Where-Object ID -eq 10 | Where-Object RawValue -ne 0 | Format-Table - - # Recalibration Retries - $Warnings += $Output | Where-Object ID -eq 11 | Where-Object RawValue -ne 0 | Format-Table - - # Used Reserved Block Count Total - $Warnings += $Output | Where-Object ID -eq 179 | Where-Object RawValue -gt 1 | Format-Table - - # Erase Failure Count - $Warnings += $Output | Where-Object ID -eq 182 | Where-Object RawValue -ne 0 | Format-Table - - # SATA Downshift Error Count or Runtime Bad Block - $Warnings += $Output | Where-Object ID -eq 183 | Where-Object RawValue -ne 0 | Format-Table - - # End-to-End error / IOEDC - $Warnings += $Output | Where-Object ID -eq 184 | Where-Object RawValue -ne 0 | Format-Table - - # Reported Uncorrectable Errors - $Warnings += $Output | Where-Object ID -eq 187 | Where-Object RawValue -ne 0 | Format-Table - - # Command Timeout - $Warnings += $Output | Where-Object ID -eq 188 | Where-Object RawValue -gt 2 | Format-Table - - # High Fly Writes - $Warnings += $Output | Where-Object ID -eq 189 | Where-Object RawValue -ne 0 | Format-Table - - # Temperature Celcius - $Warnings += $Output | Where-Object ID -eq 194 | Where-Object RawValue -gt 50 | Format-Table - - # Reallocation Event Count - $Warnings += $Output | Where-Object ID -eq 196 | Where-Object RawValue -ne 0 | Format-Table - - # Current Pending Sector Count - $Warnings += $Output | Where-Object ID -eq 197 | Where-Object RawValue -ne 0 | Format-Table - - # Uncorrectable Sector Count - $Warnings += $Output | Where-Object ID -eq 198 | Where-Object RawValue -ne 0 | Format-Table - - # UltraDMA CRC Error Count - $Warnings += $Output | Where-Object ID -eq 199 | Where-Object RawValue -ne 0 | Format-Table - - # Soft Read Error Rate - $Warnings += $Output | Where-Object ID -eq 201 | Where-Object Worst -lt 95 | Format-Table - - # SSD Life Left - $Warnings += $Output | Where-Object ID -eq 231 | Where-Object Worst -lt 50 | Format-Table - - # SSD Media Wear Out Indicator - $Warnings += $Output | Where-Object ID -eq 233 | Where-Object Worst -lt 50 | Format-Table - + + End { + if ($Error) { + if ($Error -match "Not supported") { + Write-Output "You may need to switch from ACHI to RAID/RST mode, see the link for how to do this non-destructively: https://www.top-password.com/blog/switch-from-raid-to-ahci-without-reinstalling-windows/" + } + + Write-Output $Error + Write-Output "Done" + exit 1 + } + Write-Output "Done" + Exit 0 + } } - -$Warnings += Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | -Select-Object InstanceName, PredictFailure, Reason | -Where-Object { $_.PredictFailure -ne $False } | Format-Table - -$Warnings += Get-CimInstance -ClassName 'Win32_DiskDrive' | -Select-Object Model, SerialNumber, Name, Size, Status | -Where-Object { $_.status -ne 'OK' } | Format-Table - -$Warnings += Get-PhysicalDisk | -Select-Object FriendlyName, Size, MediaType, OperationalStatus, HealthStatus | -Where-Object { $_.OperationalStatus -ne 'OK' -or $_.HealthStatus -ne 'Healthy' } | Format-Table - -if ($Warnings) { - $Warnings = $warnings | Out-String - $Warnings - Write-Host "$Warnings" - Exit 1 + +if (-not(Get-Command 'Win_Hardware_Disk_SMART' -errorAction SilentlyContinue)) { + . $MyInvocation.MyCommand.Path } - -if ($Error) { - if ($Error -match "Not supported") { - $notsup = "You may need to switch from ACHI to RAID/RST mode, see the link for how to do this non-destructively: https://www.top-password.com/blog/switch-from-raid-to-ahci-without-reinstalling-windows/" - $notsup - } - Write-Host "$Error $notsup" - exit 1 + +$scriptArgs = @{ + Warning = $Warning + Pretty = $Pretty } - + +Win_Hardware_Disk_SMART @scriptArgs \ No newline at end of file diff --git a/scripts_wip/Win_Disk_SMART2.ps1 b/scripts_wip/Win_Disk_SMART2.ps1 deleted file mode 100644 index c255e5a3..00000000 --- a/scripts_wip/Win_Disk_SMART2.ps1 +++ /dev/null @@ -1,215 +0,0 @@ -# Requires -Version 4.0 -# Requires -RunAsAdministrator - -<# -.Synopsis - Outputs SMART data -.DESCRIPTION - Checks the system for a comprehensive list of SMART data. - Will exit on finding a virtual machine. - Use the -Warning flag to only get warnings instead of all data. - Use the -Pretty flag to make the output pretty. -.EXAMPLE - Win_Hardware_Disk_SMART -.EXAMPLE - Win_Hardware_Disk_SMART -Warning -.EXAMPLE - Win_Hardware_Disk_SMART -Warning -Pretty -.NOTES - Version: 1.0 - Author: nullzilla - Modified by: redanthrax -#> - -Param( - [Parameter(Mandatory = $false)] - [switch]$Warning, - - [Parameter(Mandatory = $false)] - [switch]$Pretty -) - -function Win_Hardware_Disk_SMART { - [CmdletBinding()] - Param( - [Parameter(Mandatory = $false)] - [switch]$Warning, - - [Parameter(Mandatory = $false)] - [switch]$Pretty - ) - - Begin { - # If this is a virtual machine, we don't need to continue - $Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem' - if ($Computer.Model -like 'Virtual*') { - exit - } - } - - Process { - Try { - $data = @{} - $disks = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | Select-Object 'InstanceName') - foreach ($disk in $disks.InstanceName) { - $SmartData = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_ATAPISMartData' | Where-Object 'InstanceName' -eq $disk) - [Byte[]]$RawSmartData = $SmartData | Select-Object -ExpandProperty 'VendorSpecific' - # Starting at the third number (first two are irrelevant) - # get the relevant data by iterating over every 12th number - # and saving the values from an offset of the SMART attribute ID - [PSCustomObject[]]$Output = for ($i = 2; $i -lt $RawSmartData.Count; $i++) { - if (0 -eq ($i - 2) % 12 -and $RawSmartData[$i] -ne 0) { - # Construct the raw attribute value by combining the two bytes that make it up - [Decimal]$RawValue = ($RawSmartData[$i + 6] * [Math]::Pow(2, 8) + $RawSmartData[$i + 5]) - - $InnerOutput = [PSCustomObject]@{ - ID = $RawSmartData[$i] - #Flags = $RawSmartData[$i + 1] - #Value = $RawSmartData[$i + 3] - Worst = $RawSmartData[$i + 4] - RawValue = $RawValue - } - - $InnerOutput - - } - } - - # View full table with - #$Output - - $diskData = [PSCustomObject]@{ - "Reallocated Sector Count" = ($Output | Where-Object ID -eq 5 | Select-Object -ExpandProperty RawValue) - "Spin Retry Count" = ($Output | Where-Object ID -eq 10 | Select-Object -ExpandProperty RawValue) - "Recalibration Retries" = ($Output | Where-Object ID -eq 11 | Select-Object -ExpandProperty RawValue) - "Used Reserved Block Count Total" = ($Output | Where-Object ID -eq 179 | Select-Object -ExpandProperty RawValue) - "Erase Failure Count" = ($Output | Where-Object ID -eq 182 | Select-Object -ExpandProperty RawValue) - "SATA Downshift Error Countor Runtime Bad Block" = ($Output | Where-Object ID -eq 183 | Select-Object -ExpandProperty RawValue) - "End-to-End error / IOEDC" = ($Output | Where-Object ID -eq 184 | Select-Object -ExpandProperty RawValue) - "Reported Uncorrectable Errors" = ($Output | Where-Object ID -eq 187 | Select-Object -ExpandProperty RawValue) - "Command Timeout" = ($Output | Where-Object ID -eq 188 | Select-Object -ExpandProperty RawValue) - "High Fly Writes" = ($Output | Where-Object ID -eq 189 | Select-Object -ExpandProperty RawValue) - "Temperature Celcius" = ($Output | Where-Object ID -eq 194 | Select-Object -ExpandProperty RawValue) - "Reallocation Event Count" = ($Output | Where-Object ID -eq 196 | Select-Object -ExpandProperty RawValue) - "Current Pending Sector Count" = ($Output | Where-Object ID -eq 197 | Select-Object -ExpandProperty RawValue) - "Uncorrectable Sector Count" = ($Output | Where-Object ID -eq 198 | Select-Object -ExpandProperty RawValue) - "UltraDMA CRC Error Count" = ($Output | Where-Object ID -eq 199 | Select-Object -ExpandProperty RawValue) - "Soft Read Error Rate" = ($Output | Where-Object ID -eq 201 | Select-Object -ExpandProperty RawValue) - "SSD Life Left" = ($Output | Where-Object ID -eq 231 | Select-Object -ExpandProperty RawValue) - "SSD Media Wear Out Indicator" = ($Output | Where-Object ID -eq 233 | Select-Object -ExpandProperty RawValue) - "Power On Hours" = ($Output | Where-Object ID -eq 9 | Select-Object -ExpandProperty RawValue) - "FailurePredictStatus" = ( - Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | - Select-Object PredictFailure, Reason - ) - "DiskDriveOkay" = ( - Get-CimInstance -ClassName 'Win32_DiskDrive' | - Select-Object -ExpandProperty Status - ) - "PhysicalDiskOkayAndHealthy" = ( - Get-PhysicalDisk | - Select-Object OperationalStatus, HealthStatus - ) - } - - $data.Add($disk, $diskData) - } - - #Only output warnings - if ($Warning) { - $warnings = @{} - $data.GetEnumerator() | Foreach-Object { - $diskWarnings = @{} - $_.Value.psobject.Members | ForEach-Object { - $item = $_ - switch ($_.Name) { - #Anything in this section will cause the script to return warning. - "Power On Hours" { if ($null -ne $item.Value -and $item.Value -gt 50000) { $diskWarnings.Add($item.Name, $item.Value) } } #Remove line or adjust 50000 number if you don't want Old drives to start returning Warnings - "Reallocated Sector Count" { if ($null -ne $item.Value -and $item.Value -gt 1) { $diskWarnings.Add($item.Name, $item.Value) } } - "Recalibration Retries" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Used Reserved Block Count Total" { if ($null -ne $item.Value -and $item.Value -gt 1) { $diskWarnings.Add($item.Name, $item.Value) } } - "Erase Failure Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "SATA Downshift Error Countor Runtime Bad Block" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "End-to-End error / IOEDC" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Reported Uncorrectable Errors" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Command Timeout" { if ($null -ne $item.Value -and $item.Value -gt 2) { $diskWarnings.Add($item.Name, $item.Value) } } - "High Fly Writes" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Temperature Celcius" { if ($null -ne $item.Value -and $item.Value -gt 50) { $diskWarnings.Add($item.Name, $item.Value) } } - "Reallocation Event Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Current Pending Sector Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Uncorrectable Sector Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "UltraDMA CRC Error Count" { if ($null -ne $item.Value -and $item.Value -ne 0) { $diskWarnings.Add($item.Name, $item.Value) } } - "Soft Read Error Rate" { if ($null -ne $item.Value -and $item.Value -lt 95) { $diskWarnings.Add($item.Name, $item.Value) } } - "SSD Life Left" { if ($null -ne $item.Value -and $item.Value -lt 50) { $diskWarnings.Add($item.Name, $item.Value) } } - "SSD Media Wear Out Indicator" { if ($null -ne $item.Value -and $item.Value -lt 50) { $diskWarnings.Add($item.Name, $item.Value) } } - "FailurePredictStatus" { if ($item.Value | Where-Object PredictFailure -ne $False) { $diskWarnings.Add($item.Name, $item.Value) } } - "DiskDriveOkay" { if ($null -ne $item.Value -and $item.Value -ne 'OK') { $diskWarnings.Add($item.Name, $item.Value) } } - "PhysicalDiskOkayAndHealthy" { if ($item.Value | Where-Object { ($_.OperationalStatus -ne 'OK') -or ($_.HealthStatus -ne 'Healthy') }) { $diskWarnings.Add($item.Name, $item.Value) } } - } - } - - if ($diskWarnings.Count -gt 0) { - $warnings.Add($_.Key, $diskWarnings) - } - } - - if ($warnings.Count -gt 0) { - if ($Pretty) { - foreach ($key in $warnings.Keys) { - Write-Output "Disk: $key" - Write-Output $warnings[$key] - } - } - else { - $warnings - } - Write-Output "Done" - Exit 1 - } - } - else { - if ($Pretty) { - foreach ($key in $data.Keys) { - Write-Output "Disk: $key" - Write-Output $data[$key] - } - } - else { - $data - } - } - } - - Catch { - $exception = $_.Exception - Write-Output "Error: $exception" - Write-Output "Done" - Exit 1 - } - } - - End { - if ($Error) { - if ($Error -match "Not supported") { - Write-Output "You may need to switch from ACHI to RAID/RST mode, see the link for how to do this non-destructively: https://www.top-password.com/blog/switch-from-raid-to-ahci-without-reinstalling-windows/" - } - - Write-Output $Error - Write-Output "Done" - exit 1 - } - Write-Output "Done" - Exit 0 - } -} - -if (-not(Get-Command 'Win_Hardware_Disk_SMART' -errorAction SilentlyContinue)) { - . $MyInvocation.MyCommand.Path -} - -$scriptArgs = @{ - Warning = $Warning - Pretty = $Pretty -} - -Win_Hardware_Disk_SMART @scriptArgs \ No newline at end of file diff --git a/scripts_wip/Win_Disk_Space_Check.ps1 b/scripts_wip/Win_Disk_Space_Check.ps1 index 99a08eb6..17242a1a 100644 --- a/scripts_wip/Win_Disk_Space_Check.ps1 +++ b/scripts_wip/Win_Disk_Space_Check.ps1 @@ -5,34 +5,44 @@ Long description Checks all FileSystem drives for an amount of space specified (amount is converted to Gigabytes). .EXAMPLE - Win_Disk_Space_Check -Size 10 + Confirm-DiskSpaceAvailable -Size 10 .EXAMPLE - Win_Disk_Space_Check -Size 10 -Percent + Confirm-DiskSpaceAvailable -Size 10 -Percent .NOTES Version: 1.0 Author: redanthrax Creation Date: 2022-04-05 + Updated: Owen Conti 2025-12-12 #> Param( [Parameter(Mandatory)] - [int]$Size, + [int]#The minimum amount of GB that should be available + $Size, [Parameter(Mandatory = $false)] - [switch]$Percent -) + [switch]#Switches the Size to be a percentage instead of GB + $Percent, -#Script Version -$sScriptVersion = "1.0" + [Parameter(Mandatory = $false)] + [switch]#Writes a message out even when the drive has more than the minimum available amount. In other words, logs *every* time. + $outputSuccess +) -function Win_Disk_Space_Check { +function Confirm-DiskSpaceAvailable { [CmdletBinding()] Param( [Parameter(Mandatory)] - [int]$Size, + [int]#The minimum amount of GB that should be available + $Size, + + [Parameter(Mandatory = $false)] + [switch]#Switches the Size to be a percentage instead of GB + $Percent, [Parameter(Mandatory = $false)] - [switch]$Percent + [switch]#Writes a message out even when the drive has more than the minimum available amount. In other words, logs *every* time. + $outputSuccess ) Begin {} @@ -40,25 +50,27 @@ function Win_Disk_Space_Check { Process { Try { $errors = 0 - $drives = Get-PSDrive | Where-Object { $_.Provider.Name -eq "FileSystem" -and $_.Used -gt 0 } + $drives = Get-PSDrive | Where-Object { $_.Provider.Name -eq "FileSystem" -and $_.Used -gt 0 -and $_.Name.ToLower() -ne "temp" } foreach ($drive in $drives) { + [string]$label = "GB" + [double]$available = 0 if ($Percent) { #Percent flag is set - #Calculate percent of space left on drive - $remainingPercent = [math]::Round($drive.Used / ($drive.Free + $drive.Used)) - $name = $drive.Name - if ($Size -gt $remainingPercent) { - Write-Output "$remainingPercent% space remaining on $name." - $errors += 1 - } + #Calculate percent of free space left on drive + $available = [math]::Round(($drive.Free / ($drive.Free + $drive.Used)) * 100,2) + $label = "%" } else { - $free = [math]::Round($drive.Free / 1Gb, 2) - $name = $drive.Name - if ($Size -gt $free) { - Write-Output "${free}GB of space on $name." - $errors += 1 - } + $available = [math]::Round($drive.Free / 1Gb, 2) + } + + If($outputSuccess){ + Write-Output "$available $label space remaining on $($drive.Name)." + } + + if ($Size -gt $available) { + Write-Output "ERROR: $($drive.Name) is below the threshold of $size $label ($available available)." + $errors += 1 } } } @@ -74,18 +86,19 @@ function Win_Disk_Space_Check { Exit 1 } - Write-Output "All disk space checked and clear." + Write-Output "All disks have been checked and have more than or equal to $size $label space available." Exit 0 } } -if (-not(Get-Command 'Win_Disk_Space_Check' -errorAction SilentlyContinue)) { +if (-not(Get-Command 'Confirm-DiskSpaceAvailable' -errorAction SilentlyContinue)) { . $MyInvocation.MyCommand.Path } $scriptArgs = @{ Size = $Size Percent = $Percent + outputSuccess = $outputSuccess } -Win_Disk_Space_Check @scriptArgs \ No newline at end of file +Confirm-DiskSpaceAvailable @scriptArgs \ No newline at end of file diff --git a/scripts_wip/Win_RAM_Available_Check.ps1 b/scripts_wip/Win_RAM_Available_Check.ps1 new file mode 100644 index 00000000..503f2c82 --- /dev/null +++ b/scripts_wip/Win_RAM_Available_Check.ps1 @@ -0,0 +1,39 @@ +<# +.Synopsis + Checks the available amount of RAM on a computer +.DESCRIPTION + This was written specifically for use as a "Script Check" in mind, where it the output is deliberaly light unless a warning or error condition is found that needs more investigation. + + If the total available (free) amount of RAM is less than the warning limit, an error is returned. + +#> + +[cmdletbinding()] +Param( + [Parameter(Mandatory = $false)] + [double]#Warn if the amount of available RAM (defaults to GB) is below this limit. Defaults to 1 GB. + $minimumAvailableRAM = 1, + + [Parameter(Mandatory = $false)] + [switch]#Use percentage instead of absolute GB values + $percent +) + +$os = Get-CimInstance -ClassName Win32_OperatingSystem + +$available = [math]::Round(($os.FreePhysicalMemory * 1KB) / 1GB, 2) +$label = "GB" +if ($Percent) { + #Percent flag is set + #Calculate percent of free available RAM + $available = [math]::Round(($os.FreePhysicalMemory / $os.TotalVisibleMemorySize) * 100, 1) + $label = "%" +} + +If($minimumAvailableRAM -gt $available){ + Write-Output "Avalable RAM is below the threshold of $minimumAvailableRAM $label ($available $label available)." + Exit 1 +} else { + Write-Output "Avalable RAM is above the threshold of $minimumAvailableRAM $label ($available $label available)." + Exit 0 +} \ No newline at end of file