ict-autopilot.ps1
|
<#PSScriptInfo .VERSION 3.1.0 .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 $script:TempPath = Join-Path $env:TEMP "ICT-Autopilot" function Ensure-TempDirectory { if (-not (Test-Path -Path $script:TempPath)) { [void](New-Item -Path $script:TempPath -ItemType Directory -Force) } return $script:TempPath } function Get-TempFilePath { param( [Parameter(Mandatory = $true)] [string]$FileName ) Join-Path (Ensure-TempDirectory) $FileName } function Test-IsAdministrator { return ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Ensure-Module { param( [Parameter(Mandatory = $true)] [string]$Name, [switch]$AllowClobber ) if (-not (Get-Module -ListAvailable -Name $Name)) { $installParams = @{ Name = $Name Force = $true Scope = 'CurrentUser' Confirm = $false ErrorAction = 'Stop' } if ($AllowClobber) { $installParams.AllowClobber = $true } Install-Module @installParams } Import-Module $Name -Force -Global -ErrorAction Stop | Out-Null } function Create-MainForm { $form = New-Object System.Windows.Forms.Form $form.Text = "ICT-Autopilot 3.1.0" $form.Size = New-Object System.Drawing.Size(520, 700) $form.StartPosition = "CenterScreen" $form.BackColor = [System.Drawing.Color]::FromArgb(248, 250, 252) $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $form.MaximizeBox = $false $form.Font = New-Object System.Drawing.Font("Segoe UI", 9) # Add custom icon try { $iconPath = Get-TempFilePath -FileName "win11.ico" if (-not (Test-Path $iconPath)) { Invoke-WebRequest -Uri "https://ictautopilot.blob.core.windows.net/assets/win11.ico" -OutFile $iconPath -ErrorAction Stop } if (Test-Path $iconPath) { $form.Icon = New-Object System.Drawing.Icon($iconPath) } } catch { Write-Warning "Could not load custom icon: $_" } $titleLabel = New-Object System.Windows.Forms.Label $titleLabel.Location = New-Object System.Drawing.Point(20, 16) $titleLabel.Size = New-Object System.Drawing.Size(470, 28) $titleLabel.Font = New-Object System.Drawing.Font("Segoe UI Semibold", 14) $titleLabel.ForeColor = [System.Drawing.Color]::FromArgb(15, 23, 42) $titleLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter $titleLabel.Text = "ICT Autopilot Toolkit" # Add serial number header $headerLabel = New-Object System.Windows.Forms.Label $headerLabel.Location = New-Object System.Drawing.Point(20, 50) $headerLabel.Size = New-Object System.Drawing.Size(470, 26) $headerLabel.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) $headerLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter $headerLabel.ForeColor = [System.Drawing.Color]::FromArgb(51, 65, 85) # Get and display serial number try { $serial = Get-CimInstance -ClassName Win32_BIOS | Select-Object -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, 86) $script:listBox.Size = New-Object System.Drawing.Size(470, 245) $script:listBox.Font = New-Object System.Drawing.Font("Segoe UI", 10) $script:listBox.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle $script:listBox.IntegralHeight = $false # ...existing listbox items... $executeButton = New-Object System.Windows.Forms.Button $executeButton.Location = New-Object System.Drawing.Point(20, 344) $executeButton.Size = New-Object System.Drawing.Size(470, 40) $executeButton.Text = "Execute Selected Option" $executeButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat $executeButton.BackColor = [System.Drawing.Color]::FromArgb(37, 99, 235) $executeButton.ForeColor = [System.Drawing.Color]::White $executeButton.Font = New-Object System.Drawing.Font("Segoe UI Semibold", 10) $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. Enrol your machine into Autopilot") [void]$script:listBox.Items.Add("2. Create Autopilot CSV file") [void]$script:listBox.Items.Add("3. Enrol Custom Device into Autopilot") [void]$script:listBox.Items.Add("4. Enrol Surface 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. Retrieve BitLocker Recovery Key") [void]$script:listBox.Items.Add("11. Install PowerShell 7 (Stable)") [void]$script:listBox.Items.Add("12. Restart PC") $script:outputBox = New-Object System.Windows.Forms.RichTextBox $script:outputBox.Location = New-Object System.Drawing.Point(20, 394) $script:outputBox.Size = New-Object System.Drawing.Size(470, 250) $script:outputBox.ReadOnly = $true $script:outputBox.BackColor = [System.Drawing.Color]::FromArgb(241, 245, 249) $script:outputBox.ForeColor = [System.Drawing.Color]::FromArgb(15, 23, 42) $script:outputBox.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle $script:outputBox.Font = New-Object System.Drawing.Font("Segoe UI", 10) $script:outputBox.Text = "Ready. Select an action and click Execute." $form.Controls.Add($titleLabel) $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( [string]$message, [switch]$Clear ) if (-not $script:outputBox) { Write-Host $message return } if ($Clear) { $script:outputBox.Clear() } if ([string]::IsNullOrWhiteSpace($script:outputBox.Text)) { $script:outputBox.Text = $message } else { $script:outputBox.AppendText("`r`n$message") } $script:outputBox.SelectionStart = $script:outputBox.TextLength $script:outputBox.ScrollToCaret() [System.Windows.Forms.Application]::DoEvents() } function Get-BitLockerRecoveryKey { 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 retrieve the BitLocker recovery key." return } $keyInfo = Get-BitLockerVolume -MountPoint "C:" | Select-Object -ExpandProperty KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } if ($keyInfo) { $recoveryKey = $keyInfo.RecoveryPassword Update-Output "BitLocker Recovery Key for C:`n$recoveryKey" } else { Update-Output "No BitLocker recovery key found for C: drive." } } catch { Update-Output "Error retrieving BitLocker recovery key" } } function Execute-Selection { param($selection) if ($selection -notmatch '^\s*(\d+)\.') { Update-Output "Please select an option from the list." -Clear return } $option = [int]$matches[1] Update-Output "Running option $option..." -Clear switch ($option) { 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 { Get-BitLockerRecoveryKey } 11 { Install-PowerShell7 } 12 { Restart-PCWithCountdown } default { Update-Output "Please select an option from the list." } } } function Check-Windows11Compatibility { try { $results = @() # Download CPU compatibility lists Update-Output "Checking CPU compatibility lists..." $cpuSources = @{ 'AMD-CPU.txt' = 'https://ictautopilot.blob.core.windows.net/win11compat/AMD-CPU.txt' 'INTEL-CPU.txt' = 'https://ictautopilot.blob.core.windows.net/win11compat/Intel-CPU.txt' 'SNAP-CPU.txt' = 'https://ictautopilot.blob.core.windows.net/win11compat/snap-CPU.txt' } foreach ($entry in $cpuSources.GetEnumerator()) { $targetPath = Get-TempFilePath -FileName $entry.Key $downloadRequired = -not (Test-Path $targetPath) if (-not $downloadRequired) { $downloadRequired = ((Get-Date) - (Get-Item $targetPath).LastWriteTime).TotalDays -gt 7 } if ($downloadRequired) { Invoke-WebRequest -Uri $entry.Value -OutFile $targetPath -ErrorAction Stop } } # Load CPU lists and get system info $listprocIntel = Get-Content (Get-TempFilePath -FileName 'INTEL-CPU.txt') $listprocAMD = Get-Content (Get-TempFilePath -FileName 'AMD-CPU.txt') $listprocSNAP = Get-Content (Get-TempFilePath -FileName 'SNAP-CPU.txt') $procs = (Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty Name) $cpuCompatible = $false $cpuLabel = ($procs -join '; ') # Check CPU compatibility foreach ($proc in $procs) { $candidate = $false if ($proc -like "*Intel*") { $candidate = $listprocIntel | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } elseif ($proc -like "*AMD*") { $candidate = $listprocAMD | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } else { $candidate = $listprocSNAP | Where-Object { $proc -like "*$_*" } | Select-Object -First 1 } if ($candidate) { $cpuCompatible = $true break } } # Add CPU compatibility result $results += "CPU Model: $cpuLabel - $(if($cpuCompatible){'Pass'}else{'Fail'})" # ...existing checks... # Check RAM $ram = Get-CimInstance -ClassName 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-CimInstance -ClassName 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-CimInstance -Namespace "root\CIMV2\Security\MicrosoftTpm" -ClassName 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 try { $secureBootStatus = Confirm-SecureBootUEFI -ErrorAction Stop } catch { $secureBootStatus = $false } $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 (Test-IsAdministrator)) { 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-CimInstance -ClassName Win32_BIOS | Select-Object -ExpandProperty SerialNumber $deviceName = $env:COMPUTERNAME Update-Output "Installing required PowerShell modules..." Ensure-Module -Name WindowsAutopilotIntune -AllowClobber Ensure-Module -Name Microsoft.Graph.Intune Ensure-Module -Name Microsoft.Graph.Identity.DirectoryManagement Update-Output "Connecting to Microsoft Graph..." Connect-MgGraph -ClientId 5fa15279-2ada-4a13-b288-76929759e805 -TenantId 2b897507-ee8c-4575-830b-4f8267c3d307 # 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 Install-PowerShell7 { try { Update-Output "Downloading PowerShell 7 installer..." $installerPath = Get-TempFilePath -FileName "PowerShell-7.msi" Invoke-WebRequest -Uri "https://aka.ms/powershell-release?tag=stable" -OutFile $installerPath Update-Output "Running PowerShell 7 installer..." Start-Process msiexec.exe -ArgumentList "/i `"$installerPath`" /qn" -Wait Update-Output "PowerShell 7 installation completed. You may need to restart your computer." } catch { Update-Output "Error installing PowerShell 7" } } function Restart-PCWithCountdown { try { # Check for admin privileges if (-not (Test-IsAdministrator)) { 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-CimInstance -ClassName 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 (Test-IsAdministrator)) { 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 } # Load dependencies first, then WindowsAutopilotIntune Update-Output "Checking required modules..." Ensure-Module -Name Microsoft.Graph.Authentication Ensure-Module -Name Microsoft.Graph.Intune Ensure-Module -Name Microsoft.Graph.Identity.DirectoryManagement Ensure-Module -Name WindowsAutopilotIntune -AllowClobber Update-Output "Connecting to Microsoft Graph..." Connect-MgGraph -ClientId "5fa15279-2ada-4a13-b288-76929759e805" -TenantId "2b897507-ee8c-4575-830b-4f8267c3d307" # Get serial number Update-Output "Getting device serial number..." $serial = Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop | Select-Object -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 (Test-IsAdministrator)) { 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 -tenantid "2b897507-ee8c-4575-830b-4f8267c3d307" -appid "5fa15279-2ada-4a13-b288-76929759e805" -appsecret "cfw8Q~PVAvzVxXV2DrUswXZtYg3KHQD2~Dca4bWm" -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 (Test-IsAdministrator)) { 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 -tenantid "2b897507-ee8c-4575-830b-4f8267c3d307" -appid "5fa15279-2ada-4a13-b288-76929759e805" -appsecret "cfw8Q~PVAvzVxXV2DrUswXZtYg3KHQD2~Dca4bWm" -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 (Test-IsAdministrator)) { 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 -tenantid "2b897507-ee8c-4575-830b-4f8267c3d307" -appid "5fa15279-2ada-4a13-b288-76929759e805" -appsecret "cfw8Q~PVAvzVxXV2DrUswXZtYg3KHQD2~Dca4bWm" -GroupTag MTR-ICT -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 (Test-IsAdministrator)) { Update-Output "Please run as Administrator to create an Autopilot CSV" return } $csvPath = Get-TempFilePath -FileName "AutopilotHWID.csv" Update-Output "Installing Autopilot PowerShell script..." Install-Script -Name Get-WindowsAutoPilotInfo -Force Update-Output "Creating Autopilot CSV in $csvPath. Please wait..." Get-WindowsAutoPilotInfo -OutputFile $csvPath Update-Output "Hardware hash saved to $csvPath" } catch { Update-Output "Error enrolling device: $_" } } function Run-WindowsUpdate { try { if (-not (Test-IsAdministrator)) { Update-Output "Please run as Administrator to perform Windows Update" return } # Install required module Update-Output "Installing required PowerShell modules..." Ensure-Module -Name PSWindowsUpdate 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 { $computerInfo = Get-ComputerInfo $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem $os = $osInfo.Caption $cpu = Get-CimInstance -ClassName Win32_Processor $ram = [math]::Round((Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2) $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'" $freeSpace = [math]::Round($disk.FreeSpace / 1GB, 2) $model = $computerInfo.CsModel $bios = $computerInfo.BiosSMBIOSBIOSVersion $locale = $computerInfo.OsLanguage $serial = $computerInfo.BiosSerialNumber $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 # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUOhifE0a25Sd9ARtsydck0JWI # 2y+ggg47MIIG7zCCBNegAwIBAgITIQAAAAQ+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 # NwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFHuQ6ZJNazZmBff7 # ATyYFjmmK4ZoMA0GCSqGSIb3DQEBAQUABIIBAGnbgRDqS9GtC6mhc163ClzM/94Y # 4xA6x+nS70nT8Z9uJak+Gnzn+02dnv2FgLpZwuN0KdsWgwsjuNdfWx6pLmZ8c6lg # UAGyrBI0fFp+TpBmyN6U6Sj2t733+qax/+II4zwuJ99bTXJqjmdLGA2BeHD+TtPe # HuonwLnTinEKN9clK+gxzyhYgJKPO/ckY98Ctf/XWV6pReE4KdX7Rl2+nkR0ds0T # s6DZbYH1bXUmADwD93uLP78LjHSe/9f8h7UcK3ZQyL9rCVubUVJq2x1mMiPdK1q5 # cLulTroaleNZ3FMiIaZsFw5DnrhX0dKujgPQ6hX+guGE+znb41BHJLosmp8= # SIG # End signature block |