Intune-Diag-UI.ps1
|
<#PSScriptInfo
.VERSION 2.1 .GUID b00d1997-e4fa-4af1-86f0-49220c606238 .AUTHOR Florian Salzmann .COMPANYNAME scloud.work .COPYRIGHT 2025 Florian Salzmann. GPL-3.0 license. .TAGS PowerShell Intune Diagnostics LogAnalyzer Autopilot .LICENSEURI https://github.com/FlorianSLZ/scloud/blob/main/LICENSE .PROJECTURI https://github.com/FlorianSLZ/scloud/tree/main/scripts/Intune-Diag .ICONURI https://scloud.work/wp-content/uploads/Intune-Diag.png .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES 2024-09-26, 1.0 - Original published version. 2025-03-14, 1.1 - Minor improvements 2025-03-14, 1.2 - Changed to English, improved error handling and loader 2026-02-24, 2.0 - UI overhaul, script selector dropdown 2026-02-25, 2.1 - Enhanced dark UI, Export Autopilot Logs button, pwsh compatibility #> <# .DESCRIPTION A PowerShell-based tool for analyzing Intune Management Extension and Autopilot logs. Quickly troubleshoot Intune and Autopilot issues with an intuitive UI and built-in ZIP extraction. Supported diagnostic scripts (downloaded from PowerShell Gallery): - Get-IntuneManagementExtensionDiagnostics (by Petri Paavola) - Get-AutopilotDiagnostics (by Michael Niehaus / Microsoft) - Get-AutopilotDiagnosticsCommunity (by Andrew Taylor, Michael Niehaus & Steven van Beek) #> ######################################################################################### # Initial Setup ######################################################################################### $PackageName = "IntuneDiagnostic-UI" $ScriptFolder = "C:\ProgramData\$PackageName" $DiagScripts = @( @{ Name = "Get-IntuneManagementExtensionDiagnostics" Label = "IME Diagnostics (Petri Paavola)" FileName = "Get-IntuneManagementExtensionDiagnostics.ps1" FolderArg = '-LogFilesFolder "{0}"' FileArg = '-LogFilesFolder "{0}"' LocalArg = '' }, @{ Name = "Get-IntuneManagementExtensionDiagnosticsV2" Label = "IME Diagnostics V2 - Modern UI (Ayoub Sekoum)" FileName = "Get-IntuneManagementExtensionDiagnosticsV2.ps1" FolderArg = '-LogFilesFolder "{0}"' FileArg = '-LogFilesFolder "{0}"' LocalArg = '' }, @{ Name = "Get-AutopilotDiagnostics" Label = "Autopilot Diagnostics (Michael Niehaus)" FileName = "Get-AutopilotDiagnostics.ps1" FolderArg = '-ZIPFile "{0}"' FileArg = '-ZIPFile "{0}"' LocalArg = '' }, @{ Name = "Get-AutopilotDiagnosticsCommunity" Label = "Autopilot Diagnostics Community (Andrew Taylor)" FileName = "Get-AutopilotDiagnosticsCommunity.ps1" FolderArg = '-File "{0}"' FileArg = '-File "{0}"' LocalArg = '' } ) # Always use Windows PowerShell 5.1 for diagnostic scripts (they need reg.exe, expand.exe in PATH) $psExePath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" ######################################################################################### # Execution Policy Check ######################################################################################### $CurrentPolicy = Get-ExecutionPolicy -Scope Process if ($CurrentPolicy -ne "Bypass") { Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force } ######################################################################################### # Download Scripts ######################################################################################### if (!(Test-Path $ScriptFolder)) { New-Item -Path $ScriptFolder -Type Directory -Force | Out-Null } foreach ($ds in $DiagScripts) { $scriptPath = Join-Path $ScriptFolder $ds.FileName if (!(Test-Path $scriptPath)) { try { Save-Script $ds.Name -Path $ScriptFolder -Force -ErrorAction Stop } catch { Write-Host "Warning: Could not download $($ds.Name): $_" -ForegroundColor Yellow } } } ######################################################################################### # UI ######################################################################################### Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Set unique AppUserModelID so the taskbar shows our icon try { Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class TaskbarHelper { [DllImport("shell32.dll", SetLastError = true)] public static extern void SetCurrentProcessExplicitAppUserModelID( [MarshalAs(UnmanagedType.LPWStr)] string AppID); } "@ [TaskbarHelper]::SetCurrentProcessExplicitAppUserModelID("scloud.IntuneDiagnosticTool") } catch { } # ---------- Color Palette (enhanced dark theme) ---------- $colBg = [System.Drawing.Color]::FromArgb(22, 22, 30) $colSurface = [System.Drawing.Color]::FromArgb(32, 33, 42) $colSurfaceHi = [System.Drawing.Color]::FromArgb(42, 43, 56) $colAccent = [System.Drawing.Color]::FromArgb(99, 102, 241) # indigo $colAccentHover = [System.Drawing.Color]::FromArgb(118, 120, 255) $colSuccess = [System.Drawing.Color]::FromArgb(34, 197, 94) $colWarning = [System.Drawing.Color]::FromArgb(245, 158, 11) $colError = [System.Drawing.Color]::FromArgb(239, 68, 68) $colAmber = [System.Drawing.Color]::FromArgb(245, 158, 11) $colAmberHover = [System.Drawing.Color]::FromArgb(255, 180, 40) $colTextPrimary = [System.Drawing.Color]::White $colTextMuted = [System.Drawing.Color]::FromArgb(140, 140, 165) $colInputBg = [System.Drawing.Color]::FromArgb(38, 38, 55) $colBorder = [System.Drawing.Color]::FromArgb(55, 55, 75) # ---------- Fonts ---------- $fontTitle = New-Object System.Drawing.Font("Segoe UI", 15, [System.Drawing.FontStyle]::Bold) $fontNormal = New-Object System.Drawing.Font("Segoe UI", 9.5) $fontSmall = New-Object System.Drawing.Font("Segoe UI", 8.5) $fontBadge = New-Object System.Drawing.Font("Segoe UI", 7.5, [System.Drawing.FontStyle]::Bold) $fontButton = New-Object System.Drawing.Font("Segoe UI Semibold", 9.5) # ---------- Form ---------- $form = New-Object System.Windows.Forms.Form $form.Text = "Intune Diagnostic Tool" $form.Size = New-Object System.Drawing.Size(560, 520) $form.StartPosition = "CenterScreen" $form.FormBorderStyle = "FixedSingle" $form.MaximizeBox = $false $form.BackColor = $colBg $form.ForeColor = $colTextPrimary $form.Font = $fontNormal # ---------- Header Panel ---------- $panelHeader = New-Object System.Windows.Forms.Panel $panelHeader.Dock = "Top" $panelHeader.Height = 72 $panelHeader.BackColor = $colSurface $form.Controls.Add($panelHeader) # Accent separator line at bottom of header $panelSep = New-Object System.Windows.Forms.Panel $panelSep.Location = New-Object System.Drawing.Point(0, 70) $panelSep.Size = New-Object System.Drawing.Size(560, 2) $panelSep.BackColor = $colAccent $panelHeader.Controls.Add($panelSep) # Logo $logoSize = 44 $logoPadLeft = 16 $logoPadTop = 14 $logoPath = Join-Path $ScriptFolder "IntuneDiag_logo.png" $picLogo = New-Object System.Windows.Forms.PictureBox $picLogo.Location = New-Object System.Drawing.Point($logoPadLeft, $logoPadTop) $picLogo.Size = New-Object System.Drawing.Size($logoSize, $logoSize) $picLogo.SizeMode = "Zoom" $picLogo.BackColor = [System.Drawing.Color]::Transparent try { if (Test-Path $logoPath) { $picLogo.Image = [System.Drawing.Image]::FromFile($logoPath) } else { $webClient = New-Object System.Net.WebClient $webClient.DownloadFile("https://scloud.work/wp-content/uploads/Intune-Diag.png", $logoPath) $picLogo.Image = [System.Drawing.Image]::FromFile($logoPath) } $iconBmp = New-Object System.Drawing.Bitmap($picLogo.Image, 32, 32) $hIcon = $iconBmp.GetHicon() $form.Icon = [System.Drawing.Icon]::FromHandle($hIcon) } catch { } $panelHeader.Controls.Add($picLogo) $textLeft = $logoPadLeft + $logoSize + 12 $lblTitle = New-Object System.Windows.Forms.Label $lblTitle.Text = "Intune Diagnostic Tool" $lblTitle.Font = $fontTitle $lblTitle.ForeColor = $colTextPrimary $lblTitle.AutoSize = $true $lblTitle.Location = New-Object System.Drawing.Point($textLeft, 12) $panelHeader.Controls.Add($lblTitle) $lblSubtitle = New-Object System.Windows.Forms.Label $lblSubtitle.Text = "Analyze Intune & Autopilot logs with ease" $lblSubtitle.Font = $fontSmall $lblSubtitle.ForeColor = $colTextMuted $lblSubtitle.AutoSize = $true $lblSubtitle.Location = New-Object System.Drawing.Point(($textLeft + 2), 42) $panelHeader.Controls.Add($lblSubtitle) # ---------- Card 1: Script Selector ---------- $card1 = New-Object System.Windows.Forms.Panel $card1.Location = New-Object System.Drawing.Point(16, 86) $card1.Size = New-Object System.Drawing.Size(512, 95) $card1.BackColor = $colSurface $form.Controls.Add($card1) $lbl1 = New-Object System.Windows.Forms.Label $lbl1.Text = " DIAGNOSTIC SCRIPT" $lbl1.Font = $fontBadge $lbl1.ForeColor = $colAccent $lbl1.Location = New-Object System.Drawing.Point(12, 10) $lbl1.Size = New-Object System.Drawing.Size(300, 16) $card1.Controls.Add($lbl1) $comboScript = New-Object System.Windows.Forms.ComboBox $comboScript.Location = New-Object System.Drawing.Point(12, 30) $comboScript.Size = New-Object System.Drawing.Size(488, 28) $comboScript.DropDownStyle = "DropDownList" $comboScript.FlatStyle = "Flat" $comboScript.BackColor = $colInputBg $comboScript.ForeColor = $colTextPrimary $comboScript.Font = $fontNormal foreach ($ds in $DiagScripts) { $comboScript.Items.Add($ds.Label) | Out-Null } $comboScript.SelectedIndex = 0 $card1.Controls.Add($comboScript) $lblAvail = New-Object System.Windows.Forms.Label $lblAvail.Font = $fontSmall $lblAvail.Location = New-Object System.Drawing.Point(12, 66) $lblAvail.Size = New-Object System.Drawing.Size(488, 18) $card1.Controls.Add($lblAvail) function Update-Availability { $idx = $comboScript.SelectedIndex $scriptPath = Join-Path $ScriptFolder $DiagScripts[$idx].FileName if (Test-Path $scriptPath) { $lblAvail.Text = [char]0x2713 + " Script ready and cached locally" $lblAvail.ForeColor = $colSuccess } else { $lblAvail.Text = [char]0x26A0 + " Script not found - will download on run" $lblAvail.ForeColor = $colWarning } } $comboScript.add_SelectedIndexChanged({ Update-Availability }) Update-Availability # ---------- Card 2: Log Source ---------- $card2 = New-Object System.Windows.Forms.Panel $card2.Location = New-Object System.Drawing.Point(16, 193) $card2.Size = New-Object System.Drawing.Size(512, 95) $card2.BackColor = $colSurface $form.Controls.Add($card2) $lbl2 = New-Object System.Windows.Forms.Label $lbl2.Text = " LOG SOURCE" $lbl2.Font = $fontBadge $lbl2.ForeColor = [System.Drawing.Color]::FromArgb(139, 92, 246) # violet $lbl2.Location = New-Object System.Drawing.Point(12, 10) $lbl2.Size = New-Object System.Drawing.Size(300, 16) $card2.Controls.Add($lbl2) $textBox = New-Object System.Windows.Forms.TextBox $textBox.Location = New-Object System.Drawing.Point(12, 30) $textBox.Size = New-Object System.Drawing.Size(394, 28) $textBox.AllowDrop = $true $textBox.BackColor = $colInputBg $textBox.ForeColor = $colTextPrimary $textBox.BorderStyle = "FixedSingle" $textBox.Font = $fontNormal $card2.Controls.Add($textBox) # Browse button $btnBrowse = New-Object System.Windows.Forms.Button $btnBrowse.Text = "Browse..." $btnBrowse.Location = New-Object System.Drawing.Point(414, 29) $btnBrowse.Size = New-Object System.Drawing.Size(86, 28) $btnBrowse.FlatStyle = "Flat" $btnBrowse.BackColor = $colSurfaceHi $btnBrowse.ForeColor = $colTextPrimary $btnBrowse.Font = $fontSmall $btnBrowse.FlatAppearance.BorderColor = $colBorder $btnBrowse.Cursor = [System.Windows.Forms.Cursors]::Hand $card2.Controls.Add($btnBrowse) $btnBrowse.add_Click({ $dlg = New-Object System.Windows.Forms.OpenFileDialog $dlg.Title = "Select a ZIP, CAB, or log file" $dlg.Filter = "Supported files (*.zip;*.cab)|*.zip;*.cab|All files (*.*)|*.*" $dlg.CheckFileExists = $true if ($dlg.ShowDialog() -eq "OK") { $textBox.Text = $dlg.FileName } }) $lblHint = New-Object System.Windows.Forms.Label $lblHint.Text = [char]0x2193 + " Drag & drop a folder, ZIP or CAB file, or use Browse" $lblHint.Font = $fontSmall $lblHint.ForeColor = $colTextMuted $lblHint.Location = New-Object System.Drawing.Point(12, 66) $lblHint.Size = New-Object System.Drawing.Size(488, 18) $card2.Controls.Add($lblHint) # ---------- Drag & Drop ---------- $textBox.add_DragEnter({ param($sender, $e) if ($e.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) { $e.Effect = [Windows.Forms.DragDropEffects]::Copy } else { $e.Effect = [Windows.Forms.DragDropEffects]::None } }) $textBox.add_DragDrop({ param($sender, $e) $items = $e.Data.GetData([Windows.Forms.DataFormats]::FileDrop) if ($items.Count -eq 1 -and (Test-Path $items[0])) { $textBox.Text = $items[0] } else { [System.Windows.Forms.MessageBox]::Show( "Please drop only one valid folder, ZIP, or CAB file.", "Invalid Input", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning ) } }) # ---------- Buttons Row 1: Analyze ---------- $btnAnalyzeFolder = New-Object System.Windows.Forms.Button $btnAnalyzeFolder.Text = [char]0x25B6 + " Analyze Path" $btnAnalyzeFolder.Location = New-Object System.Drawing.Point(16, 302) $btnAnalyzeFolder.Size = New-Object System.Drawing.Size(248, 42) $btnAnalyzeFolder.FlatStyle = "Flat" $btnAnalyzeFolder.BackColor = $colAccent $btnAnalyzeFolder.ForeColor = $colTextPrimary $btnAnalyzeFolder.Font = $fontButton $btnAnalyzeFolder.FlatAppearance.BorderSize = 0 $btnAnalyzeFolder.Cursor = [System.Windows.Forms.Cursors]::Hand $form.Controls.Add($btnAnalyzeFolder) $btnAnalyzeFolder.add_MouseEnter({ $this.BackColor = $colAccentHover }) $btnAnalyzeFolder.add_MouseLeave({ $this.BackColor = $colAccent }) $btnAnalyzePC = New-Object System.Windows.Forms.Button $btnAnalyzePC.Text = [char]0x2318 + " Analyze This PC" $btnAnalyzePC.Location = New-Object System.Drawing.Point(280, 302) $btnAnalyzePC.Size = New-Object System.Drawing.Size(248, 42) $btnAnalyzePC.FlatStyle = "Flat" $btnAnalyzePC.BackColor = $colSurface $btnAnalyzePC.ForeColor = $colTextPrimary $btnAnalyzePC.Font = $fontButton $btnAnalyzePC.FlatAppearance.BorderColor = $colBorder $btnAnalyzePC.Cursor = [System.Windows.Forms.Cursors]::Hand $form.Controls.Add($btnAnalyzePC) $btnAnalyzePC.add_MouseEnter({ $this.BackColor = $colSurfaceHi }) $btnAnalyzePC.add_MouseLeave({ $this.BackColor = $colSurface }) # ---------- Button Row 2: Export Logs ---------- $btnExportLogs = New-Object System.Windows.Forms.Button $btnExportLogs.Text = [char]0x21E9 + " Export Autopilot Logs (.zip)" $btnExportLogs.Location = New-Object System.Drawing.Point(16, 354) $btnExportLogs.Size = New-Object System.Drawing.Size(512, 38) $btnExportLogs.FlatStyle = "Flat" $btnExportLogs.BackColor = $colSurface $btnExportLogs.ForeColor = $colAmber $btnExportLogs.Font = $fontButton $btnExportLogs.FlatAppearance.BorderColor = $colAmber $btnExportLogs.Cursor = [System.Windows.Forms.Cursors]::Hand $form.Controls.Add($btnExportLogs) $btnExportLogs.add_MouseEnter({ $this.BackColor = $colSurfaceHi }) $btnExportLogs.add_MouseLeave({ $this.BackColor = $colSurface }) # ---------- Status ---------- $lblStatus = New-Object System.Windows.Forms.Label $lblStatus.Location = New-Object System.Drawing.Point(16, 406) $lblStatus.Size = New-Object System.Drawing.Size(512, 20) $lblStatus.Font = $fontSmall $lblStatus.ForeColor = $colTextMuted $lblStatus.Text = "" $form.Controls.Add($lblStatus) # ---------- Progress Bar ---------- $progressBar = New-Object System.Windows.Forms.ProgressBar $progressBar.Location = New-Object System.Drawing.Point(16, 428) $progressBar.Size = New-Object System.Drawing.Size(512, 5) $progressBar.Style = "Marquee" $progressBar.MarqueeAnimationSpeed = 30 $progressBar.Visible = $false $form.Controls.Add($progressBar) # ---------- Footer ---------- $lblFooter = New-Object System.Windows.Forms.LinkLabel $lblFooter.Text = "baki | Intune Diagnostic Tool | v2.1" $lblFooter.Font = $fontSmall $lblFooter.LinkColor = [System.Drawing.Color]::FromArgb(80, 80, 110) $lblFooter.ActiveLinkColor = $colAccent $lblFooter.VisitedLinkColor = [System.Drawing.Color]::FromArgb(80, 80, 110) $lblFooter.TextAlign = "MiddleCenter" $lblFooter.Dock = "Bottom" $lblFooter.Height = 30 $lblFooter.BackColor = [System.Drawing.Color]::FromArgb(16, 16, 22) $lblFooter.LinkArea = New-Object System.Windows.Forms.LinkArea(0, 4) $lblFooter.add_LinkClicked({ Start-Process "https://github.com/Ayoub-Sekoum" }) $form.Controls.Add($lblFooter) ######################################################################################### # Functions ######################################################################################### function Set-UIBusy { param([bool]$Busy, [string]$Message = "") $lblStatus.Text = $Message $progressBar.Visible = $Busy $btnAnalyzeFolder.Enabled = -not $Busy $btnAnalyzePC.Enabled = -not $Busy $btnExportLogs.Enabled = -not $Busy $comboScript.Enabled = -not $Busy $btnBrowse.Enabled = -not $Busy if ($Busy) { $form.Cursor = [System.Windows.Forms.Cursors]::WaitCursor $lblStatus.ForeColor = $colAccent } else { $form.Cursor = [System.Windows.Forms.Cursors]::Default } $form.Refresh() } function Get-SelectedScript { $idx = $comboScript.SelectedIndex return $DiagScripts[$idx] } function Ensure-ScriptAvailable { param($ScriptDef) $path = Join-Path $ScriptFolder $ScriptDef.FileName if (!(Test-Path $path)) { Set-UIBusy -Busy $true -Message "Downloading $($ScriptDef.Name)..." try { Save-Script $ScriptDef.Name -Path $ScriptFolder -Force -ErrorAction Stop } catch { [System.Windows.Forms.MessageBox]::Show( "Failed to download $($ScriptDef.Name):`n$_", "Download Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error ) Set-UIBusy -Busy $false -Message "Download failed." $lblStatus.ForeColor = $colError return $null } } if (Test-Path $path) { return $path } else { return $null } } function Start-Analysis { param([string]$InputPath) $scriptDef = Get-SelectedScript $scriptPath = Ensure-ScriptAvailable -ScriptDef $scriptDef if (-not $scriptPath) { return } Set-UIBusy -Busy $true -Message "Running $($scriptDef.Name)..." $logTarget = $InputPath # Handle archive extraction for IME Diagnostics (it expects a folder, not a file) if ($scriptDef.Name -like "Get-IntuneManagementExtensionDiagnostics*" -and $InputPath -match '\.(zip|cab)$') { $extractPath = Join-Path $env:TEMP "IntuneDiag_$(Get-Random)" New-Item -Path $extractPath -Type Directory -Force | Out-Null try { if ($InputPath -match '\.zip$') { Expand-Archive -Path $InputPath -DestinationPath $extractPath -Force } else { # CAB files: use expand.exe $expandProc = Start-Process -FilePath "expand.exe" ` -ArgumentList "`"$InputPath`" -F:* `"$extractPath`"" ` -PassThru -Wait -NoNewWindow if ($expandProc.ExitCode -ne 0) { throw "expand.exe exited with code $($expandProc.ExitCode)" } } $logTarget = $extractPath } catch { [System.Windows.Forms.MessageBox]::Show( "Error extracting archive:`n$_", "Extraction Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error ) Set-UIBusy -Busy $false -Message "Analysis failed." $lblStatus.ForeColor = $colError return } } # Build argument string $isFolder = (Test-Path $logTarget -PathType Container) $isFile = (Test-Path $logTarget -PathType Leaf) if ($scriptDef.Name -like "Get-IntuneManagementExtensionDiagnostics*") { $argString = $scriptDef.FolderArg -f $logTarget } elseif ($isFile) { $argString = $scriptDef.FileArg -f $logTarget } else { $archiveFile = Get-ChildItem -Path $logTarget -Include *.zip, *.cab -Recurse -File | Select-Object -First 1 if ($archiveFile) { $argString = $scriptDef.FileArg -f $archiveFile.FullName } else { $argString = $scriptDef.FolderArg -f $logTarget } } try { $psArgs = "-ExecutionPolicy Bypass -File `"$scriptPath`" $argString" Start-Process -FilePath $psExePath -ArgumentList $psArgs -NoNewWindow -Wait Set-UIBusy -Busy $false -Message ([char]0x2713 + " Analysis completed successfully.") $lblStatus.ForeColor = $colSuccess } catch { Set-UIBusy -Busy $false -Message ([char]0x2717 + " Analysis encountered an error.") $lblStatus.ForeColor = $colError } Update-Availability } function Start-LocalAnalysis { $scriptDef = Get-SelectedScript $scriptPath = Ensure-ScriptAvailable -ScriptDef $scriptDef if (-not $scriptPath) { return } Set-UIBusy -Busy $true -Message "Running $($scriptDef.Name) on this PC..." try { $localArg = "$($scriptDef.LocalArg)".Trim() $psArgs = "-ExecutionPolicy Bypass -File `"$scriptPath`" $localArg".Trim() Start-Process -FilePath $psExePath -ArgumentList $psArgs -NoNewWindow -Wait Set-UIBusy -Busy $false -Message ([char]0x2713 + " Local analysis completed successfully.") $lblStatus.ForeColor = $colSuccess } catch { Set-UIBusy -Busy $false -Message ([char]0x2717 + " Local analysis encountered an error.") $lblStatus.ForeColor = $colError } Update-Availability } function Start-ExportLogs { $outFolder = "C:\temp" if (!(Test-Path $outFolder)) { New-Item -Path $outFolder -Type Directory -Force | Out-Null } $pcName = $env:COMPUTERNAME $cabPath = Join-Path $outFolder "AutopilotLogs-$pcName.cab" $extractTo = Join-Path $outFolder "AutopilotLogs-$pcName" # Clean previous exports if (Test-Path $cabPath) { Remove-Item $cabPath -Force -ErrorAction SilentlyContinue } if (Test-Path $extractTo) { Remove-Item $extractTo -Recurse -Force -ErrorAction SilentlyContinue } # 1. Export CAB Set-UIBusy -Busy $true -Message "Exporting Autopilot logs..." try { $proc = Start-Process -FilePath "mdmdiagnosticstool.exe" ` -ArgumentList "-area Autopilot -cab `"$cabPath`"" ` -PassThru -Wait -NoNewWindow if ($proc.ExitCode -ne 0 -or !(Test-Path $cabPath)) { Set-UIBusy -Busy $false -Message ([char]0x2717 + " Export failed (exit code $($proc.ExitCode)).") $lblStatus.ForeColor = $colError return } } catch { Set-UIBusy -Busy $false -Message ([char]0x2717 + " Export error: $_") $lblStatus.ForeColor = $colError return } # 2. Extract CAB to folder New-Item -Path $extractTo -Type Directory -Force | Out-Null Set-UIBusy -Busy $true -Message "Extracting CAB..." try { Start-Process -FilePath "expand.exe" ` -ArgumentList "`"$cabPath`" -F:* `"$extractTo`"" ` -Wait -NoNewWindow } catch { Set-UIBusy -Busy $false -Message ([char]0x2717 + " Extraction error: $_") $lblStatus.ForeColor = $colError return } # 3. Verify extraction produced files $extractedFiles = Get-ChildItem -Path $extractTo -File -ErrorAction SilentlyContinue if ($null -eq $extractedFiles -or $extractedFiles.Count -eq 0) { Set-UIBusy -Busy $false -Message ([char]0x2717 + " CAB was empty - no files extracted.") $lblStatus.ForeColor = $colError return } # 4. Pre-check: is this an Autopilot device? Set-UIBusy -Busy $true -Message "Step 3/3: Checking Autopilot data..." $autopilotPatterns = @("*DeviceHash*", "*AutopilotDDSZTDFile*", "*CloudAssigned*", "*TpmHliInfo*", "*DiagnosticLogCSP*Autopilot*", "*MDMDiagReport*") $foundFiles = @() foreach ($pat in $autopilotPatterns) { $m = $extractedFiles | Where-Object { $_.Name -like $pat } if ($m) { $foundFiles += $m.Name } } $regAutopilot = Test-Path "HKLM:\SOFTWARE\Microsoft\Provisioning\Diagnostics\Autopilot" -ErrorAction SilentlyContinue if ($foundFiles.Count -eq 0 -and -not $regAutopilot) { $answer = [System.Windows.Forms.MessageBox]::Show( "This device does not appear to be Autopilot-enrolled.`n`n" + "No Autopilot indicators found in the exported logs.`n" + "No Autopilot registry keys detected.`n`n" + "Extracted $($extractedFiles.Count) file(s) to:`n$extractTo`n`n" + "Do you want to analyze anyway?", "Autopilot Not Detected", [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning ) if ($answer -eq [System.Windows.Forms.DialogResult]::No) { Set-UIBusy -Busy $false -Message ([char]0x26A0 + " Not an Autopilot device. Files saved in $extractTo") $lblStatus.ForeColor = $colWarning $textBox.Text = $extractTo return } } # Ready for analysis - select Autopilot Community (best for exported Autopilot data) $comboScript.SelectedIndex = 2 $textBox.Text = $extractTo $statusMsg = [char]0x2713 + " $($extractedFiles.Count) files extracted" if ($foundFiles.Count -gt 0) { $statusMsg += " (Autopilot data found)" } $statusMsg += " - click Analyze Path" Set-UIBusy -Busy $false -Message $statusMsg $lblStatus.ForeColor = $colSuccess } ######################################################################################### # Button Events ######################################################################################### $btnAnalyzeFolder.add_Click({ $path = $textBox.Text.Trim() if ([string]::IsNullOrWhiteSpace($path) -or -not (Test-Path $path)) { [System.Windows.Forms.MessageBox]::Show( "Please enter or drag & drop a valid folder, ZIP, or CAB file first.", "No Input", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information ) return } Start-Analysis -InputPath $path }) $btnAnalyzePC.add_Click({ Start-LocalAnalysis }) $btnExportLogs.add_Click({ Start-ExportLogs }) ######################################################################################### # Show Form ######################################################################################### [System.Windows.Forms.Application]::EnableVisualStyles() $form.ShowDialog() | Out-Null |