# Command line parameters param( [string]$Source = "production", # Can be "local", "beta", or "production" [string]$LocalPath, # Custom local path for XAML file [switch]$CheckVersion, # Force version check [switch]$UpdateConfig, # Update config file with new values [string]$BetaUrl, # Custom beta URL [string]$ProductionUrl, # Custom production URL [switch]$ValidateOnly # Only validate XAML without loading ) # Load required assemblies try { Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName PresentationCore Add-Type -AssemblyName WindowsBase Add-Type -AssemblyName System.Xaml } catch { Write-Error "Failed to load required assemblies. Please ensure .NET Framework is installed." Write-Host "Press any key to exit..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") exit 1 } $currentUser = ${env:Username} $scriptDir = $PSScriptRoot if (-not $scriptDir) { $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition } # Configuration settings $configFile = "$env:TEMP\wintool_config.json" $versionFile = "$env:TEMP\wintool_version.json" $defaultConfig = @{ "source" = "production" "localPath" = Join-Path $scriptDir "main.xaml" "githubUrls" = @{ "beta" = "https://raw.githubusercontent.com/avengert/setup-system/beta/main.xaml" "production" = "https://raw.githubusercontent.com/avengert/setup-system/main/main.xaml" } "lastCheck" = (Get-Date).ToString("o") "version" = @{ "local" = $null "beta" = $null "production" = $null } "autoUpdate" = $true "validateXAML" = $true } # Function to get file content from local or online source function Get-FileContent { param( [string]$path, [string]$fallbackUrl ) try { if ($path -and (Test-Path $path)) { return Get-Content $path -Raw } elseif ($fallbackUrl) { $webClient = New-Object System.Net.WebClient $webClient.Headers.Add("User-Agent", "PowerShell Wintool") return $webClient.DownloadString($fallbackUrl) } } catch { Write-Warning "Failed to load file from $path or $fallbackUrl : $_" } return $null } # Function to validate XAML content function Test-XAMLContent { param([string]$xamlContent) try { if ([string]::IsNullOrWhiteSpace($xamlContent)) { throw "XAML content is empty" } # Create a new XAML reader settings $readerSettings = New-Object System.Xml.XmlReaderSettings $readerSettings.IgnoreWhitespace = $true # Create a string reader for the XAML content $stringReader = New-Object System.IO.StringReader($xamlContent) $xmlReader = [System.Xml.XmlReader]::Create($stringReader, $readerSettings) # Load the XAML $xaml = [Windows.Markup.XamlReader]::Load($xmlReader) return $true } catch { Write-Error "XAML validation failed: $_" return $false } } # Function to load XAML content function Load-XAMLContent { param([string]$xamlContent) try { if ([string]::IsNullOrWhiteSpace($xamlContent)) { throw "XAML content is empty" } # Remove class references and fix XAML $xamlContent = $xamlContent -replace 'x:Class="[^"]*"', '' $xamlContent = $xamlContent -replace 'xmlns:local="[^"]*"', '' $xamlContent = $xamlContent -replace 'mc:Ignorable="d"', '' # Create a new XAML reader settings $readerSettings = New-Object System.Xml.XmlReaderSettings $readerSettings.IgnoreWhitespace = $true # Create a string reader for the XAML content $stringReader = New-Object System.IO.StringReader($xamlContent) $xmlReader = [System.Xml.XmlReader]::Create($stringReader, $readerSettings) # Load the XAML return [Windows.Markup.XamlReader]::Load($xmlReader) } catch { Write-Error "Failed to load XAML: $_" return $null } } # Function to get file version (hash) function Get-FileVersion { param([string]$content) return [System.Security.Cryptography.SHA256]::Create().ComputeHash( [System.Text.Encoding]::UTF8.GetBytes($content) ) | ForEach-Object { $_.ToString("x2") } | Join-String } # Function to check for updates function Test-XAMLUpdates { param([hashtable]$config) $updates = @{} $webClient = New-Object Net.WebClient # Check beta version try { $betaContent = $webClient.DownloadString($config.githubUrls.beta) $betaVersion = Get-FileVersion $betaContent $updates.beta = @{ "version" = $betaVersion "content" = $betaContent "isNew" = $betaVersion -ne $config.version.beta } } catch { Write-Warning "Failed to check beta version: $_" } # Check production version try { $prodContent = $webClient.DownloadString($config.githubUrls.production) $prodVersion = Get-FileVersion $prodContent $updates.production = @{ "version" = $prodVersion "content" = $prodContent "isNew" = $prodVersion -ne $config.version.production } } catch { Write-Warning "Failed to check production version: $_" } return $updates } # Load or create config if (Test-Path $configFile) { $config = Get-Content $configFile | ConvertFrom-Json # Convert PSCustomObject back to Hashtable $config = @{ source = $config.source localPath = $config.localPath githubUrls = @{ beta = $config.githubUrls.beta production = $config.githubUrls.production } lastCheck = $config.lastCheck version = @{ local = $config.version.local beta = $config.version.beta production = $config.version.production } autoUpdate = $config.autoUpdate validateXAML = $config.validateXAML } } else { $config = $defaultConfig $config | ConvertTo-Json -Depth 10 | Set-Content $configFile } # Update config with command line parameters if ($Source) { $config.source = $Source } if ($LocalPath) { $config.localPath = $LocalPath } if ($BetaUrl) { $config.githubUrls.beta = $BetaUrl } if ($ProductionUrl) { $config.githubUrls.production = $ProductionUrl } # Check for updates if needed $shouldCheck = $CheckVersion -or $config.autoUpdate -or ((Get-Date) - [DateTime]::Parse($config.lastCheck)).TotalHours -gt 24 if ($shouldCheck) { Write-Host "Checking for XAML updates..." $updates = Test-XAMLUpdates -config ([hashtable]$config) # Update version information if ($updates.beta) { $config.version.beta = $updates.beta.version if ($updates.beta.isNew) { Write-Host "New beta version available!" } } if ($updates.production) { $config.version.production = $updates.production.version if ($updates.production.isNew) { Write-Host "New production version available!" } } $config.lastCheck = (Get-Date).ToString("o") } # Load XAML based on configuration try { $inputXAML = switch ($config.source) { "local" { $content = Get-FileContent -path $config.localPath -fallbackUrl $config.githubUrls.production if ($content) { $config.version.local = Get-FileVersion $content $content } else { throw "Failed to load XAML from local path or fallback URL" } } "beta" { $content = Get-FileContent -path $null -fallbackUrl $config.githubUrls.beta if ($content) { $content } else { throw "Failed to load XAML from beta URL" } } "production" { $content = Get-FileContent -path $null -fallbackUrl $config.githubUrls.production if ($content) { $content } else { throw "Failed to load XAML from production URL" } } default { throw "Invalid source specified" } } if ($ValidateOnly) { Write-Host "XAML loaded successfully" exit } # Load the XAML $Form = Load-XAMLContent $inputXAML if ($null -eq $Form) { throw "Failed to load XAML form" } } catch { Write-Error "Failed to load XAML: $_" Write-Warning "Attempting to load from production URL as fallback..." try { $inputXAML = (new-object Net.WebClient).DownloadString($config.githubUrls.production) $Form = Load-XAMLContent $inputXAML if ($null -eq $Form) { throw "Failed to load fallback XAML form" } } catch { Write-Error "All attempts to load XAML failed. Please check your internet connection and try again." exit 1 } } # Save the current configuration $config | ConvertTo-Json -Depth 10 | Set-Content $configFile # Find and assign UI elements try { # Find and assign UI elements $XAML.SelectNodes("//*[@Name]") | ForEach-Object {Set-Variable -Name $($_.Name) -Value $Form.FindName($_.Name)} } catch { Write-Host "Warning: Some UI elements could not be found: $($_.Exception.Message)" } # Update version information label $currentVersion = switch ($config.source) { "local" { $config.version.local } "beta" { $config.version.beta } "production" { $config.version.production } default { "unknown" } } $versionInfo = "Version: $($config.source.ToUpper()) ($($currentVersion.Substring(0,8)))" $lblVersionInfo.Content = $versionInfo # Add tooltip with full version info $tooltip = New-Object System.Windows.Controls.ToolTip $tooltip.Content = @" Source: $($config.source) Version: $currentVersion Last Check: $($config.lastCheck) Auto Update: $($config.autoUpdate) "@ $lblVersionInfo.ToolTip = $tooltip Add-Type -AssemblyName System.Windows.Forms # Group all $Form.FindName assignments $btnClose = $Form.FindName("btnClose") $btnSetDomain = $Form.FindName("btnSetDomain") $btnShowOptionalFeatures = $Form.FindName("btnShowOptionalFeatures") $btnShowApplications = $Form.FindName("btnShowApplications") $btnControlPanel = $Form.FindName("btnControlPanel") $btnEnableRDP = $Form.FindName("btnEnableRDP") $btnNetworkConnections = $Form.FindName("btnNetworkConnections") $btnUserPanel = $Form.FindName("btnUserPanel") $btnOpenPowershell = $Form.FindName("btnOpenPowershell") $btnExecutePowershell = $Form.FindName("btnExecutePowershell") $btnSetComputersToMonitor = $Form.FindName("btnSetComputersToMonitor") $btnUpgradeAll = $Form.FindName("btnUpgradeAll") $btnSystemInfo = $Form.FindName("btnSystemInfo") $btnDeviceManager = $Form.FindName("btnDeviceManager") $btnEventViewer = $Form.FindName("btnEventViewer") $btnServices = $Form.FindName("btnServices") $btnTaskManager = $Form.FindName("btnTaskManager") $btnWindowsUpdate = $Form.FindName("btnWindowsUpdate") $btnSystemProperties = $Form.FindName("btnSystemProperties") $btnRegistryEditor = $Form.FindName("btnRegistryEditor") $btnDiskManagement = $Form.FindName("btnDiskManagement") $btnNetworkConnections2 = $Form.FindName("btnNetworkConnections2") $btnControlPanel2 = $Form.FindName("btnControlPanel2") $btnCmd = $Form.FindName("btnCmd") $btnPowerShell = $Form.FindName("btnPowerShell") $btnEnableUser = $Form.FindName("btnEnableUser") $btnDisableUser = $Form.FindName("btnDisableUser") $btnRemoveUser = $Form.FindName("btnRemoveUser") $btnResetPassword = $Form.FindName("btnResetPassword") $btnRestartAsAdmin = $Form.FindName("btnRestartAsAdmin") $btnPing = $Form.FindName("btnPing") $btnTracert = $Form.FindName("btnTracert") $btnNSLookup = $Form.FindName("btnNSLookup") $btnShowIPConfig = $Form.FindName("btnShowIPConfig") $btnReleaseDHCP = $Form.FindName("btnReleaseDHCP") $btnRenewDHCP = $Form.FindName("btnRenewDHCP") $btnFlushDNS = $Form.FindName("btnFlushDNS") $txtNetworkTarget = $Form.FindName("txtNetworkTarget") $txtNetworkOutput = $Form.FindName("txtNetworkOutput") $lstLocalUsers = $Form.FindName("lstLocalUsers") $btnAddUser = $Form.FindName("btnAddUser") $txtNewUserName = $Form.FindName("txtNewUserName") $txtNewUserPassword = $Form.FindName("txtNewUserPassword") $lstPowershell = $Form.FindName("lstPowershell") $lstInstalledApps = $Form.FindName("lstInstalledApps") $txtAppSearch = $Form.FindName("txtAppSearch") $btnChangeApp = $Form.FindName("btnChangeApp") $btnUninstallApp = $Form.FindName("btnUninstallApp") $btnInstallLatestCU = $Form.FindName("btnInstallLatestCU") $lstScripts = $Form.FindName("lstScripts") $btnBrowseScripts = $Form.FindName("btnBrowseScripts") $txtScriptPreview = $Form.FindName("txtScriptPreview") $txtScriptArgs = $Form.FindName("txtScriptArgs") $chkRunAsAdmin = $Form.FindName("chkRunAsAdmin") $btnExecuteScript = $Form.FindName("btnExecuteScript") $btnClearOutput = $Form.FindName("btnClearOutput") $txtScriptOutput = $Form.FindName("txtScriptOutput") $btnSaveOutput = $Form.FindName("btnSaveOutput") $chkThemeToggle = $Form.FindName("chkThemeToggle") $lblThemeStatus = $Form.FindName("lblThemeStatus") $btnSetPCName = $Form.FindName("btnSetPCName") $txtPCName = $Form.FindName("txtPCName") $txtSetDomain = $Form.FindName("txtSetDomain") $btnSetDNS = $Form.FindName("btnSetDNS") $txtSetDNS = $Form.FindName("txtSetDNS") $btnSetIP = $Form.FindName("btnSetIP") $txtSetIP = $Form.FindName("txtSetIP") $chkSelectAllPUPs = $Form.FindName("chkSelectAllPUPs") $lstPUPs = $Form.FindName("lstPUPs") $btnRemovePUPs = $Form.FindName("btnRemovePUPs") $btnRefreshPUPs = $Form.FindName("btnRefreshPUPs") $themeConfigFile = "$env:TEMP\wintool_theme.conf" # PUP list configuration $pupListUrl = "https://raw.githubusercontent.com/avengert/setup-system/main/pups.json" $localPupListPath = "$env:TEMP\wintool_pups.json" # Function to load PUP list function Load-PUPList { try { # Try to download from URL first $webClient = New-Object System.Net.WebClient $jsonContent = $webClient.DownloadString($pupListUrl) $pupList = $jsonContent | ConvertFrom-Json # Save to local file for offline use $jsonContent | Set-Content -Path $localPupListPath } catch { # If download fails, try to load from local file if (Test-Path $localPupListPath) { $jsonContent = Get-Content -Path $localPupListPath -Raw $pupList = $jsonContent | ConvertFrom-Json } else { # If no local file exists, create empty list $pupList = @{ pups = @() } } } return $pupList } Function ReadConfigFile(){ $confFile = "$env:temp\adminConfig.conf" if(Test-Path -Path $confFile){ foreach($i in $(Get-Content $confFile)){ Set-Variable -Name $i.split("=")[0] -Value $i.split("=",2)[1] $lblConfigStatus.Content = "Config Loaded" } } else { $dns = "8.8.8.8" $lblConfigStatus.Content = "Config Not Loaded" } } ReadConfigFile $btnDeviceManager.Add_Click({Start-Process devmgmt.msc}) $btnEventViewer.Add_Click({Start-Process eventvwr.msc}) $btnServices.Add_Click({Start-Process services.msc}) $btnTaskManager.Add_Click({Start-Process taskmgr}) $btnWindowsUpdate.Add_Click({Start-Process "ms-settings:windowsupdate"}) $btnSystemProperties.Add_Click({Start-Process sysdm.cpl}) $btnRegistryEditor.Add_Click({Start-Process regedit}) $btnDiskManagement.Add_Click({Start-Process diskmgmt.msc}) $btnNetworkConnections2.Add_Click({Start-Process ncpa.cpl}) $btnControlPanel2.Add_Click({Start-Process control}) $btnCmd.Add_Click({Start-Process cmd.exe}) $btnPowerShell.Add_Click({Start-Process powershell.exe}) $btnSystemInfo.Add_Click({ try { $sysInfoXAML = Get-FileContent -path (Join-Path $scriptDir "SystemInfoWindow.xaml") -fallbackUrl "https://raw.githubusercontent.com/avengert/setup-system/main/SystemInfoWindow.xaml" if (-not $sysInfoXAML) { throw "Failed to load SystemInfoWindow.xaml" } $sysInfoXAML = $sysInfoXAML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^