public/Start-WindowsUpdateTool.ps1

function Start-WindowsUpdateTool {
    [cmdletbinding()]
    Param (
        [parameter()]
        [string]$ComputerName = $env:COMPUTERNAME,
        [parameter()]
        [string]$Domain = $env:USERDNSDOMAIN
    )
    
    $SettingsRegPath = "HKEY_Current_User\Software\pXLabs\Windows Update Tool"
    $LogFile = "$($env:ProgramData)\pXLabs-WindowsUpdateTool\pXLabs_WindowsUpdateTool.log"
    $Script:SectionBreak = "----------------------------------------------"
    
    # Hide the console
    $SW_HIDE, $SW_SHOW = 0, 5
    $TypeDef = '[DllImport("User32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);'
    Add-Type -MemberDefinition $TypeDef -Namespace Win32 -Name Functions
    $hWnd = (Get-Process -Id $PID).MainWindowHandle
    $Null = [Win32.Functions]::ShowWindow($hWnd, $SW_HIDE)
    
    Add-Type -AssemblyName PresentationFramework
    Add-Type -AssemblyName PresentationCore
    Add-Type -AssemblyName WindowsBase
    Add-Type -AssemblyName System.Xaml
    Add-Type -AssemblyName System.Windows.Forms
    
    # Check if running as admin
    $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
    $isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    
    if (-not $isAdmin) {
        [System.Windows.MessageBox]::Show(
            "This tool must be run as Administrator. Please restart PowerShell as Administrator and try again.",
            "Administrator Privileges Required",
            'OK',
            'Warning'
        ) | Out-Null
        
        return
    }
    
    IF (-not (Test-Path "$($env:ProgramData)\pXLabs-WindowsUpdateTool")) {
        New-Item -Path "$($env:ProgramData)\pXLabs-WindowsUpdateTool" -Force -ItemType Directory | out-null
    }
    
    # Create a Windows Forms Timer object
    $script:timerJobTracker = New-Object System.Windows.Forms.Timer
    $script:timerJobTracker.Interval = 1000 # e.g., every 1 second
    
    # Add timer tick
    $timerJobTracker.Add_Tick({
            Update-JobTracker
        })
    
    # Stop the tracker if the form is closed while it is running
    $jobTracker_FormClosed = [System.Windows.Forms.FormClosedEventHandler]{
        Stop-JobTracker
    }
    
    if (-not $script:JobTrackerList) {
        $script:JobTrackerList = New-Object System.Collections.ArrayList
    }
            
    class UpdateItem : System.ComponentModel.INotifyPropertyChanged {
        # Microsoft Update (PSWindowsUpdate)
        [string]$Title
        [string]$KB
        [string]$Size
        [string]$Description
        [string]$Status
        [string]$Deadline
        [string]$DeploymentAction
        [bool]$IsDownloaded
        [bool]$IsInstalled
        [bool]$IsMandatory
        [bool]$IsPresent
        [string]$LastDeploymentChangeTime
        
        # CMUpdate (CCM_SoftwareUpdate)
        [string]$Name
        [string]$Publisher
        [string]$ArticleID
        [string]$StartTime
        [string]$PercentComplete
        [string]$State
        [string]$ErrorCode
        [string]$UpdateID
        [string]$EvaluationState
        
        hidden [bool]$isRunning
        hidden [System.ComponentModel.PropertyChangedEventHandler]$PropertyChanged
        
        UpdateItem() {
            $this.IsRunning = $false
        }
        
        [bool]get_IsRunning() { return $this.isRunning }
        [void]set_IsRunning([bool]$value) {
            $this.isRunning = $value
            $this.OnPropertyChanged("IsRunning")
        }
        
        [void]OnPropertyChanged([string]$propertyName) {
            if ($this.PropertyChanged) {
                $this.PropertyChanged.Invoke($this, [System.ComponentModel.PropertyChangedEventArgs]::new($propertyName))
            }
        }
        
        [void]add_PropertyChanged([System.ComponentModel.PropertyChangedEventHandler]$handler) {
            $this.PropertyChanged = [System.Delegate]::Combine($this.PropertyChanged, $handler)
        }
        
        [void]remove_PropertyChanged([System.ComponentModel.PropertyChangedEventHandler]$handler) {
            $this.PropertyChanged = [System.Delegate]::Remove($this.PropertyChanged, $handler)
        }
    }
    
    #region Load XAML
    $XamlPath = Join-Path $PSScriptRoot '..\ui\App.xaml'
    [xml]$xaml = Get-Content -Path $XamlPath
    $reader = (New-Object System.Xml.XmlNodeReader ([xml]$xaml))
    $window = [Windows.Markup.XamlReader]::Load($reader)
    $reader.Close()
    $reader.Dispose()
    
    # Find named controls
    $controls = @{ }
    $window.FindName("textbox_ComputerName") | ForEach-Object { $controls["ComputerName"] = $_ }
    $window.FindName("button_Ping") | ForEach-Object { $controls["Ping"] = $_ }
    $window.FindName("button_Clear") | ForEach-Object { $controls["Clear"] = $_ }
    $window.FindName("button_EventViewer") | ForEach-Object { $controls["EventViewer"] = $_ }
    $window.FindName("button_ExplorerHere") | ForEach-Object { $controls["ExplorerHere"] = $_ }
    $window.FindName("button_PSSessionHere") | ForEach-Object { $controls["PSSessionHere"] = $_ }
    $window.FindName("button_CheckServices") | ForEach-Object { $controls["CheckServices"] = $_ }
    $window.FindName("button_ResetWUComponents") | ForEach-Object { $controls["ResetWUComponents"] = $_ }
    $window.FindName("button_UpdateScan") | ForEach-Object { $controls["UpdateScan"] = $_ }
    $window.FindName("button_UpdateEvaluation") | ForEach-Object { $controls["UpdateEvaluation"] = $_ }
    $window.FindName("button_GetUpdateHistory") | ForEach-Object { $controls["GetUpdateHistory"] = $_ }
    $window.FindName("button_GetUpdates") | ForEach-Object { $controls["GetUpdates"] = $_ }
    $window.FindName("button_GetSettings") | ForEach-Object { $controls["GetSettings"] = $_ }
    $window.FindName("button_RefreshGPO") | ForEach-Object { $controls["RefreshGPO"] = $_ }
    $window.FindName("button_GetIntunePolicy") | ForEach-Object { $controls["GetIntunePolicy"] = $_ }
    $window.FindName("button_RefreshCMPolicy") | ForEach-Object { $controls["RefreshCMPolicy"] = $_ }
    $window.FindName("button_RestartCMAgent") | ForEach-Object { $controls["RestartCMAgent"] = $_ }
    $window.FindName("datagridview_UpdateList") | ForEach-Object { $controls["UpdateList"] = $_ }
    $window.FindName("richtextbox_Output") | ForEach-Object { $controls["Output"] = $_ }
    $window.FindName("toolstripstatuslabel_Status") | ForEach-Object { $controls["Status"] = $_ }
    $window.FindName("toolstripstatuslabel_SessionType") | ForEach-Object { $controls["SessionType"] = $_ }
    $window.FindName("toolstripstatuslabel_UpdateMethod") | ForEach-Object { $controls["UpdateMethod"] = $_ }
    $window.FindName("toolstripstatuslabel_Diskspace") | ForEach-Object { $controls["Diskspace"] = $_ }
    $window.FindName("progressbar_Status") | ForEach-Object { $controls["Progressbar"] = $_ }
    
    $groupboxes = @{ }
    $window.FindName("groupbox_CMUpdate") | ForEach-Object { $groupboxes["CMUpdate"] = $_ }
    $window.FindName("groupbox_MSUpdate") | ForEach-Object { $groupboxes["MSUpdate"] = $_ }
    $window.FindName("groupbox_Policy") | ForEach-Object { $groupboxes["Policy"] = $_ }
    
    $menuItems = @{ }
    $window.FindName("menuItem_InvokeDeviceSync") | ForEach-Object { $menuItems["InvokeDeviceSync"] = $_ }
    $window.FindName("menuItem_GetDeviceStatus") | ForEach-Object { $menuItems["GetDeviceStatus"] = $_ }
    $window.FindName("menuItem_GetComplianceState") | ForEach-Object { $menuItems["GetComplianceState"] = $_ }
    $window.FindName("menuItem_GetAssignedConfigurations") | ForEach-Object { $menuItems["GetAssignedConfigurations"] = $_ }
    $window.FindName("menuItem_GetIntuneUpdatePolicy") | ForEach-Object { $menuItems["GetIntuneUpdatePolicy"] = $_ }
    $window.FindName("menuItem_InstallUpdate") | ForEach-Object { $menuItems["InstallUpdate"] = $_ }
    $window.FindName("menuItem_DarkTheme") | ForEach-Object { $menuItems["DarkTheme"] = $_ }
    $window.FindName("menuItem_LightTheme") | ForEach-Object { $menuItems["LightTheme"] = $_ }
    $window.FindName("menuItem_MonokaiTheme") | ForEach-Object { $menuItems["MonokaiTheme"] = $_ }
    $window.FindName("menuItem_NordTheme") | ForEach-Object { $menuItems["NordTheme"] = $_ }
    $window.FindName("menuItem_EverForestTheme") | ForEach-Object { $menuItems["EverForestTheme"] = $_ }
    #endregion
    
    #Region Set control tooltips
    Set-ControlToolTip -ControlName "Ping" -Message "Ping computer (disabled for local sessions)"
    Set-ControlToolTip -ControlName "Clear" -Message "Clean up output"
    Set-ControlToolTip -ControlName "EventViewer" -Message "Open eventviewer"
    Set-ControlToolTip -ControlName "ExplorerHere" -Message "Open an explorer window"
    Set-ControlToolTip -ControlName "PSSessionHere" -Message "Opens remote PowerShell session (disabled for local sessions)"
    Set-ControlToolTip -ControlName "CheckServices" -Message "Check services related to Windows Update processes"
    Set-ControlToolTip -ControlName "ResetWUComponents" -Message "Reset Windows Update components"
    Set-ControlToolTip -ControlName "UpdateScan" -Message "Scan for missing updates against CMUpdate (disabled if a CMUpdate server is not found)"
    Set-ControlToolTip -ControlName "UpdateEvaluation" -Message "Evaluate Update deployments and check if updates should be installed (disabled if a CMUpdate server is not found)"
    Set-ControlToolTip -ControlName "RestartCMAgent" -Message "Restarts the MECM client agent (disabled if a CMUpdate server is not found)"
    Set-ControlToolTip -ControlName "GetUpdateHistory" -Message "Gets Windows Update History"
    Set-ControlToolTip -ControlName "GetUpdates" -Message "Forces an Update scan against Microsoft Updates"
    Set-ControlToolTip -ControlName "GetSettings" -Message "Gets the Windows Update settings"
    Set-ControlToolTip -ControlName "RefreshGPO" -Message "Invokes a GPUpdate /force"
    Set-ControlToolTip -ControlName "GetIntunePolicy" -Message "Invokes an Intune Policy refresh"
    Set-ControlToolTip -ControlName "RefreshCMPolicy" -Message "Invokes a CM Policy refresh (disabled if a CMUpdate server is not found)"
    #endregion
    
    #region Controls
    $script:storyboard = $controls["GetUpdates"].Resources["PulseAnimation"]
    
    # Button Event: ComputerName
    $controls["ComputerName"].Add_LostFocus({
            $controls["ComputerName"].Text = $controls["ComputerName"].Text.ToUpper()
            Invoke-SessionLoad -SessionLoad $SessionLoad
        })
    
    # Button Event: ComputerName
    $controls["ComputerName"].Add_KeyDown({
            if ($_.Key -eq 'Enter') {
                $controls["ComputerName"].Text = $controls["ComputerName"].Text.ToUpper()
                Invoke-SessionLoad -SessionLoad $SessionLoad
            }
        })
    
    # Button Event: Ping
    $controls["Ping"].Add_Click({
            $controls["Status"].Text = "Status: Pinging..."
            
            $computer = $controls["ComputerName"].Text
            if ([string]::IsNullOrWhiteSpace($computer)) {
                Write-OutputBox " Computer name is empty."
                return
            }
            
            if ([string]::IsNullOrWhiteSpace($computer)) {
                Write-OutputBox " Please enter a computer name."
                return
            }
            
            Write-OutputBox "Pinging $computer..."
            
            if (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
                Write-OutputBox " $computer is online."
            } else {
                Write-OutputBox " $computer is offline or unreachable."
            }
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: Clear
    $controls["Clear"].Add_Click({
            Clear-WpfDataGrid -DataGrid $controls["UpdateList"]
            $controls["ComputerName"].Clear()
            $controls["Output"].Document.Blocks.Clear()
            $controls["Status"].Text = "Status: Cleared"
        })
    
    # Button Event: EventViewer
    $controls["EventViewer"].Add_Click({
            Start-Process eventvwr
        })
    
    # Button Event: ExplorerHere
    $controls["ExplorerHere"].Add_Click({
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox " Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
            }
            
            If (Test-Path "\\$Computer\c`$\Windows\CCM\Logs") {
                Start-Process explorer -ArgumentList "\\$Computer\c`$\Windows\CCM\Logs"
            } elseif (Test-Path "\\$Computer\c`$") {
                Start-Process explorer -ArgumentList "\\$Computer\c`$"
            } Else {
                Write-Prompt -PromptText " $Computer unavailable for connection." -PromptTitle "Warning" -PromptType 16
            }
        })
    
    # Button Event: PSSessionHere
    $controls["PSSessionHere"].Add_Click({
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
            }
            
            Start-Process powershell -ArgumentList "-noexit -command (enter-pssession $($Computer))"
        })
    
    # Button Event: CheckServices
    $controls["CheckServices"].Add_Click({
            $controls["Status"].Text = "Status: Checking services..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$SectionBreak`nChecking Windows Update services..."
            
            IF ($SessionType -eq "Remote") {
                $services = Get-Service -ComputerName $computer wuauserv, bits, cryptsvc, msiserver | Select-Object Name, Status
            } Else {
                $services = Get-Service wuauserv, bits, cryptsvc, msiserver | Select-Object Name, Status
            }
            
            Write-OutputBox "$SectionBreak`n Windows Update services`n$SectionBreak".Trim() -ReplaceLastLine
            Write-OutputBox " $($services | out-string)"
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: ResetWUComponents
    $controls["ResetWUComponents"].Add_Click({
            $controls["Status"].Text = "Status: Resetting WU Components..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$SectionBreak`nResetting Windows Update Components..."
            
            $storyboard.Begin($controls["ResetWUComponents"])
            $controls["Progressbar"].Visibility = 'Visible'
            $controls["Progressbar"].IsIndeterminate = $true
            
            $paramAddJobTracker = @{
                Name      = "ResetWUComponentsJob"
                JobScript = {
                    Param (
                        [string]$computer,
                        [string]$SessionType,
                        [PSCredential]$cred
                    )
                    
                    try {
                        $Scriptblock = {
                            Try {
                                Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
                            } catch {
                                $_
                            }
                            
                            Import-Module PSWindowsUpdate
                            Reset-WUComponents
                        }
                        
                        if ($SessionType -eq "Local") {
                            $Result = Invoke-Command -ScriptBlock $Scriptblock
                        } else {
                            If (-Not (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-PSSessionConfiguration -Name 'VirtualAccount' -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> )) { 
                                Invoke-Command -ComputerName $Computer -ScriptBlock { New-PSSessionConfigurationFile -RunAsVirtualAccount -Path .\VirtualAccount.pssc } #-UseSSL -Credential $cred
                                Invoke-Command -ComputerName $Computer -ScriptBlock { Register-PSSessionConfiguration -Name 'VirtualAccount' -Path .\VirtualAccount.pssc -Force -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> | out-null
                            }
                            
                            $Result = Invoke-Command -ComputerName $Computer -HideComputerName -ScriptBlock $Scriptblock -ConfigurationName 'VirtualAccount' #-UseSSL -Credential $cred
                        }
                        
                        $Result
                    } catch {
                        Write-Output @{
                            Success = $false
                            Error   = $_.Exception.Message
                        }
                    }
                }
                
                ArgumentList = $computer, $SessionType, $cred
                
                CompletedScript = {
                    Param ([System.Management.Automation.Job]$Job)
                    
                    # Stop animation and reset progress UI
                    $controls["ResetWUComponents"].BeginAnimation([System.Windows.UIElement]::OpacityProperty, $null)
                    $controls["Progressbar"].IsIndeterminate = $false
                    $controls["Progressbar"].Visibility = 'Collapsed'
                    
                    # Handle job-level failure
                    if ($Job.State -eq 'Failed') {
                        $reason = $Job.ChildJobs[0].JobStateInfo.Reason.Message
                        Write-OutputBox " Job failed: $reason"
                        $controls["Status"].Text = "Status: Failed"
                        return
                    }
                    
                    try {
                        # Collect all job results
                        $results = Receive-Job -Job $Job -ErrorAction Stop
                        
                        if ($results -is [System.Management.Automation.ErrorRecord]) {
                            Write-OutputBox " ERROR: $($results.ToString())"
                            $controls["Status"].Text = "Status: Error"
                            return
                        }
                        
                        # Handle output from job if it's a structured hashtable
                        if ($results -is [hashtable]) {
                            if ($results.ContainsKey("Success") -and -not $results["Success"]) {
                                $errorMessage = $results["Error"] #?? "Unknown error"
                                Write-OutputBox " ERROR: $errorMessage"
                                $controls["Status"].Text = "Status: Failed"
                                return
                            }
                        }
                        
                        # If no errors
                        Write-OutputBox " Windows Update Components reset completed"
                        $controls["Status"].Text = "Status: Ready"
                    } catch {
                        Write-OutputBox "Failed to process job results: $($_.Exception.Message)"
                        $controls["Status"].Text = "Status: Failed"
                    }
                }                
                
                UpdateScript = {
                    Param ([System.Management.Automation.Job]$Job)
                }
            }
            
            Add-JobTracker @paramAddJobTracker
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: GetUpdateHistory
    $controls["GetUpdateHistory"].Add_Click({
            $controls["Status"].Text = "Status: Getting updates..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                    $script:QuickFixHistory = Get-CimInstance -ClassName Win32_QuickFixEngineering
                } Else {
                    $SessionType = "Remote"
                    $RemoteCimSession = New-CimSession -ComputerName $computer #-Credential $cred
                    $script:QuickFixHistory = Get-CimInstance -ComputerName $Computer -ClassName Win32_QuickFixEngineering
                    Remove-CimSession -CimSession $RemoteCimSession
                }
            }
            
            Write-OutputBox "$Sectionbreak`nGetting Update History..."
            
            $storyboard.Begin($controls["GetUpdateHistory"])
            $controls["Progressbar"].Visibility = 'Visible'
            $controls["Progressbar"].IsIndeterminate = $true
            
            $paramAddJobTracker = @{
                Name      = "GetUpdateHistoryJob"
                JobScript = {
                    Param (
                        [string]$computer,
                        [string]$SessionType,
                        [PSCredential]$cred
                    )
                    
                    try {
                        $Scriptblock = {
                            Param (
                                [string]$Computer
                            )
                            
                            Try {
                                Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
                            } catch {
                                $_
                            }
                            
                            Import-Module PSWindowsUpdate
                            Get-WUHistory | Select-object KB, Date, Title, Description, Result -ExcludeProperty RunspaceId
                        }
                        
                        if ($SessionType -eq "Local") {
                            $UpdateHistory = Invoke-Command -ScriptBlock $Scriptblock
                        } else {
                            IF (-Not (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-PSSessionConfiguration -Name 'VirtualAccount' -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #>)) {
                                Invoke-Command -ComputerName $Computer -ScriptBlock { New-PSSessionConfigurationFile -RunAsVirtualAccount -Path .\VirtualAccount.pssc } #-UseSSL -Credential $cred
                                Invoke-Command -ComputerName $Computer -ScriptBlock { Register-PSSessionConfiguration -Name 'VirtualAccount' -Path .\VirtualAccount.pssc -Force -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> | out-null
                            }
                            
                            $UpdateHistory = Invoke-Command -ComputerName $Computer -HideComputerName -ScriptBlock $Scriptblock -ConfigurationName 'VirtualAccount' #-UseSSL -Credential $cred
                        }
                        
                        $UpdateHistory
                    } catch {
                        Write-Output @{
                            Success = $false
                            Error   = $_.Exception.Message
                        }
                    }
                }
                
                ArgumentList = $computer, $SessionType, $cred
                
                JobData   = @{
                    ComputerName = $computer
                    Sectionbreak = $Sectionbreak
                }
                
                CompletedScript = {
                    Param (
                        [System.Management.Automation.Job]$Job,
                        $JobData
                    )
                    
                    # Stop animation and progress
                    $controls["GetUpdateHistory"].BeginAnimation([System.Windows.UIElement]::OpacityProperty, $null)
                    $controls["Progressbar"].IsIndeterminate = $false
                    $controls["Progressbar"].Visibility = 'Collapsed'
                    
                    # Check if the job itself failed
                    if ($Job.State -eq 'Failed') {
                        $reason = $Job.ChildJobs[0].JobStateInfo.Reason.Message
                        Write-OutputBox " Job failed: $reason"
                        $controls["Status"].Text = "Status: Failed"
                        return
                    }
                    
                    try {
                        # Safely receive job results
                        $results = Receive-Job -Job $Job -ErrorAction Stop
                        
                        # Handle known ErrorRecord
                        if ($results -is [System.Management.Automation.ErrorRecord]) {
                            Write-OutputBox " ERROR: $($results.ToString())"
                            $controls["Status"].Text = "Status: Error"
                            return
                        }
                        
                        # Handle no results
                        if (-not $results) {
                            Write-OutputBox " WARNING: No update history returned."
                            $controls["Status"].Text = "Status: Warning"
                            return
                        }
                        
                        # Output structured update history
                        Write-OutputBox "$($JobData.SectionBreak)`n $($JobData.ComputerName.ToUpper()) Update History`n$($JobData.SectionBreak)" -ReplaceLastLine
                        Write-OutputBox "$($results | Select-Object KB, Date, Title, Description, Result -ExcludeProperty RunspaceId | Out-String)".Trim()
                        
                        # Output QuickFixEngineering info
                        Write-OutputBox "$($JobData.SectionBreak)`n $($JobData.ComputerName.ToUpper()) QuickFixEngineering History`n$($JobData.SectionBreak)"
                        Write-OutputBox "$($script:QuickFixHistory | Select-Object Description, HotFixID, InstalledBy, InstalledOn -ExcludeProperty PSComputerName | Sort-Object InstalledOn | Out-String)".Trim()
                        
                        $controls["Status"].Text = "Status: Ready"
                    } catch {
                        # Catch unexpected issues
                        Write-OutputBox "Failed to process job results: $($_.Exception.Message)"
                        $controls["Status"].Text = "Status: Failed"
                    }
                }                
                
                UpdateScript = {
                    Param ([System.Management.Automation.Job]$Job)
                }
            }
            
            Add-JobTracker @paramAddJobTracker
        })
    
    # Button Event: GetUpdates
    $controls["GetUpdates"].Add_Click({
            $controls["Status"].Text = "Status: Getting updates..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$Sectionbreak`nGetting Updates..."
            
            $storyboard.Begin($controls["GetUpdates"])
            $controls["Progressbar"].Visibility = 'Visible'
            $controls["Progressbar"].IsIndeterminate = $true
            
            $paramAddJobTracker = @{
                Name      = "GetUpdatesJob"
                JobScript = {
                    Param (
                        [string]$computer,
                        [string]$SessionType,                        
                        [object]$CMClientPresent,
                        [PSCredential]$cred
                    )
                    
                    try {
                        if ($CMClientPresent) {
                            $Scriptblock = {
                                Get-CimInstance -Query "SELECT * FROM CCM_SoftwareUpdate" -Namespace "ROOT\ccm\ClientSDK"
                            }
                        } else {
                            $Scriptblock = {
                                Try {
                                    Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
                                } catch {
                                    $_
                                }
                                
                                Import-Module PSWindowsUpdate -Force
                                Get-WindowsUpdate
                            }
                        }
                        
                        if ($SessionType -eq "Local") {
                            $Updates = Invoke-Command -ScriptBlock $Scriptblock
                        } else {
                            IF (-Not (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-PSSessionConfiguration -Name 'VirtualAccount' -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #>)) {
                                Invoke-Command -ComputerName $Computer -ScriptBlock { New-PSSessionConfigurationFile -RunAsVirtualAccount -Path .\VirtualAccount.pssc } #-UseSSL -Credential $cred
                                Invoke-Command -ComputerName $Computer -ScriptBlock { Register-PSSessionConfiguration -Name 'VirtualAccount' -Path .\VirtualAccount.pssc -Force -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> | out-null
                            }
                            
                            $Updates = Invoke-Command -ComputerName $Computer -HideComputerName -ScriptBlock $Scriptblock -ConfigurationName 'VirtualAccount' #-UseSSL -Credential $cred
                        }
                        
                        $Updates
                    } catch {
                        Write-Output @{
                            Success = $false
                            Error   = $_.Exception.Message
                        }
                    }
                }
                
                ArgumentList = $computer, $SessionType, $CMClientPresent, $cred
                
                JobData   = @{
                    ComputerName = $computer
                    Sectionbreak = $Sectionbreak
                }
                
                CompletedScript = {
                    Param (
                        [System.Management.Automation.Job]$Job,
                        $JobData
                    )
                    
                    # Stop animation and progress
                    $controls["GetUpdates"].BeginAnimation([System.Windows.UIElement]::OpacityProperty, $null)
                    $controls["Progressbar"].IsIndeterminate = $false
                    $controls["Progressbar"].Visibility = 'Collapsed'
                    
                    # Job failure check
                    if ($Job.State -eq 'Failed') {
                        $reason = $Job.ChildJobs[0].JobStateInfo.Reason.Message
                        Write-OutputBox " Job failed: $reason"
                        $controls["Status"].Text = "Status: Failed"
                        return
                    }
                    
                    try {
                        # Safely retrieve results
                        $results = Receive-Job -Job $Job -ErrorAction Stop
                        
                        # Handle if it's a direct error object
                        if ($results -is [System.Management.Automation.ErrorRecord]) {
                            Write-OutputBox " ERROR: $($results.ToString())"
                            $controls["Status"].Text = "Status: Error"
                            return
                        }
                        
                        # Handle empty result set
                        if (-not $results) {
                            Write-OutputBox " No updates returned."
                            $controls["Status"].Text = "Status: No Updates"
                            return
                        }
                        
                        # Safely build the update items list
                        $updateItems = foreach ($r in $results) {
                            try {
                                $item = [UpdateItem]::new()
                                
                                if (-not $CMClient) {
                                    $item.KB = $r.KB
                                    $item.Size = $r.Size
                                    $item.Title = $r.Title
                                    $item.Description = $r.Description
                                    $item.Status = $r.Status
                                    $item.Deadline = "$($r.Deadline)"
                                    $item.DeploymentAction = $r.DeploymentAction
                                    $item.IsDownloaded = $r.IsDownloaded
                                    $item.IsInstalled = $r.IsInstalled
                                    $item.IsMandatory = $r.IsMandatory
                                    $item.IsPresent = $r.IsPresent
                                    $item.LastDeploymentChangeTime = "$($r.LastDeploymentChangeTime)"
                                } else {
                                    $item.Name = $r.Name
                                    $item.Publisher = $r.Publisher
                                    $item.ArticleID = $r.ArticleID
                                    $item.StartTime = $r.StartTime
                                    $item.Deadline = $r.Deadline
                                    $item.PercentComplete = "$($r.PercentComplete)"
                                    $item.State = $r.State
                                    $item.ErrorCode = "$($r.ErrorCode)"
                                    $item.UpdateID = $r.UpdateID
                                    $item.Description = $r.Description
                                    $item.EvaluationState = "$($r.EvaluationState)"
                                }
                                
                                $item
                            } catch {
                                Write-OutputBox " Failed to parse update item: $($_.Exception.Message)"
                            }
                        }
                        
                        # Update the UI with parsed items
                        Clear-WpfDataGrid -DataGrid $controls["UpdateList"]
                        Update-WpfDataGrid -DataGrid $controls["UpdateList"] -Item $updateItems -AutoSizeColumns $true
                        
                        Write-OutputBox "$($JobData.SectionBreak)`n Available Updates`n$($JobData.SectionBreak)" -ReplaceLastLine
                        Write-OutputBox "$($results | Select-Object Status, KB, Size, Title, RebootRequired -ExcludeProperty RunspaceId | Out-String)".Trim()
                        
                        $controls["Status"].Text = "Status: Ready"
                    } catch {
                        Write-OutputBox " ERROR: Failed to process job results: $($_.Exception.Message)"
                        $controls["Status"].Text = "Status: Failed"
                    }
                }                
                
                UpdateScript = {
                    Param ([System.Management.Automation.Job]$Job)
                }
            }
            
            Add-JobTracker @paramAddJobTracker
        })
    
    # Button Event: GetSettings
    $controls["GetSettings"].Add_Click({
            $controls["Status"].Text = "Status: Getting settings..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            IF ($SessionType -eq "Remote") {
                $WUSettings = invoke-command -computername $Computer -HideComputerName -ScriptBlock { import-module PSWindowsUpdate -Force; Get-WUSettings } #-UseSSL -Credential $cred
            } Else {
                $WUSettings = Get-WUSettings
            }
            
            Write-OutputBox "$SectionBreak`n Windows Update Settings`n$Sectionbreak"
            IF ($WUSettings) {
                Write-OutputBox "$($WUSettings | format-list | Out-string)"
            } Else {
                Write-OutputBox " No settings found."
            }
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: UpdateScan
    $controls["UpdateScan"].Add_Click({
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            $Scriptblock = {
                Invoke-CimMethod -Namespace "ROOT\ccm" -ClassName "SMS_Client" -MethodName "TriggerSchedule" -Arguments @{ sScheduleID = "{00000000-0000-0000-0000-000000000113}" }
            }
            
            If ($SessionType -eq "Remote") {
                $result = invoke-command -computername $Computer -HideComputerName -ScriptBlock $Scriptblock #-UseSSL -Credential $cred
            } Else {
                $result = invoke-command -ScriptBlock $Scriptblock
            }
            
            If (-not $result.ReturnValue) {
                $result = "Successfully started"
            } Else {
                $result = $result.ReturnValue
            }
            
            Write-OutputBox " Result: $($result)"
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: UpdateEvaluation
    $controls["UpdateEvaluation"].Add_Click({
            $controls["Status"].Text = "Status: Running update evaluation..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$SectionBreak`nStarting CM update evaluation..."
            
            $Scriptblock = {
                Invoke-CimMethod -Namespace "ROOT\ccm" -ClassName "SMS_Client" -MethodName "TriggerSchedule" -Arguments @{ sScheduleID = "{00000000-0000-0000-0000-000000000108}" }
            }
            
            If ($SessionType -eq "Remote") {
                $result = invoke-command -computername $Computer -HideComputerName -ScriptBlock { $Scriptblock } #-UseSSL -Credential $cred
            } Else {
                $result = invoke-command -ScriptBlock $Scriptblock
            }
            
            If (-not $result.ReturnValue) {
                $result = "Successfully started"
            } Else {
                $result = $result.ReturnValue
            }
            
            Write-OutputBox " Update Evaluation Results`n$SectionBreak" -ReplaceLastLine
            Write-OutputBox " Result: $($result)"
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: RefreshGPO
    $controls["RefreshGPO"].Add_Click({
            $controls["Status"].Text = "Status: Refreshing GPO..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$SectionBreak`nRefreshing Group Policy..."
            
            $storyboard.Begin($controls["RefreshGPO"])
            $controls["Progressbar"].Visibility = 'Visible'
            $controls["Progressbar"].IsIndeterminate = $true
            
            $paramAddJobTracker = @{
                Name      = "RefreshGPOJob"
                JobScript = {
                    Param (
                        [string]$computer,
                        [string]$SessionType,
                        [PSCredential]$cred
                    )
                    
                    try {
                        $Scriptblock = {
                            $result = (Start-Process -FilePath gpupdate -ArgumentList "/force" -Wait -PassThru).ExitCode
                            
                            If ($result -eq 0) {
                                $output = "Successful"
                            } Else {
                                $output = "Unsuccessful"
                            }
                            
                            $output | Out-File "C:\gporesult.txt"
                            $output
                        }
                        
                        if ($SessionType -eq "Local") {
                            $Result = Invoke-Command -ScriptBlock $Scriptblock
                        } else {
                            IF (-Not (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-PSSessionConfiguration -Name 'VirtualAccount' -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #>)) {
                                Invoke-Command -ComputerName $Computer -ScriptBlock { New-PSSessionConfigurationFile -RunAsVirtualAccount -Path .\VirtualAccount.pssc } #-UseSSL -Credential $cred
                                Invoke-Command -ComputerName $Computer -ScriptBlock { Register-PSSessionConfiguration -Name 'VirtualAccount' -Path .\VirtualAccount.pssc -Force -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> | out-null
                            }
                            
                            $Result = Invoke-Command -ComputerName $Computer -HideComputerName -ScriptBlock $Scriptblock -ConfigurationName 'VirtualAccount' #-UseSSL -Credential $cred
                        }
                        
                        $Result
                    } catch {
                        Write-Output @{
                            Success = $false
                            Error   = $_.Exception.Message
                        }
                    }
                }
                
                ArgumentList = $computer, $SessionType, $cred
                
                CompletedScript = {
                    Param ([System.Management.Automation.Job]$Job)
                    
                    $controls["RefreshGPO"].BeginAnimation([System.Windows.UIElement]::OpacityProperty, $null)
                    $controls["Progressbar"].IsIndeterminate = $false
                    $controls["Progressbar"].Visibility = 'Collapsed'
                    
                    if ($Job.State -eq 'Failed') {
                        $reason = $Job.ChildJobs[0].JobStateInfo.Reason.Message
                        Write-OutputBox " Job failed: $reason"
                        $controls["Status"].Text = "Status: Failed"
                        return
                    }
                    
                    try {
                        $results = Receive-Job -Job $Job -ErrorAction Stop
                        
                        if ($results -is [System.Management.Automation.ErrorRecord]) {
                            Write-OutputBox " ERROR: $($results.ToString())"
                            $controls["Status"].Text = "Status: Error"
                            return
                        }
                        
                        if (-not $results) {
                            Write-OutputBox " WARNING: No results returned."
                            $controls["Status"].Text = "Status: No Results"
                            return
                        }
                        
                        Write-OutputBox " Result: $results"
                        $controls["Status"].Text = "Status: Ready"
                    } catch {
                        Write-OutputBox "Failed to process job results: $($_.Exception.Message)"
                        $controls["Status"].Text = "Status: Failed"
                    }
                }
                
                
                UpdateScript = {
                    Param ([System.Management.Automation.Job]$Job)
                }
            }
            
            Add-JobTracker @paramAddJobTracker
        })
    
    # Button Event: GetIntunePolicy
    $controls["GetIntunePolicy"].Add_Click({
            $controls["Status"].Text = "Status: Getting Intune policy..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox $Sectionbreak
            Write-OutputBox "Refreshing Intune Policies..."
            
            $Scriptblock = {
                $Tasks = Get-ScheduledTask | Where-Object { $_.TaskName -eq "Schedule #3 created by enrollment client" }
                
                IF (-NOT $Tasks) {
                    return "No Task"
                }
                
                $Tasks | ForEach-Object {
                    Start-ScheduledTask -TaskPath $_.TaskPath -TaskName $_.TaskName
                    Start-Sleep 5
                }
            }
            
            If ($SessionType -eq "Remote") {
                $result = invoke-command -computername $Computer -HideComputerName -ScriptBlock { $Scriptblock } #-UseSSL -Credential $cred
            } Else {
                $result = invoke-command -ScriptBlock $Scriptblock
            }
            
            If ($result -eq "No Task") {
                $result = "No Intune policy to refresh"
            } Else {
                $result = "Successfully started"
            }
            
            Write-OutputBox " Result: $result"
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: RefreshCMPolicy
    $controls["RefreshCMPolicy"].Add_Click({
            $controls["Status"].Text = "Status: Refreshing CM policy..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox $SectionBreak
            Write-OutputBox "Starting CM policy refresh..."
            
            $Scriptblock = {
                If (Get-CimClass -Namespace 'ROOT\ccm' -ClassName 'SMS_Client' -ErrorAction SilentlyContinue) {
                    Invoke-CimMethod -Namespace "ROOT\ccm" -ClassName "SMS_Client" -MethodName "TriggerSchedule" -Arguments @{ sScheduleID = "{00000000-0000-0000-0000-000000000021}" }
                } Else {
                    return "No CM Client"
                }
            }
            
            If ($SessionType -eq "Remote") {
                $result = invoke-command -computername $Computer -HideComputerName -ScriptBlock { $Scriptblock } #-UseSSL -Credential $cred
            } Else {
                $result = invoke-command -ScriptBlock $Scriptblock
            }
            
            If ($result -eq "No CM Client") {
                
            } elseif ($null -eq $result.ReturnValue) {
                $result = "Successfully started"
            } Else {
                $result = $result.ReturnValue
            }
            
            Write-OutputBox " Result: $($result)"
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: RestartCMAgent
    $controls["RestartCMAgent"].Add_Click({
            $controls["Status"].Text = "Status: Restarting CM agent..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
    <#
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
#>

            }
            
            Write-OutputBox $SectionBreak
            Write-OutputBox "Restarting CM agent..."
            
            IF (Get-Service -ComputerName "$Computer" -name ccmexec -ErrorAction SilentlyContinue) {
                Restart-CMAgent -Computername $Computer
                Write-OutputBox " CM restart command sent."
            } Else {
                Write-OutputBox " CM service not found."
            }
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Button Event: UpdateList
    $controls["UpdateList"].Add_PreviewMouseRightButtonDown({
            param ($sender,
                $e)
            
            $originalSource = $e.OriginalSource
            
            while ($originalSource -and -not ($originalSource -is [System.Windows.Controls.DataGridRow])) {
                $originalSource = $originalSource.Parent
            }
            
            if ($originalSource -is [System.Windows.Controls.DataGridRow]) {
                $originalSource.IsSelected = $true
            }
        })
    
    # Menu Event: InstallUpdate
    $menuItems["InstallUpdate"].Add_Click({
            $controls["Status"].Text = "Status: Installing updates..."
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = Set-Computername -ComputerName $controls["ComputerName"].Text
                
                IF ($controls["ComputerName"].Text.ToUpper() -eq $env:computername.ToUpper()) {
                    $SessionType = "Local"
                } Else {
                    $SessionType = "Remote"
                }
            }
            
            Write-OutputBox "$Sectionbreak".Trim()
            $controls["Progressbar"].Visibility = 'Visible'
            $controls["Progressbar"].IsIndeterminate = $true
            
            $selectedItems = $controls["UpdateList"].SelectedItems
            
            if ($null -ne $selectedItems) {
                foreach ($item in $selectedItems) {
                    if ($item.PSObject.Properties.Match("Title") -and $item.Title) {
                        $Title = $item.Title
                    }
                    
                    if ($item.PSObject.Properties.Match("KB") -and $item.KB) {
                        $kbOrId = $item.KB
                    } elseif ($item.PSObject.Properties.Match("UpdateId") -and $item.UpdateId) {
                        $kbOrId = $item.UpdateId
                    } else {
                        #Write-OutputBox "WARNING: No KB or UpdateId found for item: $($item | Out-String)"
                        
                        #$controls["Progressbar"].IsIndeterminate = $false
                        #$controls["Progressbar"].Visibility = 'Collapsed'
                        
                        #return
                        $kbOrId = "NoKBOrId"
                    }
                    
                    Write-OutputBox "Installing update: $kbOrId - $Title"
                    
                    $paramAddJobTracker = @{
                        Name      = "InstallUpdateJob"
                        JobScript = {
                            Param (
                                [string]$computer,
                                [string]$SessionType,
                                [string]$Title,
                                [string]$UpdateID,                                
                                [object]$CMClientPresent,
                                [PSCredential]$cred
                            )
                            
                            try {
                                if ($CMClientPresent) {
                                    $Scriptblock = {
                                        $updates = Get-CimInstance -Namespace "ROOT\ccm\ClientSDK" -ClassName "CCM_SoftwareUpdate" -Filter "UpdateID LIKE '$UpdateID'" -CimSession $cimSession
                                        Invoke-CimMethod -Namespace "ROOT\ccm\ClientSDK" -ClassName "CCM_SoftwareUpdatesManager" -MethodName "InstallUpdates" -Arguments @{ CCMUpdates = $updates } -CimSession $cimSession
                                        
                                        Write-output ' Installation invoked. Please use the `"Get Updates`" button to check on progress.'
                                    }
                                } else {
                                    $Scriptblock = {
                                        Try {
                                            Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
                                        } catch {
                                            $_
                                        }
                                        
                                        Import-Module PSWindowsUpdate
                                        
                                        If ($UpdateID -ne "NoKBOrId") {
                                            Install-WindowsUpdate -AcceptAll -IgnoreReboot -KBArticleID $UpdateID
                                        } Else {
                                            Install-WindowsUpdate -AcceptAll -IgnoreReboot -Title "$Title"
                                        }                                        
                                    }
                                }
                                
                                if ($SessionType -eq "Local") {
                                    $Result = Invoke-Command -ScriptBlock $Scriptblock
                                } else {
                                    IF (-Not (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-PSSessionConfiguration -Name 'VirtualAccount' -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #>)) {
                                        Invoke-Command -ComputerName $Computer -ScriptBlock { New-PSSessionConfigurationFile -RunAsVirtualAccount -Path .\VirtualAccount.pssc } #-UseSSL -Credential $cred
                                        Invoke-Command -ComputerName $Computer -ScriptBlock { Register-PSSessionConfiguration -Name 'VirtualAccount' -Path .\VirtualAccount.pssc -Force -ErrorAction SilentlyContinue } <# -UseSSL -Credential $cred #> | out-null
                                    }
                                    
                                    $Result = Invoke-Command -ComputerName $Computer -ScriptBlock $Scriptblock -ConfigurationName 'VirtualAccount' #-UseSSL -Credential $cred
                                }
                                
                                $Result
                            } catch {
                                Write-Output @{
                                    Success = $false
                                    Error   = $_.Exception.Message
                                }
                            }
                        }
                        
                        ArgumentList = $computer, $SessionType, $Title, $kbOrId, $CMClientPresent, $cred
                        
                        CompletedScript = {
                            Param ([System.Management.Automation.Job]$Job)
                            
                            $controls["Progressbar"].IsIndeterminate = $false
                            $controls["Progressbar"].Visibility = 'Collapsed'
                            
                            if ($Job.State -eq 'Failed') {
                                $reason = $Job.ChildJobs[0].JobStateInfo.Reason.Message
                                Write-OutputBox "Job failed: $reason"
                                $controls["Status"].Text = "Status: Failed"
                                return
                            }
                            
                            try {
                                $results = Receive-Job -Job $Job -ErrorAction Stop
                                
                                if ($results -is [System.Management.Automation.ErrorRecord]) {
                                    Write-OutputBox " ERROR: $($results.ToString())"
                                    $controls["Status"].Text = "Status: Error"
                                    return
                                }
                                
                                if (-not $results) {
                                    Write-OutputBox " No installation performed"
                                    $controls["Status"].Text = "Status: No Changes"
                                    return
                                }
                                
                                Write-OutputBox "$($results | Select-Object Result, KB, Size, Title | Out-String)"
                                $controls["Status"].Text = "Status: Ready"
                            } catch {
                                Write-OutputBox "Failed to process job results: $($_.Exception.Message)"
                                $controls["Status"].Text = "Status: Failed"
                            }
                        }                        
                        
                        UpdateScript = {
                            Param ([System.Management.Automation.Job]$Job)
                            
                            $controls["Progressbar"].Visibility = 'Visible'
                            $controls["Progressbar"].IsIndeterminate = $true
                        }
                    }
                    
                    Add-JobTracker @paramAddJobTracker
                }
            } else {
                Write-OutputBox "No update selected."
            }
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: InvokeDeviceSync
    $menuItems["InvokeDeviceSync"].Add_Click({
            $controls["Status"].Text = "Status: Invoking Intune device sync..."
            Write-OutputBox "$SectionBreak`nInvoking Intune device sync...`n$SectionBreak"

            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = $controls["ComputerName"].Text
                $Connected = Test-GraphConnection
                
                If (-Not $Connected) {
                    Connect-GraphWithDeviceRead
                }
                
                $device = Get-IntuneDevice -deviceName $computer -erroraction SilentlyContinue
                
                If (-Not $device) {
                    Write-OutputBox "ERROR: Cannot retrieve device Id for $computer"
                    return
                }
            }
            
            $output = Invoke-IntuneDeviceSync -deviceId $device.Id 
            Write-OutputBox "$output"
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: GetDeviceStattus
    $menuItems["GetDeviceStatus"].Add_Click({
            $controls["Status"].Text = "Status: Getting Intune device status..."
            Write-OutputBox "$SectionBreak`nGetting Intune device status...`n$SectionBreak"

            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = $controls["ComputerName"].Text
                $Connected = Test-GraphConnection
                
                If (-Not $Connected) {
                    Connect-GraphWithDeviceRead
                }
                
                $device = Get-IntuneDevice -deviceName $computer -erroraction SilentlyContinue
                
                If (-Not $device) {
                    Write-OutputBox "ERROR: Cannot retrieve device Id for $computer"
                    return
                }
            }
            
            $output = Get-IntuneDeviceStatus -deviceId $device.Id
            Write-OutputBox ("Retrieved Intune device status for $($Device.Id):`n" + ($output | Format-List | Out-String))
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: GetComplianceState
    $menuItems["GetComplianceState"].Add_Click({
            $controls["Status"].Text = "Status: Getting Intune compliance state..."
            Write-OutputBox "$SectionBreak`nGetting Intune compliance state...`n$SectionBreak"
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = $controls["ComputerName"].Text
                $Connected = Test-GraphConnection
                
                If (-Not $Connected) {
                    Connect-GraphWithDeviceRead
                }
                
                $device = Get-IntuneDevice -deviceName $computer -erroraction SilentlyContinue
                
                If (-Not $device) {
                    Write-OutputBox "ERROR: Cannot retrieve device Id for $computer"
                    return
                }
            }
            
            $output = Get-IntuneComplianceState -deviceId $device.Id
            
            Write-OutputBox (" Intune device compliance state for $($Device.Id): " + ($output | Out-String))
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: GetAssignedConfigurations
    $menuItems["GetAssignedConfigurations"].Add_Click({
            $controls["Status"].Text = "Status: Getting Intune assigned configurations..."
            Write-OutputBox "$SectionBreak`nGetting Intune assigned configurations...`n$SectionBreak"
            
            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = $controls["ComputerName"].Text
                $Connected = Test-GraphConnection
                
                If (-Not $Connected) {
                    Connect-GraphWithDeviceRead
                }
                
                $device = Get-IntuneDevice -deviceName $computer -erroraction SilentlyContinue
                
                If (-Not $device) {
                    Write-OutputBox "ERROR: Cannot retrieve device Id for $computer"
                    return
                }
            }
            
            $output = Get-IntuneAssignedConfigurations -deviceId $device.Id
            
            Write-OutputBox ("Intune device assigned configurations for $($Device.Id):`n" + ($output | Format-List | Out-String))
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: GetIntuneUpdatePolicy
    $menuItems["GetIntuneUpdatePolicy"].Add_Click({
            $controls["Status"].Text = "Status: Getting Intune update policy..."
            Write-OutputBox "$SectionBreak`nGetting Intune update policy...`n$SectionBreak"

            if ([string]::IsNullOrWhiteSpace($controls["ComputerName"].Text)) {
                Write-OutputBox "Computer name is empty."
                return
            } Else {
                $computer = $controls["ComputerName"].Text
                $Connected = Test-GraphConnection
                
                If (-Not $Connected) {
                    Connect-GraphWithDeviceRead
                }
                
                $device = Get-IntuneDevice -deviceName $computer -erroraction SilentlyContinue
                
                If (-Not $device) {
                    Write-OutputBox "ERROR: Cannot retrieve device Id for $computer"
                    return
                }
            }
            
            $output = Get-IntuneUpdatePolicy -deviceId $device.Id
            
            Write-OutputBox ("Update-related configuration states for $($Device.Id):`n" + ($output | Format-List | Out-String))
            
            $controls["Status"].Text = "Status: Ready"
        })
    
    # Menu Event: DarkTheme
    $menuItems["DarkTheme"].Add_Click({
            Set-Theme -themePath $ThemePaths["Dark"] -Window $window 
            Set-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value "Dark"
        })
    
    # Menu Event: LightTheme
    $menuItems["LightTheme"].Add_Click({
            Set-Theme -themePath $ThemePaths["Light"] -Window $window
            Set-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value "Light"
        })
    
    # Menu Event: MonokaiTheme
    $menuItems["MonokaiTheme"].Add_Click({
            Set-Theme -themePath $ThemePaths["Monokai"] -Window $window
            Set-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value "Monokai"
        })
    # Menu Event: Nordtheme
    $menuItems["NordTheme"].Add_Click({
            Set-Theme -themePath $ThemePaths["Nord"] -Window $window
            Set-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value "Nord"
        })
    
    # Menu Event: EverForestTheme
    $menuItems["EverForestTheme"].Add_Click({
            Set-Theme -themePath $ThemePaths["EverForest"] -Window $window
            Set-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value "EverForest"
        })
    #endregion
    
    #region Startup
    if (-not (Get-Command Invoke-IntuneDeviceSync -ErrorAction SilentlyContinue)) {
        Import-module (Join-Path $PSScriptRoot '..\modules\IntuneGraph.psm1')
    }
    
    $iconPath = Join-Path $PSScriptRoot "..\resources\WindowsUpdates.ico"
    
    if (Test-Path $iconPath) {
        $icon = New-Object System.Windows.Media.Imaging.BitmapImage
        $icon.BeginInit()
        $icon.UriSource = New-Object System.Uri($iconPath, [System.UriKind]::Absolute)
        $icon.EndInit()
        
        $window.Icon = $icon
    } else {
        Write-Warning "Icon not found at $iconPath"
    }
    
    # Load theme file information
    $ThemePaths = @{ }
    $ThemeFiles = Get-ChildItem (Join-Path -Path $PSScriptRoot '..\resources\themes') -Filter *.xaml
    
    foreach ($file in $ThemeFiles) {
        $key = $file.BaseName
        $ThemePaths[$key] = $file.FullName
    }
    
    # Read saved theme or fall back to default
    If (-Not (Get-Item -path registry::"$SettingsRegPath" -ErrorAction SilentlyContinue)) {
        New-Item -Path registry::"$SettingsRegPath" -Force | out-null
    }
    
    $SavedThemeChoice = (Get-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -ErrorAction SilentlyContinue).Theme
    $defaultTheme = "Nord"
    
    $themeToLoad = if ($SavedThemeChoice) {
        $SavedThemeChoice
    } else {
        New-ItemProperty -Path registry::"$SettingsRegPath" -Name "Theme" -Value $defaultTheme -PropertyType String
        $defaultTheme
    }
    
    $themeToLoad = $themeToLoad.ToLower()
    
    switch ($themeToLoad) {
        "dark" { $themePath = $ThemePaths["Dark"] }
        "monokai" { $themePath = $ThemePaths["Monokai"] }
        "nord" { $themePath = $ThemePaths["Nord"] }
        "everforest" { $themePath = $ThemePaths["Everforest"] }
        default { $themePath = $ThemePaths["Light"] }
    }
    
    Set-Theme -themePath $themePath -Window $window
    
    $SessionLoad = {
        If ($controls["ComputerName"].Text -eq "") {
            $controls["ComputerName"].Text = $ComputerName
        } Else {
            $ComputerName = $controls["ComputerName"].Text
        }
        
        $computer = Set-Computername -ComputerName $ComputerName
        
        Write-OutputBox "Session starting on '$ComputerName'...".Trim()
        $controls["Status"].Text = "Session starting on '$ComputerName'..."
        
        IF ($ComputerName.ToUpper() -eq $env:computername.ToUpper()) {
            $SessionType = "Local"
            Update-ButtonState -State Disabled -ButtonPurpose "Remote"
        } Else {
            $SessionType = "Remote"
            Update-ButtonState -State Enabled -ButtonPurpose "Remote"
        }
        
        Write-OutputBox " '$ComputerName' is $SessionType"
        $controls["SessionType"].Text = "| $SessionType"
        
        #Validate PSWindowsUpdate module is installed
        if ((Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue) -or ($ComputerName -eq $env:computername)) {
            # Start comment here if administrators do not have internet access
            
            $GetPSWindowsUpdateModule = {
                $ModulePresent = get-module -ListAvailable -name pswindowsupdate -ErrorAction SilentlyContinue
                
                If (-Not $ModulePresent) {
                    $repo = Get-PSRepository -Name 'PSGallery' -ErrorAction SilentlyContinue
                    if ($repo -and $repo.InstallationPolicy -ne 'Trusted') {
                        Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
                    }
                    
                    Install-Module -Name PSWindowsUpdate -Force -Scope AllUsers -AllowClobber
                }
            }
            
            Write-OutputBox "Validating PSWindowsUpdate module installed..."
            
            IF ($SessionType -eq "Local") {
                Invoke-Command -ScriptBlock $GetPSWindowsUpdateModule
                Import-Module PSWindowsUpdate -PassThru | out-null
            } else {
                Invoke-Command -ComputerName $Computer -ScriptBlock $GetPSWindowsUpdateModule #-UseSSL -Credential $cred
            }
            
        <# If administrators do not have access to the internet, uncomment this section of code and comment out the above code,
           then manually stage the PSWindowsUpdate module in the modules directory. The process will then copy the module to the
           "C:\Program Files\WindowsPowerShell\Modules" directory if it is not already present.
         
        $ModuleSourcePath = "$ScriptDirectory\Modules\PSWindowsUpdate"
        $ComputerModulePath = "C:\Program Files\WindowsPowerShell\Modules"
        $FileProperties = Get-ItemProperty "$ModuleSourcePath\*\PSWindowsUpdate.dll"
        $ModuleVersion = $FileProperties.VersionInfo.FileVersion
         
        Write-OutputBox "Validating module version...".Trim()
        $controls["Status"].Text = "Status: Validating module version..."
         
        $GetModuleScript = {
            $ModuleResult = get-module -ListAvailable -name pswindowsupdate -ErrorAction SilentlyContinue | where-object { $_.ModuleBase -like "$ComputerModulePath\*" }
             
            If ($ModuleResult) {
                $ModuleResult
            }
        }
         
        IF ($SessionType -eq "Local") {
            $ComputerModuleVersion = (Invoke-Command -ScriptBlock $GetModuleScript).Version
        } else {
            $ComputerModuleVersion = Invoke-Command -ComputerName $Computer -UseSSL -Credential $cred -ScriptBlock $GetModuleScript #).Version
             
            If (-Not $ComputerModuleVersion) {
                $ComputerModuleVersion = 0
                $ComputerModulePath = $ComputerModulePath.Replace("C:","\\$Computer\c`$")
            }
        }
         
        IF ($ComputerModuleVersion -ne $ModuleVersion) {
            Write-OutputBox " Module outdated. Upgrading to version $ModuleVersion..."
            Copy-Item -Path $ModuleSourcePath -Destination $ComputerModulePath -Recurse -Force
        } else {
            Write-OutputBox " Module version $($ModuleVersion) current."
        }
         
        IF ($SessionType -eq "Local") {
            Import-Module PSWindowsUpdate -PassThru | out-null
        }
        #>

        } Else {
            Write-OutputBox " Computer offline: '$ComputerName'"
            Return
        }
        
        Write-OutputBox "Getting Windows Update Settings...".Trim()
        $controls["Status"].Text = "Status: Getting Windows Update Settings..."
        
        $wsusCheck = {
            $WindowsUpdateKey = "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"
            
            if (Test-Path $WindowsUpdateKey) {
                $WUServer = Get-ItemProperty -Path $WindowsUpdateKey -Name "WUServer" -ErrorAction SilentlyContinue
                if ($WUServer.WUServer) {
                    $WSUSServer = $WUServer.WUServer
                } else {
                    $WSUSServer = $null
                }
            } else {
                $WSUSServer = $null
            }
            
            $WSUSServer
        }
        
        IF ($SessionType -eq "Local") {
            If (-Not (Get-Module PSWindowsUpdate)) {
                Import-Module PSWindowsUpdate
            }
            
            $WSUSServer = Invoke-Command -ScriptBlock { $wsusCheck }
            $CMClient = Get-CimInstance -Namespace "root\ccm\clientsdk" -ClassName "CCM_Client" -ErrorAction SilentlyContinue | Select-Object -Property ClientActiveStatus
        } Else {
            $WSUSServer = Invoke-Command -ComputerName $Computer -ScriptBlock { $wsusCheck } #-UseSSL -Credential $cred
            
            $RemoteCimSession = New-CimSession -ComputerName $computer #-Credential $cred
            $CMClient = Get-CimInstance -CimSession $RemoteCimSession -Namespace "root\ccm\clientsdk" -ClassName "CCM_Client" -ErrorAction SilentlyContinue | Select-Object -Property ClientActiveStatus
            Remove-CimSession -CimSession $RemoteCimSession
        }
        
        If ($CMClient) {
            $Global:CMClientPresent = $True
        } else {
            $Global:CMClientPresent = $False
        }
        
        If ($CMClient -and ($Null -ne $wsusServer)) {
            $UpdateMethod = "CM Update"
            $Groupboxes["CMUpdate"].Visibility = [System.Windows.Visibility]::Visible #Collapsed, Visible
            Update-ButtonState -State Enabled -ButtonPurpose "CMUpdate"
        } Else {
            $UpdateMethod = "MS Update"
            $Groupboxes["CMUpdate"].Visibility = [System.Windows.Visibility]::Collapsed #Hidden, Visible
            Update-ButtonState -State Disabled -ButtonPurpose "CMUpdate"
        }
        
        Write-OutputBox " Update method: $UpdateMethod"
        $controls["UpdateMethod"].Text = "| $UpdateMethod"
        
        $window.Title = "pXLabs Windows Update Tool - $ComputerName ($SessionType | $UpdateMethod)"
        
        Write-OutputBox "Getting disk space...".Trim()
        $controls["Status"].Text = "Status: Getting disk space..."
        
        IF ($SessionType -eq "Local") {
            $Diskspace = (Get-PSDrive C) | Select-Object Used, Free
        } Else {
            $Diskspace = Invoke-Command -ComputerName $Computer -ScriptBlock {
                Get-PSDrive C
            } <# -UseSSL -Credential $cred #> | Select-Object Used, Free
        }
        
        $DiskspaceText = "$([Math]::Round($Diskspace.Used / 1GB))GB Used / $([Math]::Round($Diskspace.Free / 1GB))GB Free"
        Write-OutputBox " $DiskspaceText"
        $controls["Diskspace"].Text = "| $DiskspaceText"
        
        $controls["Status"].Text = "Status: Ready"
    }
    
    Invoke-Command -ScriptBlock $SessionLoad
    #endRegion
    
    $window.add_Closing({
            [Win32.Functions]::ShowWindow($hWnd, $SW_SHOW)
            Start-AppCleanup
            $window.Resources.MergedDictionaries.Clear()            
        })
    
    # Show Window
    $window.ShowDialog()
}