<# .SYNOPSIS Windows Device Health Audit with Auto-Elevation .DESCRIPTION Performs comprehensive system checks with automatic admin elevation when needed. Logs to: C:\Logs\DeviceAudit\AUDIT_[HOSTNAME]_[DATE].log .NOTES Version: 1.2 Author: Your Name .EXAMPLE # Basic check (non-admin): .\WindowsHealthAudit.ps1 .EXAMPLE # Full check (auto-elevates to admin if needed): .\WindowsHealthAudit.ps1 -Full #> param( [switch]$Full = $false ) #region Initial Setup # ------------------ $logDir = "C:\Logs\DeviceAudit" $logFile = "$logDir\AUDIT_$($env:COMPUTERNAME)_$(Get-Date -Format 'ddMMyyyy').log" # Create log directory if missing if (-not (Test-Path $logDir)) { New-Item -Path $logDir -ItemType Directory -Force | Out-Null } # Clear previous log if (Test-Path $logFile) { Clear-Content $logFile } #endregion #region Logging Function # --------------------- function Write-Log { param ( [string]$Message, [string]$Level = "INFO" ) $timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss" $logEntry = "$timestamp $Level`: $Message" Write-Output $logEntry $logEntry | Out-File -FilePath $logFile -Append -Encoding UTF8 } #endregion #region Self-Elevation # ------------------- $isAdmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544') if ($Full -and (-not $isAdmin)) { Write-Host "Re-launching as administrator..." -ForegroundColor Yellow try { $scriptPath = $MyInvocation.MyCommand.Path Start-Process pwsh -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -Full" -Verb RunAs -WindowStyle Hidden exit } catch { Write-Host "Failed to elevate! Running in basic mode." -ForegroundColor Red $Full = $false } } #endregion #region Main Audit # --------------- Write-Log "=== WINDOWS DEVICE HEALTH AUDIT ===" Write-Log "Host: $($env:COMPUTERNAME)" Write-Log "User: $($env:USERNAME)" Write-Log "Mode: $(if ($Full) {'FULL (Admin)'} else {'BASIC (Non-Admin)'})" Write-Log "Date: $(Get-Date -Format 'dd-MM-yyyy HH:mm:ss')" Write-Log "" # 1. System Information Write-Log "=== SYSTEM INFORMATION ===" $os = Get-CimInstance Win32_OperatingSystem $computer = Get-CimInstance Win32_ComputerSystem $uptime = (Get-Date) - $os.LastBootUpTime Write-Log "OS: $($os.Caption) (Build: $($os.BuildNumber))" Write-Log "Uptime: $($uptime.Days)d $($uptime.Hours)h $($uptime.Minutes)m" Write-Log "Manufacturer: $($computer.Manufacturer)" Write-Log "Model: $($computer.Model)" Write-Log "RAM: $([math]::Round($computer.TotalPhysicalMemory / 1GB, 2)) GB" Write-Log "" # 2. Performance Metrics Write-Log "=== PERFORMANCE ===" $cpuLoad = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average $memory = Get-CimInstance Win32_OperatingSystem $usedMem = [math]::Round(($memory.TotalVisibleMemorySize - $memory.FreePhysicalMemory) / 1MB, 2) $totalMem = [math]::Round($memory.TotalVisibleMemorySize / 1MB, 2) Write-Log "CPU Load: $cpuLoad%" Write-Log "Memory Usage: $usedMem/$totalMem GB ($([math]::Round(($usedMem/$totalMem)*100))% used)" Write-Log "" # 3. Disk Information Write-Log "=== DISK STORAGE ===" Get-CimInstance Win32_LogicalDisk -Filter "DriveType = 3" | ForEach-Object { $freeGB = [math]::Round($_.FreeSpace / 1GB, 2) $totalGB = [math]::Round($_.Size / 1GB, 2) $pctUsed = [math]::Round(($totalGB - $freeGB) / $totalGB * 100, 2) if ($pctUsed -gt 90) { Write-Log "WARNING: $($_.DeviceID) low space: $freeGB GB free ($pctUsed% used)" -Level "WARNING" } else { Write-Log "$($_.DeviceID): $freeGB GB free of $totalGB GB ($pctUsed% used)" } } Write-Log "" # 4. Admin-Only Checks if ($Full) { Write-Log "=== ADMIN CHECKS ===" # Disk Health (SMART) try { $disks = Get-PhysicalDisk | Select-Object FriendlyName, HealthStatus, OperationalStatus $disks | ForEach-Object { if ($_.HealthStatus -ne "Healthy") { Write-Log "Disk health alert: $($_.FriendlyName) is $($_.HealthStatus)" -Level "ERROR" } else { Write-Log "Disk health: $($_.FriendlyName) is Healthy" } } } catch { Write-Log "WARNING: Could not retrieve disk health data" -Level "WARNING" } Write-Log "" # BitLocker Status if (Get-Command -Name Get-BitLockerVolume -ErrorAction SilentlyContinue) { $bitlocker = Get-BitLockerVolume | Where-Object { $_.VolumeType -eq "OperatingSystem" } if ($bitlocker.ProtectionStatus -eq "On") { Write-Log "BitLocker: Enabled ($($bitlocker.EncryptionPercentage)% encrypted)" } else { Write-Log "WARNING: BitLocker is not enabled on OS drive" -Level "WARNING" } } Write-Log "" } #endregion #region Common Checks # ------------------ # 5. Windows Updates Write-Log "=== UPDATES ===" $lastUpdate = Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1 Write-Log "Last Update: $($lastUpdate.HotFixID) on $($lastUpdate.InstalledOn)" Write-Log "" # 6. Security Status Write-Log "=== SECURITY ===" $defender = Get-MpComputerStatus if ($defender.AntivirusEnabled) { Write-Log "Windows Defender: Active" } else { Write-Log "ERROR: Windows Defender is disabled" -Level "ERROR" } Write-Log "" # 7. Event Log Errors Write-Log "=== CRITICAL EVENTS (24h) ===" $criticalEvents = Get-WinEvent -FilterHashtable @{ LogName = 'System','Application' Level = 1,2 StartTime = (Get-Date).AddDays(-1) } -MaxEvents 5 -ErrorAction SilentlyContinue if ($criticalEvents) { $criticalEvents | ForEach-Object { Write-Log "Event $($_.Id) [$($_.ProviderName)]: $($_.Message)" -Level "ERROR" } } else { Write-Log "No critical events found" } #endregion #region Completion # --------------- Write-Log "" Write-Log "=== AUDIT COMPLETE ===" Write-Log "Mode: $(if ($Full) {'FULL (Admin)'} else {'BASIC (Non-Admin)'})" Write-Log "Log saved to: $logFile" # Open log file if running interactively if ($Host.Name -match "ConsoleHost") { Invoke-Item $logFile } #endregion