ict-autopilot.ps1
<#PSScriptInfo .VERSION 3.0.2 .GUID 1522f19a-667a-4638-8def-7d5590a61094 .AUTHOR a.twist@imperial.ac.uk .COMPANYNAME Imperial College London .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Enrols an ICT laptop into Autopilot, creates a CSV file for the hardware hash with various other tools #> ##### ## Imperial College London ## ----------------------- ## Enrolement script ## ##### ### # Install NuGet Provider silently if not present if (-not (Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction SilentlyContinue)) { Write-Host "Installing NuGet Provider..." Install-PackageProvider -Name NuGet -Force -Scope CurrentUser | Out-Null } Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing function Create-MainForm { $form = New-Object System.Windows.Forms.Form $form.Text = "ICT-Autopilot 3.0.2" $form.Size = New-Object System.Drawing.Size(500, 600) # Increased height to accommodate header $form.StartPosition = "CenterScreen" $form.BackColor = [System.Drawing.Color]::White # Add custom icon try { # Create temp directory if it doesn't exist if (!(test-path -path "c:\temp")) { new-item -path "c:\" -name "temp" -ItemType "directory" } invoke-webrequest https://ictautopilot.blob.core.windows.net/assets/win11.ico -outfile c:\temp\win11.ico $iconPath = "c:\temp\win11.ico" if (Test-Path $iconPath) { $form.Icon = New-Object System.Drawing.Icon($iconPath) } } catch { Write-Warning "Could not load custom icon: $_" } # Add serial number header $headerLabel = New-Object System.Windows.Forms.Label $headerLabel.Location = New-Object System.Drawing.Point(20, 20) $headerLabel.Size = New-Object System.Drawing.Size(440, 30) $headerLabel.Font = New-Object System.Drawing.Font("Segoe UI", 12, [System.Drawing.FontStyle]::Bold) $headerLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter # Get and display serial number try { $serial = Get-WmiObject win32_bios | Select-Object serialnumber -ExpandProperty serialnumber $headerLabel.Text = "Serial Number: $serial" } catch { $headerLabel.Text = "Serial Number: Unable to retrieve" } # Adjust other controls' positions to accommodate header $script:listBox = New-Object System.Windows.Forms.ListBox $script:listBox.Location = New-Object System.Drawing.Point(20, 60) # Moved down $script:listBox.Size = New-Object System.Drawing.Size(440, 200) $script:listBox.Font = New-Object System.Drawing.Font("Segoe UI", 10) # ...existing listbox items... $executeButton = New-Object System.Windows.Forms.Button $executeButton.Location = New-Object System.Drawing.Point(20, 280) # Moved down $executeButton.Size = New-Object System.Drawing.Size(440, 30) $executeButton.Text = "Execute Selected Option" $executeButton.Add_Click({ if ($script:listBox.SelectedItem) { Execute-Selection $script:listBox.SelectedItem } else { $script:outputBox.Text = "Please select an option from the list." } }) # Add options to the listbox [void]$script:listBox.Items.Add("1. Enroll your machine into Autopilot") [void]$script:listBox.Items.Add("2. Create Autopilot CSV file") [void]$script:listBox.Items.Add("3. Enroll Custom Device into Autopilot") [void]$script:listBox.Items.Add("4. Enroll Software Hub into Autopilot") [void]$script:listBox.Items.Add("5. Run Windows Update") [void]$script:listBox.Items.Add("6. Display System Information") [void]$script:listBox.Items.Add("7. Check Windows 11 Compatibility") [void]$script:listBox.Items.Add("8. Reset Device") [void]$script:listBox.Items.Add("9. Remove from Autopilot, Intune and Entra ID") [void]$script:listBox.Items.Add("10. Restart PC") $script:outputBox = New-Object System.Windows.Forms.RichTextBox $script:outputBox.Location = New-Object System.Drawing.Point(20, 330) # Moved down $script:outputBox.Size = New-Object System.Drawing.Size(440, 200) $script:outputBox.ReadOnly = $true $script:outputBox.BackColor = [System.Drawing.Color]::White $script:outputBox.Font = New-Object System.Drawing.Font("Segoe UI", 10) $form.Controls.Add($headerLabel) $form.Controls.Add($script:listBox) $form.Controls.Add($executeButton) $form.Controls.Add($script:outputBox) return $form } # Update the Update-Output function function Update-Output { param($message) $script:outputBox.Text = $message } function Execute-Selection { param($selection) switch -Wildcard ($selection) { "*1.*" { Enroll-Autopilot } "*2.*" { Enroll-Autopilot-csv } "*3.*" { Enroll-Autopilot-Custom } "*4.*" { Enroll-Autopilot-MTR } "*5.*" { Run-WindowsUpdate } "*6.*" { Get-SystemInfo } "*7.*" { Check-Windows11Compatibility } "*8.*" { Reset-Device } "*9.*" { Remove-DeviceFromCloud } "*10.*" { Restart-PCWithCountdown } default { Update-Output "Please select an option from the list." } } } function Check-Windows11Compatibility { try { $results = @() # Create temp directory if it doesn't exist if (!(test-path -path "c:\temp")) { new-item -path "c:\" -name "temp" -ItemType "directory" } # Download CPU compatibility lists Update-Output "Downloading CPU compatibility lists..." invoke-webrequest https://ictautopilot.blob.core.windows.net/win11compat/AMD-CPU.txt -outfile c:\temp\AMD-CPU.txt invoke-webrequest https://ictautopilot.blob.core.windows.net/win11compat/Intel-CPU.txt -outfile c:\temp\INTEL-CPU.txt invoke-webrequest https://ictautopilot.blob.core.windows.net/win11compat/snap-CPU.txt -outfile c:\temp\Snap-CPU.txt # Load CPU lists and get system info $listprocIntel = get-content "C:\temp\INTEL-CPU.txt" $listprocAMD = get-content "c:\temp\AMD-CPU.txt" $listprocSNAP = get-content "c:\temp\SNAP-CPU.txt" $info = Get-ComputerInfo $procs = (($info).CsProcessors).name $cpuCompatible = $false # Check CPU compatibility foreach ($proc in $procs) { if ($proc -like "*Intel*") { $cpuCompatible = $listprocIntel | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } elseif ($proc -like "*AMD*") { $cpuCompatible = $listprocAMD | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } else { $cpuCompatible = $listprocSNAP | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } } # Add CPU compatibility result $results += "CPU Model: $proc - $(if($cpuCompatible){'Pass'}else{'Fail'})" # ...existing checks... # Check RAM $ram = Get-WmiObject -Class Win32_ComputerSystem $ramGB = [math]::Round($ram.TotalPhysicalMemory / 1GB, 2) $ramCheck = $ramGB -ge 4 $results += "RAM: $ramGB GB (Minimum: 4 GB) - $(if($ramCheck){'Pass'}else{'Fail'})" # Check Storage $disk = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='C:'" $diskGB = [math]::Round($disk.Size / 1GB, 2) $diskCheck = $diskGB -ge 64 $results += "Storage: $diskGB GB (Minimum: 64 GB) - $(if($diskCheck){'Pass'}else{'Fail'})" # Check TPM try { $tpm = Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftTpm" -Class Win32_Tpm $tpmVersion = if ($tpm.SpecVersion -match "2.0") { "2.0" } else { "1.2 or lower" } $tpmCheck = $tpm.SpecVersion -match "2.0" $results += "TPM Version: $tpmVersion (Required: 2.0) - $(if($tpmCheck){'Pass'}else{'Fail'})" } catch { $results += "TPM: Not detected - Fail" $tpmCheck = $false } # Check Secure Boot $secureBootStatus = Confirm-SecureBootUEFI $results += "Secure Boot: $(if($secureBootStatus){'Enabled'}else{'Disabled'}) - $(if($secureBootStatus){'Pass'}else{'Fail'})" # Overall assessment (updated to include CPU compatibility) $compatible = $cpuCompatible -and $ramCheck -and $diskCheck -and $tpmCheck -and $secureBootStatus $output = "Windows 11 Compatibility Check:`n`n" $output += "Some Brand new CPUs may incorrectly flag as Not Compatible`n`n" $output += $results | ForEach-Object { "$_`n" } $output += "`nOverall Result: $(if($compatible){'Compatible with Windows 11'}else{'Not Compatible with Windows 11'})" Update-Output $output } catch { Update-Output "Error checking Windows 11 compatibility: $_" } } function Remove-DeviceFromCloud { try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to remove device from cloud services" return } # Show confirmation dialog $confirmation = [System.Windows.Forms.MessageBox]::Show( "Are you sure you want to remove this device from Autopilot, Intune, and Entra ID?`n`nThis action cannot be undone.", "Confirm Device Removal", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning ) if ($confirmation -eq [System.Windows.Forms.DialogResult]::No) { Update-Output "Device removal cancelled by user." return } Update-Output "Starting device removal process..." # Rest of the existing code... $serialNumber = Get-WmiObject win32_bios | Select-Object -ExpandProperty SerialNumber $deviceName = $env:COMPUTERNAME Update-Output "Installing required PowerShell modules..." Install-Module WindowsAutopilotIntune -Force -AllowClobber -Scope CurrentUser Install-Module Microsoft.Graph.Intune -Force -Scope CurrentUser Install-Module Microsoft.Graph.Identity.DirectoryManagement -Force -Scope CurrentUser Update-Output "Connecting to Microsoft Graph..." Connect-MgGraph -Scopes "Device.ReadWrite.All", "DeviceManagementServiceConfig.ReadWrite.All" # Show progress as each service is processed Update-Output "Step 1/3: Removing from Autopilot..." try { $autopilotDevice = Get-AutopilotDevice -serial $serialNumber if ($autopilotDevice) { Remove-AutopilotDevice -id $autopilotDevice.id Update-Output "Successfully removed from Autopilot" } else { Update-Output "Device not found in Autopilot" } } catch { Update-Output "Error removing from Autopilot: $_" } Update-Output "`nStep 2/3: Removing from Intune..." try { $intuneDevice = Get-MgDeviceManagementManagedDevice -Filter "serialNumber eq '$serialNumber'" if ($intuneDevice) { Remove-MgDeviceManagementManagedDevice -ManagedDeviceId $intuneDevice.Id Update-Output "Successfully removed from Intune" } else { Update-Output "Device not found in Intune" } } catch { Update-Output "Error removing from Intune: $_" } Update-Output "`nStep 3/3: Removing from Entra ID..." try { $aadDevice = Get-MgDevice -Filter "displayName eq '$deviceName'" if ($aadDevice) { Remove-MgDevice -DeviceId $aadDevice.Id Update-Output "Successfully removed from Entra ID" } else { Update-Output "Device not found in Entra ID" } } catch { Update-Output "Error removing from Entra ID: $_" } # Clean up local device state Update-Output "`nCleaning up local device state..." try { $dsregcmd = Start-Process "dsregcmd.exe" -ArgumentList "/leave" -PassThru -Wait if ($dsregcmd.ExitCode -eq 0) { Update-Output "It will take around 5 minutes to show this deletion in intune" } else { Update-Output "Warning: Local device state cleanup may not be complete" } } catch { Update-Output "Error cleaning local device state: $_" } # Final confirmation [System.Windows.Forms.MessageBox]::Show( "Device removal process completed. Please restart your device to complete the process.", "Removal Complete", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information ) } catch { Update-Output "Error in device removal process: $_" [System.Windows.Forms.MessageBox]::Show( "An error occurred during the removal process. Please check the output for details.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error ) } } function Restart-PCWithCountdown { try { # Check for admin privileges if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to restart the PC" return } Update-Output "System will restart in 5 seconds..." # Start countdown for ($i = 5; $i -gt 0; $i--) { Update-Output "Restarting in $i seconds..." Start-Sleep -Seconds 1 } # Initiate restart Restart-Computer -Force } catch { Update-Output "Error initiating restart: $_" } } function Test-AutopilotRequirements { [CmdletBinding()] param() $requirements = @{ OSVersion = $false OSEdition = $false TPM = $false AllPassed = $false } try { # Check Windows version Write-Host "Checking Windows version..." -ForegroundColor Cyan $osInfo = Get-WmiObject -Class Win32_OperatingSystem $buildNumber = [int]($osInfo.BuildNumber) $osCaption = $osInfo.Caption if ($buildNumber -ge 17134) { Write-Host "Windows build $buildNumber meets minimum requirement (17134)" -ForegroundColor Green $requirements.OSVersion = $true } else { Write-Host "Windows build $buildNumber does not meet minimum requirement (17134)" -ForegroundColor Red Write-Host "Please upgrade Windows to continue" -ForegroundColor Red } # Check Windows Edition Write-Host "`nChecking Windows Edition..." -ForegroundColor Cyan if ($osCaption -match "(Enterprise|Professional|Education|Pro)") { Write-Host "Windows edition ($osCaption) is supported" -ForegroundColor Green $requirements.OSEdition = $true } else { Write-Host "Windows edition ($osCaption) is not supported" -ForegroundColor Red Write-Host "Requires Enterprise, Professional, or Education edition" -ForegroundColor Red } # Check TPM 2.0 Write-Host "`nChecking TPM 2.0..." -ForegroundColor Cyan try { $tpm = Get-Tpm if ($tpm.TpmPresent) { if ($tpm.TpmReady) { $tpmVersion = $tpm.ManufacturerVersionFull20 if (-not ($tpmVersion.Contains("not supported"))) { Write-Host "TPM 2.0 is present and ready" -ForegroundColor Green $requirements.TPM = $true } else { Write-Host "TPM 2.0 is not supported on this device" -ForegroundColor Red } } else { Write-Host "TPM is present but not ready" -ForegroundColor Red } } else { Write-Host "No TPM found on this device" -ForegroundColor Red } } catch { Write-Host "Error checking TPM status: $_" -ForegroundColor Red } # Check if all requirements passed $requirements.AllPassed = $requirements.OSVersion -and $requirements.OSEdition -and $requirements.TPM # Final summary Write-Host "`nRequirements Summary:" -ForegroundColor Cyan Write-Host "Windows Version: $($requirements.OSVersion)" -ForegroundColor $(if ($requirements.OSVersion) { "Green" } else { "Red" }) Write-Host "Windows Edition: $($requirements.OSEdition)" -ForegroundColor $(if ($requirements.OSEdition) { "Green" } else { "Red" }) Write-Host "TPM 2.0: $($requirements.TPM)" -ForegroundColor $(if ($requirements.TPM) { "Green" } else { "Red" }) if ($requirements.AllPassed) { Write-Host "`nAll requirements met. Device is ready for Autopilot enrollment." -ForegroundColor Green } else { Write-Host "`nDevice does not meet all requirements for Autopilot enrollment." -ForegroundColor Red } return $requirements.AllPassed } catch { Write-Host "Error checking requirements: $_" -ForegroundColor Red return $false } } function Reset-Device { try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to reset the device" return } Update-Output "Resetting device..." $confirmation = [System.Windows.Forms.MessageBox]::Show("Are you sure you want to reset the device?", "Confirm Reset", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning) if ($confirmation -eq [System.Windows.Forms.DialogResult]::Yes) { # Reset the device systemreset -factoryreset } else { Update-Output "Device reset cancelled." } } catch { Update-Output "Error resetting device: $_" } } function Check-Enrol { try { # Initialize return object $enrollmentStatus = @{ IsEnrolled = $false SerialNumber = $null Error = $null } # Get WindowsAutopilotIntune module (and dependencies) Update-Output "Checking for WindowsAutopilotIntune module..." install-module WindowsAutopilotIntune -Force -AllowClobber -Confirm:$False -ErrorAction Stop $module = Import-Module WindowsAutopilotIntune -PassThru -ErrorAction Stop if (-not $module) { Update-Output "Installing WindowsAutopilotIntune module..." Install-Module WindowsAutopilotIntune -Force -AllowClobber -Confirm:$False -ErrorAction Stop Import-Module WindowsAutopilotIntune -Scope Global -ErrorAction Stop } update-output "Connecting to Microsoft Graph..." connect-mggraph # Get serial number Update-Output "Getting device serial number..." $serial = Get-WmiObject win32_bios -ErrorAction Stop | Select-Object serialnumber -ExpandProperty serialnumber if ([string]::IsNullOrEmpty($serial)) { throw "Unable to retrieve device serial number" } $enrollmentStatus.SerialNumber = $serial # Check Autopilot enrollment status Update-Output "Checking Autopilot enrollment status..." $enrolled = Get-AutopilotDevice -serial $serial -ErrorAction Stop if ($enrolled) { $enrollmentStatus.IsEnrolled = $true Update-Output "Device with serial number $serial is already enrolled in Autopilot" } else { Update-Output "Device with serial number $serial is not enrolled in Autopilot" } return $enrollmentStatus } catch { $errorMessage = "Error in Check-Enrol: $($_.Exception.Message)" Update-Output $errorMessage return @{ IsEnrolled = $false SerialNumber = $null Error = $errorMessage } } } function Enroll-Autopilot { # Check requirements first if (-not (Test-AutopilotRequirements)) { Write-Host "Cannot proceed with Autopilot enrollment - requirements not met." -ForegroundColor Red return } $enrollmentStatus = Check-Enrol if ($enrollmentStatus.Error) { Update-Output "Error checking enrollment: $($enrollmentStatus.Error)" return } if ($enrollmentStatus.IsEnrolled) { Update-Output "Device with serial number $($enrollmentStatus.SerialNumber) is already enrolled in Autopilot." return } try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to enroll in Autopilot" return } Update-Output "Installing Autopilot PowerShell module" Install-Script -Name Get-WindowsAutoPilotInfo -Force Update-Output "Enrolling in Autopilot, please wait..." Get-WindowsAutoPilotInfo -online -assign Update-Output "Device successfully enrolled in Autopilot. Please wait 15 minutes for the device to be registered." } catch { Update-Output "Error enrolling device: $_" } } function Enroll-Autopilot-Custom { # Check requirements first if (-not (Test-AutopilotRequirements)) { Write-Host "Cannot proceed with Autopilot enrollment - requirements not met." -ForegroundColor Red return } $enrollmentStatus = Check-Enrol if ($enrollmentStatus.Error) { Update-Output "Error checking enrollment: $($enrollmentStatus.Error)" return } if ($enrollmentStatus.IsEnrolled) { Update-Output "Device with serial number $($enrollmentStatus.SerialNumber) is already enrolled in Autopilot." return } try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to enroll in Autopilot" return } Update-Output "Installing Autopilot PowerShell module" Install-Script -Name Get-WindowsAutoPilotInfo -Force Update-Output "Enrolling Custom Device in Autopilot, please wait..." Get-WindowsAutoPilotInfo -GroupTag CUSTOM -Online -assign Update-Output "Custom Device successfully enrolled in Autopilot. Please wait 15 minutes for the device to be registered." } catch { Update-Output "Error enrolling device: $_" } } function Enroll-Autopilot-MTR { # Check requirements first if (-not (Test-AutopilotRequirements)) { Write-Host "Cannot proceed with Autopilot enrollment - requirements not met." -ForegroundColor Red return } $enrollmentStatus = Check-Enrol if ($enrollmentStatus.Error) { Update-Output "Error checking enrollment: $($enrollmentStatus.Error)" return } if ($enrollmentStatus.IsEnrolled) { Update-Output "Device with serial number $($enrollmentStatus.SerialNumber) is already enrolled in Autopilot." return } try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to enroll in Autopilot" return } Update-Output "Installing Autopilot PowerShell module" Install-Script -Name Get-WindowsAutoPilotInfo -Force Update-Output "Enrolling Surface Hub in Autopilot, please wait..." Get-WindowsAutoPilotInfo -GroupTag MTR -Online -assign Update-Output "Surface Hub successfully enrolled in Autopilot. Please wait 15 minutes for the device to be registered." } catch { Update-Output "Error enrolling device: $_" } } function Enroll-Autopilot-csv { try { # Check if running as admin if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to enroll in Autopilot" return } if (!(test-path -path "c:\temp")) { new-item -path "c:\" -name "temp" -ItemType "directory" update-output "Creating c:\temp" } update-output "Installing Autopilot Powershell module" Install-Script -Name Get-WindowsAutoPilotInfo -Force Update-output "Creating Autopilot csv in c:\temp please wait..." Get-WindowsAutoPilotInfo -OutputFile c:\temp\AutopilotHWID.csv Update-Output "Hardware hash saved to c:\temp\AutopilotHWID.csv" } catch { Update-Output "Error enrolling device: $_" } } function Run-WindowsUpdate { try { if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Update-Output "Please run as Administrator to perform Windows Update" return } # Install required module Update-Output "Installing required PowerShell modules..." Install-Module PSWindowsUpdate -Force Update-Output "PSWindowsUpdate module installed successfully." # Import module Update-Output "Importing PSWindowsUpdate module..." Import-Module PSWindowsUpdate Update-Output "Module imported successfully." # Check for updates Update-Output "Checking for Windows Updates..." $updates = Get-WindowsUpdate if ($updates.Count -eq 0) { Update-Output "No Windows Updates are available." return } Update-Output "Found $($updates.Count) update(s). Starting installation..." # Install updates with progress Get-WindowsUpdate -Install -AcceptAll -AutoReboot | ForEach-Object { Update-Output "Installing update: $($_.Title)`nStatus: $($_.Status)" } Update-Output "Windows Update completed successfully. The system may need to reboot to apply some updates." } catch { Update-Output "Error running Windows Update: $_" } } function Get-SystemInfo { try { $info = Get-ComputerInfo $OS = ($info).windowsproductname $cpu = Get-WmiObject -Class Win32_Processor $ram = [math]::Round((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2) $disk = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='C:'" $freeSpace = [math]::Round($disk.FreeSpace / 1GB, 2) $model = ($info).csmodel $bios = ($info).BiosSMBIOSBIOSVersion $locale = ($info).OsLanguage $serial = ($info).BiosSeralNumber $info = @" CPU: $($cpu.Name) RAM: $ram GB Free Disk Space: $freeSpace GB OS: $OS Model: $model BIOS Version: $bios Serial Number: $serial locale: $locale "@ Update-Output $info } catch { Update-Output "Error getting system information: $_" } } $form = Create-MainForm if ($form -is [System.Windows.Forms.Form]) { [void]$form.ShowDialog() } else { Write-Error "Failed to create the main form. Ensure the Create-MainForm function returns a valid System.Windows.Forms.Form object." } # SIG # Begin signature block # MIIRCAYJKoZIhvcNAQcCoIIQ+TCCEPUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUlY3uopc/rO65Ecd0kOHf7S5J # tr6ggg47MIIG7zCCBNegAwIBAgITIQAAAAQ+jdT+OF0JbAAAAAAABDANBgkqhkiG # 9w0BAQsFADCBzTExMC8GCSqGSIb3DQEJARYiaXQtc2VjdXJpdHktb2ZmaWNlckBp # bXBlcmlhbC5hYy51azELMAkGA1UEBhMCVUsxDzANBgNVBAgTBkxvbmRvbjEPMA0G # A1UEBxMGTG9uZG9uMSAwHgYDVQQKExdJbXBlcmlhbCBDb2xsZWdlIExvbmRvbjFH # MEUGA1UEAxM+SW1wZXJpYWwgQ29sbGVnZSBMb25kb24gUm9vdCBTZWN1cmUgQ2Vy # dGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAwHhcNMjAwMjA0MTQ1ODE5WhcNNDEwMjA0 # MTUwODE5WjB+MRIwEAYKCZImiZPyLGQBGRYCdWsxEjAQBgoJkiaJk/IsZAEZFgJh # YzESMBAGCgmSJomT8ixkARkWAmljMUAwPgYDVQQDEzdJbXBlcmlhbCBDb2xsZWdl # IFN1Ym9yZGluYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMIICIjANBgkq # hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwWXS9zPICV4jIdQq8gEWILjc77DGVFAX # iQw5jnbpEbp0MRybyO7xhkgvPWjApnFBQVb2MLl38kXDGfFOkk6BxM8rdzbGk7dN # 1+g5P1HMAxBEv7g3xwOMRhruXwmcFYhXO9aK5vm+LfwgB+7cI3Rald0xH88c/j2O # 5oyXwipm8QKTq+uiQgc1hJicGTwpee+MgIKg4ErOGd7u6WworI4Q5ssTRLc4QsTN # 3FsH/YoNcIH8YBOf6zsyyFVAp81wwtnpXbmb12t81xL8ilJCzId621nGmSaIieTG # t5WO3lHb5hDAR6d7j5FGvilkG5NxLqxDcTcAZwzi47J4G17XLonzG2dis5gdbxuC # csJtI15D4yIuelM0QL9tBv1rK9L3a9rNFw68PdKGLFdy45LxNKEPobW99x8akQF9 # BqkuiCQHPwy0J2IT8mGDFrwJOkQafuZH05oD9Ve0DSEmfkrb2ov3RJCtfMeoPXX8 # qqwciLbtqBPG7RdUkadvpa/57arpaaqpxmKbKWmQkkIVb70CIjoMsifZo8xOenvJ # lW0PR1DklgBPYFyMVgkjkFBlfByI+RKl2LGHdhGkjYor5Vm+0BpuvmafhzmKq4hl # t3x9w6ej3PG47hfRs2/x2rle98BXdEErbOYJQDiwC9zLWakbtXRbczJdpNRfcWOQ # VRXfK/ohEAECAwEAAaOCARQwggEQMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQW # BBSEUdMHUDoNmOjy1Qr0hY7LRkokGzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA # QTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSyoWQR # aDlAlbayM02OogP+NFWLajCBggYDVR0fBHsweTB3oHWgc4ZxaHR0cDovL2ljY2E0 # LmljLmFjLnVrL0NlcnRFbnJvbGwvSW1wZXJpYWwlMjBDb2xsZWdlJTIwTG9uZG9u # JTIwUm9vdCUyMFNlY3VyZSUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAy # MC5jcmwwDQYJKoZIhvcNAQELBQADggIBAJynGpiQjCg0dKkERvQ1cjFGykU5AyFL # su+UShC4yXsGEu07OfkmY2d+75A8p6hXzcZW/KgpWQ39eaeKITi5q5ChdsXHHszW # /JZPFaJk1cV/DwPSKKa2KJDG1TtwYUWrVFZMR+r3ns+If6f5IPJMIEU8MmBncAo0 # KaIIljwS8uRSFBW9XmaGCrxFeRs+n2a+sjf+NUXtriCgJz+8lNGzyP9Ge1/1IU8b # ZJuiV1/DgHSwqMHfVDxYPYY5RDHVnWRlSPN6R+d40Vd+ZxWq1jMxUCuRJPjjCmL3 # j/SuoAtJit5r+6yisR4jobV8wtgeFq7zLGYPz96/3BdPN/HEmmSLyi0AjiRY23jY # cDAlM+cAgNgoMyoHt77PVrkYMM8NI5GSu0PcRT+pkCEyzyGdaVWUZhzN5TmPyvrj # mwQsKuOY3B1Eid5xv+NBZGnJmJQfhiHzdu7J1h+xoLy6ylf0dkoBl1lV9JUSv8bY # bTJ3Ds+FjwH6B/6ns7Qwq89d6WnnQJDwfWDPvOC+7s8jOGaYReijxkNE/8GUK69b # Iw6oyCHjfMiyPMhnIMRZJP6jUPzP5Ka2xFOEWDWivfAolRtJjQbqGLQiITDLzY23 # bKIhdKL4FdGNd8a5z6HIe/r6Zhn4E4RkrJ8JP3dzbcxwLWVxxLk+GD2G0PP+vFJ8 # r24tTZBnA3U8MIIHRDCCBSygAwIBAgITbQAC4ullHJjXjzOpdwAAAALi6TANBgkq # hkiG9w0BAQsFADB+MRIwEAYKCZImiZPyLGQBGRYCdWsxEjAQBgoJkiaJk/IsZAEZ # FgJhYzESMBAGCgmSJomT8ixkARkWAmljMUAwPgYDVQQDEzdJbXBlcmlhbCBDb2xs # ZWdlIFN1Ym9yZGluYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIx # MDgxNzE1Mjc0M1oXDTI2MDgxNjE1Mjc0M1owfDEPMA0GA1UEBxMGTG9uZG9uMSAw # HgYDVQQKExdJbXBlcmlhbCBDb2xsZWdlIExvbmRvbjEaMBgGA1UECxMRSUNUIEVV # QyBDb2RlIFNpZ24xKzApBgkqhkiG9w0BCQEWHGphc29uLmJlbm5ldHRAaW1wZXJp # YWwuYWMudWswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIxO4kTEjy # 59THp/+s5SzWc/GmI5U+EIiomLUl29lrQb5uKwxg771VbtAxDC7Cp/QMiVPWcZWg # fuiU7ku2awzlYzi9VOMQO1vodpcBX3qHux1L3c2580l0N57qJnxMjHpcsbvnGcoM # It9Etufkv1kLmTWiQOdFG1SRFKpF1hqvqjYHghThPQwz4ZdWn9m7+qWYJSrJ5SDp # 4PredIgfJwcmbn14/wmihuXxAdxWd3gdgGPRiKdH2WeCTlVT9IBTu9gP5FBLhXUl # Gg7lUkqVnJyxzlP6PhjvuVvOsSf+YfPTU/+cPfHBUAhMPw6KWcVCfZ46uvqSgBft # zXvn6s6N8lpNAgMBAAGjggK7MIICtzA8BgkrBgEEAYI3FQcELzAtBiUrBgEEAYI3 # FQiGwpoMgYTsC82RAYTl+DaHmsUBRYHk5RmF75EkAgFkAgEIMBMGA1UdJQQMMAoG # CCsGAQUFBwMDMAsGA1UdDwQEAwIFoDAbBgkrBgEEAYI3FQoEDjAMMAoGCCsGAQUF # BwMDMB0GA1UdDgQWBBQlMfwwz4lk5V87PMknQfO9ttwfHDAfBgNVHSMEGDAWgBSE # UdMHUDoNmOjy1Qr0hY7LRkokGzCB/wYDVR0fBIH3MIH0MIHxoIHuoIHrhoHobGRh # cDovLy9DTj1JbXBlcmlhbCUyMENvbGxlZ2UlMjBTdWJvcmRpbmF0ZSUyMENlcnRp # ZmljYXRlJTIwQXV0aG9yaXR5JTIwLTAwNzQwLENOPWljY2E0LENOPUNEUCxDTj1Q # dWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0 # aW9uLERDPWljLERDPWFjLERDPXVrP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/ # YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDCB9QYIKwYBBQUH # AQEEgegwgeUwgeIGCCsGAQUFBzAChoHVbGRhcDovLy9DTj1JbXBlcmlhbCUyMENv # bGxlZ2UlMjBTdWJvcmRpbmF0ZSUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIw # LTAwNzQwLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2 # aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWljLERDPWFjLERDPXVrP2NBQ2VydGlm # aWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MA0G # CSqGSIb3DQEBCwUAA4ICAQCPxZGIOolo569qE7sw2Kuf+wjYWN6XaedFn8ATJeJj # IAZvUHhn8fDJrrdEfAsAEWUKVmh9wCJ8O93KmpoqDLw8gdhyz/I8eXssZkssonG5 # 1n5APZ9TlA2O2CIIGWNKtMFSjm+KUKmDTbGyq9xlwY6S3u376mKYoZJNoXHveyVP # tRdvvAthN+XgFjbWaE5Y/xykOGI+CcMy+veL5/xEOStWRN6lFCuU1Mr3FiPy018o # a9RUNouRvLV46pSBrDvuj0glOUFqjuqClZ/2qY0pCFZHtguV3VProVAJQIo9TjS4 # RcnQQ8oxMFXTU1bT4gWDw4pR6bZS3ozmGt3GFRDRZoI0Jly+ID1CCxEKFYOw1g1z # jM+s/FdKfMDEbLZUVzzEPxCG45TDVI3PTPS/EZ8ySwyGq6qbwsK3HXPGCR1YA6zt # K8Ua7qweTAC4jGIQSWv4RnZkZc/th0rHQEEa8MTKDIi+HrNzfAnXhqwJdgfimAc6 # Bl7BwGKtNRVMBxjoFrX3ruXXRi6FrTDPZ/f/0HXIu6T1KlKlWoFZj0++gROD1zFR # UE9jUW6/Ug3hbGOiDDHf6uNCTrl7eK9BAhlkJQCO1/iJ/JwQz9+pkXD/rkODVssU # c/XQxjRwjcnwWqsbU2hPGbfZuwAseQhgVlx//63swaKYxq6gDGuCySVBwenbvJ8Z # VDGCAjcwggIzAgEBMIGVMH4xEjAQBgoJkiaJk/IsZAEZFgJ1azESMBAGCgmSJomT # 8ixkARkWAmFjMRIwEAYKCZImiZPyLGQBGRYCaWMxQDA+BgNVBAMTN0ltcGVyaWFs # IENvbGxlZ2UgU3Vib3JkaW5hdGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAC # E20AAuLpZRyY148zqXcAAAAC4ukwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwx # CjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGC # NwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFJNhBGw+kb6397bW # 1ZM7K+7nGMhcMA0GCSqGSIb3DQEBAQUABIIBACmS3Z7ALbyxjYMRq+HYkp1EdrNJ # /NIWYm7pSDH+1grGPi+dHCLUiJHx1xtTbZAXyo2Xg37i2pvphrJUK+PbKtqguhNQ # NFLqrpn6TMIniAZ4yNL1/tPBBVQggDD8R9Ko0PWYPaoUKK+XXxbxQc/aj9tiP2pG # glzYzSSeCfuBZ1/xKSp0bcqv8Helx/L0+B9qd/T7b2+tSFeYsM6cPsbjW3KYfmFy # s1MAHJkYyu1ZkiAd7+WQ5VBoPCxaZa24ELgoX3YWhl3s1hhpcKbuiPp952ZsR4G0 # CV05osty05lfO3NLxpL1gZs2nCUe+aBcq2BEvCF8C/T3FtNbOX0AaYi1F7A= # SIG # End signature block |