################################################################################################################ ### ### ### WARNING: This file is automatically generated DO NOT modify this file directly as it will be overwritten ### ### ### ################################################################################################################ <# .NOTES Author : Chris Titus @christitustech Runspace Author: @DeveloperDurp GitHub : https://github.com/ChrisTitusTech Version : 24.01.30 #> param ( [switch]$Debug, [string]$Config, [switch]$Run ) # Set DebugPreference based on the -Debug switch if ($Debug) { $DebugPreference = "Continue" } if ($Config) { $PARAM_CONFIG = $Config } $PARAM_RUN = $false # Handle the -Run switch if ($Run) { Write-Host "Running config file tasks..." $PARAM_RUN = $true } if (!(Test-Path -Path $ENV:TEMP)) { New-Item -ItemType Directory -Force -Path $ENV:TEMP } Start-Transcript $ENV:TEMP\Winutil.log -Append # Load DLLs Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName System.Windows.Forms # Variable to sync between runspaces $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot $sync.version = "24.01.30" $sync.configs = @{} $sync.ProcessRunning = $false $currentPid = [System.Security.Principal.WindowsIdentity]::GetCurrent() $principal = new-object System.Security.Principal.WindowsPrincipal($currentPid) $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator if ($principal.IsInRole($adminRole)) { $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" clear-host } else { $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell"; $newProcess.Arguments = $myInvocation.MyCommand.Definition; $newProcess.Verb = "runas"; [System.Diagnostics.Process]::Start($newProcess); break } function ConvertTo-Icon { <# .DESCRIPTION This function will convert PNG to ICO file .EXAMPLE ConvertTo-Icon -bitmapPath "$env:TEMP\cttlogo.png" -iconPath $iconPath #> param( [Parameter(Mandatory=$true)] $bitmapPath, $iconPath = "$env:temp\newicon.ico" ) Add-Type -AssemblyName System.Drawing if (Test-Path $bitmapPath) { $b = [System.Drawing.Bitmap]::FromFile($bitmapPath) $icon = [System.Drawing.Icon]::FromHandle($b.GetHicon()) $file = New-Object System.IO.FileStream($iconPath, 'OpenOrCreate') $icon.Save($file) $file.Close() $icon.Dispose() #explorer "/SELECT,$iconpath" } else { Write-Warning "$BitmapPath does not exist" } } function Copy-Files { <# .DESCRIPTION This function will make all modifications to the registry .EXAMPLE Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" #> param ( [string] $Path, [string] $Destination, [switch] $Recurse = $false, [switch] $Force = $false ) try { $files = Get-ChildItem -Path $path -Recurse:$recurse Write-Host "Copy $($files.Count)(s) from $path to $destination" foreach($file in $files) { $status = "Copy files {0} on {1}: {2}" -f $counter, $files.Count, $file.Name Write-Progress -Activity "Copy Windows files" -Status $status -PercentComplete ($counter++/$files.count*100) $restpath = $file.FullName -Replace $path, '' if($file.PSIsContainer -eq $true) { Write-Debug "Creating $($destination + $restpath)" New-Item ($destination+$restpath) -Force:$force -Type Directory -ErrorAction SilentlyContinue } else { Write-Debug "Copy from $($file.FullName) to $($destination+$restpath)" Copy-Item $file.FullName ($destination+$restpath) -ErrorAction SilentlyContinue -Force:$force Set-ItemProperty -Path ($destination+$restpath) -Name IsReadOnly -Value $false } } Write-Progress -Activity "Copy Windows files" -Status "Ready" -Completed } Catch{ Write-Warning "Unable to Copy all the files due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Get-LocalizedYesNo { <# .SYNOPSIS This function runs choice.exe and captures its output to extract yes no in a localized Windows .DESCRIPTION The function retrieves the output of the command 'cmd /c "choice nul"' and converts the default output for Yes and No in the localized format, such as "Yes=, No=". .EXAMPLE $yesNoArray = Get-LocalizedYesNo Write-Host "Yes=$($yesNoArray[0]), No=$($yesNoArray[1])" #> # Run choice and capture its options as output # The output shows the options for Yes and No as "[Y,N]?" in the (partitially) localized format. # eg. English: [Y,N]? # Dutch: [Y,N]? # German: [J,N]? # French: [O,N]? # Spanish: [S,N]? # Italian: [S,N]? # Russian: [Y,N]? $line = cmd /c "choice nul" $charactersArray = @() $regexPattern = '([a-zA-Z])' $charactersArray = [regex]::Matches($line, $regexPattern) | ForEach-Object { $_.Groups[1].Value } Write-Debug "According to takeown.exe local Yes is $charactersArray[0]" # Return the array of characters return $charactersArray } function Get-LocalizedYesNoTakeown { <# .SYNOPSIS This function runs takeown.exe and captures its output to extract yes no in a localized Windows .DESCRIPTION The function retrieves lines from the output of takeown.exe until there are at least 2 characters captured in a specific format, such as "Yes=, No=". .EXAMPLE $yesNoArray = Get-LocalizedYesNo Write-Host "Yes=$($yesNoArray[0]), No=$($yesNoArray[1])" #> # Run takeown.exe and capture its output $takeownOutput = & takeown.exe /? | Out-String # Parse the output and retrieve lines until there are at least 2 characters in the array $found = $false $charactersArray = @() foreach ($line in $takeownOutput -split "`r`n") { # skip everything before /D flag help if ($found) { # now that /D is found start looking for a single character in double quotes # in help text there is another string in double quotes but it is not a single character $regexPattern = '"([a-zA-Z])"' $charactersArray = [regex]::Matches($line, $regexPattern) | ForEach-Object { $_.Groups[1].Value } # if ($charactersArray.Count -gt 0) { # Write-Output "Extracted symbols: $($matches -join ', ')" # } else { # Write-Output "No matches found." # } if ($charactersArray.Count -ge 2) { break } } elseif ($line -match "/D ") { $found = $true } } Write-Debug "According to takeown.exe local Yes is $charactersArray[0]" # Return the array of characters return $charactersArray } function Get-Oscdimg { <# .DESCRIPTION This function will get oscdimg file for from github Release foldersand put it into env:temp .EXAMPLE Get-Oscdimg #> param( [Parameter(Mandatory=$true)] $oscdimgPath = "$env:TEMP\oscdimg.exe" ) $downloadUrl = "https://github.com/ChrisTitusTech/winutil/raw/main/releases/oscdimg.exe" Invoke-RestMethod -Uri $downloadUrl -OutFile $oscdimgPath $hashResult = Get-FileHash -Path $oscdimgPath -Algorithm SHA256 $sha256Hash = $hashResult.Hash Write-Host "[INFO] oscdimg.exe SHA-256 Hash: $sha256Hash" $expectedHash = "AB9E161049D293B544961BFDF2D61244ADE79376D6423DF4F60BF9B147D3C78D" # Replace with the actual expected hash if ($sha256Hash -eq $expectedHash) { Write-Host "Hashes match. File is verified." } else { Write-Host "Hashes do not match. File may be corrupted or tampered with." } } Function Get-WinUtilCheckBoxes { <# .SYNOPSIS Finds all checkboxes that are checked on the specific tab and inputs them into a script. .PARAMETER Group The group of checkboxes to check .PARAMETER unCheck Whether to uncheck the checkboxes that are checked. Defaults to true .OUTPUTS A List containing the name of each checked checkbox .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> Param( [boolean]$unCheck = $false ) $Output = @{ Install = @() WPFTweaks = @() WPFFeature = @() WPFInstall = @() } $CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] } foreach ($CheckBox in $CheckBoxes) { $group = if ($CheckBox.Key.StartsWith("WPFInstall")) { "Install" } elseif ($CheckBox.Key.StartsWith("WPFTweaks")) { "WPFTweaks" } elseif ($CheckBox.Key.StartsWith("WPFFeature")) { "WPFFeature" } if ($group) { if ($CheckBox.Value.IsChecked -eq $true) { $feature = switch ($group) { "Install" { # Get the winget value $wingetValue = $sync.configs.applications.$($CheckBox.Name).winget if (-not [string]::IsNullOrWhiteSpace($wingetValue) -and $wingetValue -ne "na") { $wingetValue -split ";" } else { $sync.configs.applications.$($CheckBox.Name).choco } } default { $CheckBox.Name } } if (-not $Output.ContainsKey($group)) { $Output[$group] = @() } if ($group -eq "Install") { $Output["WPFInstall"] += $CheckBox.Name Write-Debug "Adding: $($CheckBox.Name) under: WPFInstall" } Write-Debug "Adding: $($feature) under: $($group)" $Output[$group] += $feature if ($uncheck -eq $true) { $CheckBox.Value.IsChecked = $false } } } } return $Output } function Get-WinUtilInstallerProcess { <# .SYNOPSIS Checks if the given process is running .PARAMETER Process The process to check .OUTPUTS Boolean - True if the process is running #> param($Process) if ($Null -eq $Process){ return $false } if (Get-Process -Id $Process.Id -ErrorAction SilentlyContinue){ return $true } return $false } function Get-WinUtilRegistry { <# .SYNOPSIS Gets the value of a registry key .EXAMPLE Get-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" #> param ( $Name, $Path, $Type, $Value ) Try{ $syscheckvalue = Get-ItemPropertyValue -Path $Path -Value $Value # Return Value } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } Function Get-WinUtilToggleStatus { <# .SYNOPSIS Pulls the registry keys for the given toggle switch and checks whether the toggle should be checked or unchecked .PARAMETER ToggleSwitch The name of the toggle to check .OUTPUTS Boolean to set the toggle's status to #> Param($ToggleSwitch) if($ToggleSwitch -eq "WPFToggleDarkMode"){ $app = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').AppsUseLightTheme $system = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').SystemUsesLightTheme if($app -eq 0 -and $system -eq 0){ return $true } else{ return $false } } if($ToggleSwitch -eq "WPFToggleBingSearch"){ $bingsearch = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search').BingSearchEnabled if($bingsearch -eq 0){ return $false } else{ return $true } } if($ToggleSwitch -eq "WPFToggleNumLock"){ $numlockvalue = (Get-ItemProperty -path 'HKCU:\Control Panel\Keyboard').InitialKeyboardIndicators if($numlockvalue -eq 2){ return $true } else{ return $false } } if($ToggleSwitch -eq "WPFToggleVerboseLogon"){ $VerboseStatusvalue = (Get-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System').VerboseStatus if($VerboseStatusvalue -eq 1){ return $true } else{ return $false } } if($ToggleSwitch -eq "WPFToggleShowExt"){ $hideextvalue = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced').HideFileExt if($hideextvalue -eq 0){ return $true } else{ return $false } } if($ToggleSwitch -eq "WPFToggleSnapFlyout"){ $hidesnap = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced').EnableSnapAssistFlyout if($hidesnap -eq 0){ return $false } else{ return $true } } if($ToggleSwitch -eq "WPFToggleMouseAcceleration"){ $MouseSpeed = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseSpeed $MouseThreshold1 = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseThreshold1 $MouseThreshold2 = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseThreshold2 if($MouseSpeed -eq 1 -and $MouseThreshold1 -eq 6 -and $MouseThreshold2 -eq 10){ return $true } else{ return $false } } } function Get-WinUtilVariables { <# .SYNOPSIS Gets every form object of the provided type .OUTPUTS List containing every object that matches the provided type #> param ( [Parameter()] [string[]]$Type ) $keys = $sync.keys | Where-Object { $_ -like "WPF*" } if ($Type) { $output = $keys | ForEach-Object { Try { $objType = $sync["$psitem"].GetType().Name if ($Type -contains $objType) { Write-Output $psitem } } Catch { <#I am here so errors don't get outputted for a couple variables that don't have the .GetType() attribute#> } } return $output } return $keys } function Install-WinUtilChoco { <# .SYNOPSIS Installs Chocolatey if it is not already installed #> try { Write-Host "Checking if Chocolatey is Installed..." if((Test-WinUtilPackageManager -choco)){ Write-Host "Chocolatey Already Installed" return } Write-Host "Seems Chocolatey is not installed, installing now" Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop powershell choco feature enable -n allowGlobalConfirmation } Catch { Write-Host "===========================================" Write-Host "-- Chocolatey failed to install ---" Write-Host "===========================================" } } Function Install-WinUtilProgramWinget { <# .SYNOPSIS Manages the provided programs using Winget .PARAMETER ProgramsToInstall A list of programs to manage .PARAMETER manage The action to perform on the programs, can be either 'Installing' or 'Uninstalling' .NOTES The triple quotes are required any time you need a " in a normal script block. #> param( $ProgramsToInstall, $manage = "Installing" ) $x = 0 $count = $($ProgramsToInstall -split ",").Count Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 Foreach ($Program in $($ProgramsToInstall -split ",")){ Write-Progress -Activity "$manage Applications" -Status "$manage $Program $($x + 1) of $count" -PercentComplete $($x/$count*100) if($manage -eq "Installing"){ Start-Process -FilePath winget -ArgumentList "install -e --accept-source-agreements --accept-package-agreements --scope=machine --silent $Program" -NoNewWindow -Wait } if($manage -eq "Uninstalling"){ Start-Process -FilePath winget -ArgumentList "uninstall -e --purge --force --silent $Program" -NoNewWindow -Wait } $X++ } Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed } function Get-LatestHash { $shaUrl = ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt$' }).browser_download_url $shaFile = Join-Path -Path $tempFolder -ChildPath 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt' $WebClient.DownloadFile($shaUrl, $shaFile) Get-Content $shaFile } function Install-WinUtilWinget { <# .SYNOPSIS Installs Winget if it is not already installed .DESCRIPTION This function will download the latest version of winget and install it. If winget is already installed, it will do nothing. #> Try{ Write-Host "Checking if Winget is Installed..." if (Test-WinUtilPackageManager -winget) { # Checks if winget executable exists and if the Windows Version is 1809 or higher Write-Host "Winget Already Installed" return } # Gets the computer's information if ($null -eq $sync.ComputerInfo){ $ComputerInfo = Get-ComputerInfo -ErrorAction Stop } Else { $ComputerInfo = $sync.ComputerInfo } if (($ComputerInfo.WindowsVersion) -lt "1809") { # Checks if Windows Version is too old for winget Write-Host "Winget is not supported on this version of Windows (Pre-1809)" return } Write-Host "Running Alternative Installer and Direct Installing" Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget" Write-Host "Winget Installed" } Catch{ throw [WingetFailedInstall]::new('Failed to install') } } function Invoke-MicroWin-Helper { <# .SYNOPSIS checking unit tests .PARAMETER Name no parameters .EXAMPLE placeholder #> } function Is-CompatibleImage() { <# .SYNOPSIS Checks the version of a Windows image and determines whether or not it is compatible depending on the Major property .PARAMETER imgVersion The version of the Windows image #> param ( [Parameter(Mandatory = $true)] [string] $imgVersion ) try { $version = [Version]$imgVersion if ($version.Major -ge 10) { return $True } else { return $False } } catch { return $False } } function Remove-Features([switch] $dumpFeatures = $false, [switch] $keepDefender = $false) { <# .SYNOPSIS Removes certain features from ISO image .PARAMETER Name dumpFeatures - Dumps all features found in the ISO into a file called allfeaturesdump.txt. This file can be examined and used to decide what to remove. keepDefender - Should Defender be removed from the ISO? .EXAMPLE Remove-Features -keepDefender:$false #> $appxlist = dism /English /image:$scratchDir /Get-Features | Select-String -Pattern "Feature Name : " -CaseSensitive -SimpleMatch $appxlist = $appxlist -split "Feature Name : " | Where-Object {$_} if ($dumpFeatures) { $appxlist > allfeaturesdump.txt } $appxlist = $appxlist | Where-Object { $_ -NotLike "*Printing*" -AND $_ -NotLike "*TelnetClient*" -AND $_ -NotLike "*PowerShell*" -AND $_ -NotLike "*NetFx*" } if ($keepDefender) { $appxlist = $appxlist | Where-Object { $_ -NotLike "*Defender*" }} foreach($feature in $appxlist) { $status = "Removing feature $feature" Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$appxlist.Count*100) Write-Debug "Removing feature $feature" # dism /image:$scratchDir /Disable-Feature /FeatureName:$feature /Remove /NoRestart > $null } Write-Progress -Activity "Removing features" -Status "Ready" -Completed } function Remove-Packages { $appxlist = dism /English /Image:$scratchDir /Get-Packages | Select-String -Pattern "Package Identity : " -CaseSensitive -SimpleMatch $appxlist = $appxlist -split "Package Identity : " | Where-Object {$_} $appxlist = $appxlist | Where-Object { $_ -NotLike "*ApplicationModel*" -AND $_ -NotLike "*indows-Client-LanguagePack*" -AND $_ -NotLike "*LanguageFeatures-Basic*" -AND $_ -NotLike "*Package_for_ServicingStack*" -AND $_ -NotLike "*.NET*" -AND $_ -NotLike "*Store*" -AND $_ -NotLike "*VCLibs*" -AND $_ -NotLike "*AAD.BrokerPlugin", $_ -NotLike "*LockApp*" -AND $_ -NotLike "*Notepad*" -AND $_ -NotLike "*immersivecontrolpanel*" -AND $_ -NotLike "*ContentDeliveryManager*" -AND $_ -NotLike "*PinningConfirMationDialog*" -AND $_ -NotLike "*SecHealthUI*" -AND $_ -NotLike "*SecureAssessmentBrowser*" -AND $_ -NotLike "*PrintDialog*" -AND $_ -NotLike "*AssignedAccessLockApp*" -AND $_ -NotLike "*OOBENetworkConnectionFlow*" -AND $_ -NotLike "*Apprep.ChxApp*" -AND $_ -NotLike "*CBS*" -AND $_ -NotLike "*OOBENetworkCaptivePortal*" -AND $_ -NotLike "*PeopleExperienceHost*" -AND $_ -NotLike "*ParentalControls*" -AND $_ -NotLike "*Win32WebViewHost*" -AND $_ -NotLike "*InputApp*" -AND $_ -NotLike "*AccountsControl*" -AND $_ -NotLike "*AsyncTextService*" -AND $_ -NotLike "*CapturePicker*" -AND $_ -NotLike "*CredDialogHost*" -AND $_ -NotLike "*BioEnrollMent*" -AND $_ -NotLike "*ShellExperienceHost*" -AND $_ -NotLike "*DesktopAppInstaller*" -AND $_ -NotLike "*WebMediaExtensions*" -AND $_ -NotLike "*WMIC*" -AND $_ -NotLike "*UI.XaML*" } foreach ($appx in $appxlist) { $status = "Removing $appx" Write-Progress -Activity "Removing Apps" -Status $status -PercentComplete ($counter++/$appxlist.Count*100) dism /English /image:$scratchDir /Remove-Package /PackageName:$appx /NoRestart } Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed } function Remove-ProvisionedPackages([switch] $keepSecurity = $false) { <# .SYNOPSIS Removes AppX packages from a Windows image during MicroWin processing .PARAMETER Name keepSecurity - Boolean that determines whether to keep "Microsoft.SecHealthUI" (Windows Security) in the Windows image .EXAMPLE Remove-ProvisionedPackages -keepSecurity:$false #> $appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object { $_.PackageName -NotLike "*AppInstaller*" -AND $_.PackageName -NotLike "*Store*" -and $_.PackageName -NotLike "*dism*" -and $_.PackageName -NotLike "*Foundation*" -and $_.PackageName -NotLike "*FodMetadata*" -and $_.PackageName -NotLike "*LanguageFeatures*" -and $_.PackageName -NotLike "*Notepad*" -and $_.PackageName -NotLike "*Printing*" -and $_.PackageName -NotLike "*Wifi*" -and $_.PackageName -NotLike "*Foundation*" } if ($?) { if ($keepSecurity) { $appxProvisionedPackages = $appxProvisionedPackages | Where-Object { $_.PackageName -NotLike "*SecHealthUI*" }} $counter = 0 foreach ($appx in $appxProvisionedPackages) { $status = "Removing Provisioned $($appx.PackageName)" Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100) dism /English /image:$scratchDir /Remove-ProvisionedAppxPackage /PackageName:$($appx.PackageName) /NoRestart } Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed } else { Write-Host "Could not get Provisioned App information. Skipping process..." } } function Copy-ToUSB([string] $fileToCopy) { foreach ($volume in Get-Volume) { if ($volume -and $volume.FileSystemLabel -ieq "ventoy") { $destinationPath = "$($volume.DriveLetter):\" #Copy-Item -Path $fileToCopy -Destination $destinationPath -Force # Get the total size of the file $totalSize = (Get-Item $fileToCopy).length Copy-Item -Path $fileToCopy -Destination $destinationPath -Verbose -Force -Recurse -Container -PassThru | ForEach-Object { # Calculate the percentage completed $completed = ($_.BytesTransferred / $totalSize) * 100 # Display the progress bar Write-Progress -Activity "Copying File" -Status "Progress" -PercentComplete $completed -CurrentOperation ("{0:N2} MB / {1:N2} MB" -f ($_.BytesTransferred / 1MB), ($totalSize / 1MB)) } Write-Host "File copied to Ventoy drive $($volume.DriveLette)" return } } Write-Host "Ventoy USB Key is not inserted" } function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false) { if(([string]::IsNullOrEmpty($pathToDelete))) { return } if (-not (Test-Path -Path "$($pathToDelete)")) { return } $yesNo = Get-LocalizedYesNo Write-Host "[INFO] In Your local takeown expects '$($yesNo[0])' as a Yes answer." # Specify the path to the directory # $directoryPath = "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" # takeown /a /r /d $yesNo[0] /f "$($directoryPath)" > $null # icacls "$($directoryPath)" /q /c /t /reset > $null # icacls $directoryPath /setowner "*S-1-5-32-544" # icacls $directoryPath /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q # Remove-Item -Path $directoryPath -Recurse -Force # # Grant full control to BUILTIN\Administrators using icacls # $directoryPath = "$($scratchDir)\Windows\System32\WebThreatDefSvc" # takeown /a /r /d $yesNo[0] /f "$($directoryPath)" > $null # icacls "$($directoryPath)" /q /c /t /reset > $null # icacls $directoryPath /setowner "*S-1-5-32-544" # icacls $directoryPath /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q # Remove-Item -Path $directoryPath -Recurse -Force $itemsToDelete = [System.Collections.ArrayList]::new() if ($mask -eq "") { Write-Debug "Adding $($pathToDelete) to array." [void]$itemsToDelete.Add($pathToDelete) } else { Write-Debug "Adding $($pathToDelete) to array and mask is $($mask)" if ($Directory) { $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse -Directory } else { $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse } } foreach($itemToDelete in $itemsToDelete) { $status = "Deleteing $($itemToDelete)" Write-Progress -Activity "Removing Items" -Status $status -PercentComplete ($counter++/$itemsToDelete.Count*100) if (Test-Path -Path "$($itemToDelete)" -PathType Container) { $status = "Deleting directory: $($itemToDelete)" takeown /r /d $yesNo[0] /a /f "$($itemToDelete)" icacls "$($itemToDelete)" /q /c /t /reset icacls $itemToDelete /setowner "*S-1-5-32-544" icacls $itemToDelete /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q Remove-Item -Force -Recurse "$($itemToDelete)" } elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf) { $status = "Deleting file: $($itemToDelete)" takeown /a /f "$($itemToDelete)" icacls "$($itemToDelete)" /q /c /t /reset icacls "$($itemToDelete)" /setowner "*S-1-5-32-544" icacls "$($itemToDelete)" /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q Remove-Item -Force "$($itemToDelete)" } } Write-Progress -Activity "Removing Items" -Status "Ready" -Completed } function New-Unattend { # later if we wont to remove even more bloat EU requires MS to remove everything from English(world) # Below is an example how to do it we probably should create a drop down with common locals # # # # # en-US # # en-US # en-US # en-US # en-US # # # # # # en-US # en-US # en-US # en-US # # # using here string to embedd unattend # # 1 # net user administrator /active:yes # # this section doesn't work in win10/???? # # # 0 # # # false # # $unattend = @' 1 CMD /C echo LAU GG>C:\Windows\LogAuditUser.txt StartMenu true false false true true true 3 1 cmd.exe /c echo 23>c:\windows\csup.txt 2 CMD /C echo GG>C:\Windows\LogOobeSystem.txt 3 powershell -ExecutionPolicy Bypass -File c:\windows\FirstStartup.ps1 '@ $unattend | Out-File -FilePath "$env:temp\unattend.xml" -Force } function New-CheckInstall { # using here string to embedd firstrun $checkInstall = @' @echo off if exist "C:\windows\cpu.txt" ( echo C:\windows\cpu.txt exists ) else ( echo C:\windows\cpu.txt does not exist ) if exist "C:\windows\SerialNumber.txt" ( echo C:\windows\SerialNumber.txt exists ) else ( echo C:\windows\SerialNumber.txt does not exist ) if exist "C:\unattend.xml" ( echo C:\unattend.xml exists ) else ( echo C:\unattend.xml does not exist ) if exist "C:\Windows\Setup\Scripts\SetupComplete.cmd" ( echo C:\Windows\Setup\Scripts\SetupComplete.cmd exists ) else ( echo C:\Windows\Setup\Scripts\SetupComplete.cmd does not exist ) if exist "C:\Windows\Panther\unattend.xml" ( echo C:\Windows\Panther\unattend.xml exists ) else ( echo C:\Windows\Panther\unattend.xml does not exist ) if exist "C:\Windows\System32\Sysprep\unattend.xml" ( echo C:\Windows\System32\Sysprep\unattend.xml exists ) else ( echo C:\Windows\System32\Sysprep\unattend.xml does not exist ) if exist "C:\Windows\FirstStartup.ps1" ( echo C:\Windows\FirstStartup.ps1 exists ) else ( echo C:\Windows\FirstStartup.ps1 does not exist ) if exist "C:\Windows\winutil.ps1" ( echo C:\Windows\winutil.ps1 exists ) else ( echo C:\Windows\winutil.ps1 does not exist ) if exist "C:\Windows\LogSpecialize.txt" ( echo C:\Windows\LogSpecialize.txt exists ) else ( echo C:\Windows\LogSpecialize.txt does not exist ) if exist "C:\Windows\LogAuditUser.txt" ( echo C:\Windows\LogAuditUser.txt exists ) else ( echo C:\Windows\LogAuditUser.txt does not exist ) if exist "C:\Windows\LogOobeSystem.txt" ( echo C:\Windows\LogOobeSystem.txt exists ) else ( echo C:\Windows\LogOobeSystem.txt does not exist ) if exist "c:\windows\csup.txt" ( echo c:\windows\csup.txt exists ) else ( echo c:\windows\csup.txt does not exist ) if exist "c:\windows\LogFirstRun.txt" ( echo c:\windows\LogFirstRun.txt exists ) else ( echo c:\windows\LogFirstRun.txt does not exist ) '@ $checkInstall | Out-File -FilePath "$env:temp\checkinstall.cmd" -Force -Encoding Ascii } function New-FirstRun { # using here string to embedd firstrun $firstRun = @' # Set the global error action preference to continue $ErrorActionPreference = "Continue" function Remove-RegistryValue { param ( [Parameter(Mandatory = $true)] [string]$RegistryPath, [Parameter(Mandatory = $true)] [string]$ValueName ) # Check if the registry path exists if (Test-Path -Path $RegistryPath) { $registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue # Check if the registry value exists if ($registryValue) { # Remove the registry value Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force Write-Host "Registry value '$ValueName' removed from '$RegistryPath'." } else { Write-Host "Registry value '$ValueName' not found in '$RegistryPath'." } } else { Write-Host "Registry path '$RegistryPath' not found." } } function Stop-UnnecessaryServices { $servicesToExclude = @( "AudioSrv", "AudioEndpointBuilder", "BFE", "BITS", "BrokerInfrastructure", "CDPSvc", "CDPUserSvc_dc2a4", "CoreMessagingRegistrar", "CryptSvc", "DPS", "DcomLaunch", "Dhcp", "DispBrokerDesktopSvc", "Dnscache", "DoSvc", "DusmSvc", "EventLog", "EventSystem", "FontCache", "LSM", "LanmanServer", "LanmanWorkstation", "MapsBroker", "MpsSvc", "OneSyncSvc_dc2a4", "Power", "ProfSvc", "RpcEptMapper", "RpcSs", "SCardSvr", "SENS", "SamSs", "Schedule", "SgrmBroker", "ShellHWDetection", "Spooler", "SysMain", "SystemEventsBroker", "TextInputManagementService", "Themes", "TrkWks", "UserManager", "VGAuthService", "VMTools", "WSearch", "Wcmsvc", "WinDefend", "Winmgmt", "WlanSvc", "WpnService", "WpnUserService_dc2a4", "cbdhsvc_dc2a4", "edgeupdate", "gpsvc", "iphlpsvc", "mpssvc", "nsi", "sppsvc", "tiledatamodelsvc", "vm3dservice", "webthreatdefusersvc_dc2a4", "wscsvc" ) $runningServices = Get-Service | Where-Object { $servicesToExclude -notcontains $_.Name } foreach($service in $runningServices) { Stop-Service -Name $service.Name -PassThru Set-Service $service.Name -StartupType Manual "Stopping service $($service.Name)" | Out-File -FilePath c:\windows\LogFirstRun.txt -Append -NoClobber } } "FirstStartup has worked" | Out-File -FilePath c:\windows\LogFirstRun.txt -Append -NoClobber $Theme = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" Set-ItemProperty -Path $Theme -Name AppsUseLightTheme -Value 1 Set-ItemProperty -Path $Theme -Name SystemUsesLightTheme -Value 1 # figure this out later how to set updates to security only #Import-Module -Name PSWindowsUpdate; #Stop-Service -Name wuauserv #Set-WUSettings -MicrosoftUpdateEnabled -AutoUpdateOption 'Never' #Start-Service -Name wuauserv Stop-UnnecessaryServices $taskbarPath = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar" # Delete all files on the Taskbar Get-ChildItem -Path $taskbarPath -File | Remove-Item -Force Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesRemovedChanges" Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesChanges" Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "Favorites" # Stop-Process -Name explorer -Force $process = Get-Process -Name "explorer" Stop-Process -InputObject $process # Wait for the process to exit Wait-Process -InputObject $process Start-Sleep -Seconds 3 # Delete Edge Icon from the desktop $edgeShortcutFiles = Get-ChildItem -Path $desktopPath -Filter "*Edge*.lnk" # Check if Edge shortcuts exist on the desktop if ($edgeShortcutFiles) { foreach ($shortcutFile in $edgeShortcutFiles) { # Remove each Edge shortcut Remove-Item -Path $shortcutFile.FullName -Force Write-Host "Edge shortcut '$($shortcutFile.Name)' removed from the desktop." } } Remove-Item -Path "$env:USERPROFILE\Desktop\*.lnk" Remove-Item -Path "C:\Users\Default\Desktop\*.lnk" # ************************************************ # Create WinUtil shortcut on the desktop # $desktopPath = "$($env:USERPROFILE)\Desktop" # Specify the target PowerShell command $command = "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'irm https://christitus.com/win | iex'" # Specify the path for the shortcut $shortcutPath = Join-Path $desktopPath 'winutil.lnk' # Create a shell object $shell = New-Object -ComObject WScript.Shell # Create a shortcut object $shortcut = $shell.CreateShortcut($shortcutPath) if (Test-Path -Path "c:\Windows\cttlogo.png") { $shortcut.IconLocation = "c:\Windows\cttlogo.png" } # Set properties of the shortcut $shortcut.TargetPath = "powershell.exe" $shortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -Command `"$command`"" # Save the shortcut $shortcut.Save() Write-Host "Shortcut created at: $shortcutPath" # # Done create WinUtil shortcut on the desktop # ************************************************ Start-Process explorer '@ $firstRun | Out-File -FilePath "$env:temp\FirstStartup.ps1" -Force } function Invoke-WinUtilBingSearch { <# .SYNOPSIS Disables/Enables Bing Search .PARAMETER Enabled Indicates whether to enable or disable Bing Search #> Param($Enabled) Try{ if ($Enabled -eq $false){ Write-Host "Enabling Bing Search" $value = 1 } else { Write-Host "Disabling Bing Search" $value = 0 } $Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" Set-ItemProperty -Path $Path -Name BingSearchEnabled -Value $value } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } Function Invoke-WinUtilCurrentSystem { <# .SYNOPSIS Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> param( $CheckBox ) if ($checkbox -eq "winget"){ $originalEncoding = [Console]::OutputEncoding [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new() $Sync.InstalledPrograms = winget list -s winget | Select-Object -skip 3 | ConvertFrom-String -PropertyNames "Name", "Id", "Version", "Available" -Delimiter '\s{2,}' [Console]::OutputEncoding = $originalEncoding $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"} $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object { $dependencies = @($sync.configs.applications.$($psitem.Key).winget -split ";") if ($dependencies[-1] -in $sync.InstalledPrograms.Id) { Write-Output $psitem.name } } } if($CheckBox -eq "tweaks"){ if(!(Test-Path 'HKU:\')){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS} $ScheduledTasks = Get-ScheduledTask $sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object { $Config = $psitem.Name #WPFEssTweaksTele $registryKeys = $sync.configs.tweaks.$Config.registry $scheduledtaskKeys = $sync.configs.tweaks.$Config.scheduledtask $serviceKeys = $sync.configs.tweaks.$Config.service if($registryKeys -or $scheduledtaskKeys -or $serviceKeys){ $Values = @() Foreach ($tweaks in $registryKeys){ Foreach($tweak in $tweaks){ if(test-path $tweak.Path){ $actualValue = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name) $expectedValue = $tweak.Value if ($expectedValue -notlike $actualValue){ $values += $False } } } } Foreach ($tweaks in $scheduledtaskKeys){ Foreach($tweak in $tweaks){ $task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"} if($task){ $actualValue = $task.State $expectedValue = $tweak.State if ($expectedValue -ne $actualValue){ $values += $False } } } } Foreach ($tweaks in $serviceKeys){ Foreach($tweak in $tweaks){ $Service = Get-Service -Name $tweak.Name if($Service){ $actualValue = $Service.StartType $expectedValue = $tweak.StartupType if ($expectedValue -ne $actualValue){ $values += $False } } } } if($values -notcontains $false){ Write-Output $Config } } } } } Function Invoke-WinUtilDarkMode { <# .SYNOPSIS Enables/Disables Dark Mode .PARAMETER DarkMoveEnabled Indicates the current dark mode state #> Param($DarkMoveEnabled) Try{ if ($DarkMoveEnabled -eq $false){ Write-Host "Enabling Dark Mode" $DarkMoveValue = 0 } else { Write-Host "Disabling Dark Mode" $DarkMoveValue = 1 } $Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" Set-ItemProperty -Path $Path -Name AppsUseLightTheme -Value $DarkMoveValue Set-ItemProperty -Path $Path -Name SystemUsesLightTheme -Value $DarkMoveValue } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilFeatureInstall { <# .SYNOPSIS Converts all the values from the tweaks.json and routes them to the appropriate function #> param( $CheckBox ) $CheckBox | ForEach-Object { if($sync.configs.feature.$psitem.feature){ Foreach( $feature in $sync.configs.feature.$psitem.feature ){ Try{ Write-Host "Installing $feature" Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart } Catch{ if ($psitem.Exception.Message -like "*requires elevation*"){ Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?" } else{ Write-Warning "Unable to Install $feature due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } } } if($sync.configs.feature.$psitem.InvokeScript){ Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ){ Try{ $Scriptblock = [scriptblock]::Create($script) Write-Host "Running Script for $psitem" Invoke-Command $scriptblock -ErrorAction stop } Catch{ if ($psitem.Exception.Message -like "*requires elevation*"){ Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?" } else{ Write-Warning "Unable to Install $feature due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } } } } } Function Invoke-WinUtilMouseAcceleration { <# .SYNOPSIS Enables/Disables Mouse Acceleration .PARAMETER DarkMoveEnabled Indicates the current Mouse Acceleration State #> Param($MouseAccelerationEnabled) Try{ if ($MouseAccelerationEnabled -eq $false){ Write-Host "Enabling Mouse Acceleration" $MouseSpeed = 1 $MouseThreshold1 = 6 $MouseThreshold2 = 10 } else { Write-Host "Disabling Mouse Acceleration" $MouseSpeed = 0 $MouseThreshold1 = 0 $MouseThreshold2 = 0 } $Path = "HKCU:\Control Panel\Mouse" Set-ItemProperty -Path $Path -Name MouseSpeed -Value $MouseSpeed Set-ItemProperty -Path $Path -Name MouseThreshold1 -Value $MouseThreshold1 Set-ItemProperty -Path $Path -Name MouseThreshold2 -Value $MouseThreshold2 } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilNumLock { <# .SYNOPSIS Disables/Enables NumLock on startup .PARAMETER Enabled Indicates whether to enable or disable Numlock on startup #> Param($Enabled) Try{ if ($Enabled -eq $false){ Write-Host "Enabling Numlock on startup" $value = 2 } else { Write-Host "Disabling Numlock on startup" $value = 0 } $Path = "HKCU:\Control Panel\Keyboard" Set-ItemProperty -Path $Path -Name InitialKeyboardIndicators -Value $value } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilScript { <# .SYNOPSIS Invokes the provided scriptblock. Intended for things that can't be handled with the other functions. .PARAMETER Name The name of the scriptblock being invoked .PARAMETER scriptblock The scriptblock to be invoked .EXAMPLE $Scriptblock = [scriptblock]::Create({"Write-output 'Hello World'"}) Invoke-WinUtilScript -ScriptBlock $scriptblock -Name "Hello World" #> param ( $Name, [scriptblock]$scriptblock ) Try { Write-Host "Running Script for $name" Invoke-Command $scriptblock -ErrorAction Stop } Catch [System.Management.Automation.CommandNotFoundException] { Write-Warning "The specified command was not found." Write-Warning $PSItem.Exception.message } Catch [System.Management.Automation.RuntimeException] { Write-Warning "A runtime exception occurred." Write-Warning $PSItem.Exception.message } Catch [System.Security.SecurityException] { Write-Warning "A security exception occurred." Write-Warning $PSItem.Exception.message } Catch [System.UnauthorizedAccessException] { Write-Warning "Access denied. You do not have permission to perform this operation." Write-Warning $PSItem.Exception.message } Catch { # Generic catch block to handle any other type of exception Write-Warning "Unable to run script for $name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilShowExt { <# .SYNOPSIS Disables/Enables Show file Extentions .PARAMETER Enabled Indicates whether to enable or disable Show file extentions #> Param($Enabled) Try{ if ($Enabled -eq $false){ Write-Host "Showing file extentions" $value = 0 } else { Write-Host "hiding file extensions" $value = 1 } $Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Set-ItemProperty -Path $Path -Name HideFileExt -Value $value } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilSnapFlyout { <# .SYNOPSIS Disables/Enables Snap Assist Flyout on startup .PARAMETER Enabled Indicates whether to enable or disable Snap Assist Flyout on startup #> Param($Enabled) Try{ if ($Enabled -eq $false){ Write-Host "Enabling Snap Assist Flyout On startup" $value = 1 } else { Write-Host "Disabling Snap Assist Flyout On startup" $value = 0 } # taskkill.exe /F /IM "explorer.exe" $Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" taskkill.exe /F /IM "explorer.exe" Set-ItemProperty -Path $Path -Name EnableSnapAssistFlyout -Value $value Start-Process "explorer.exe" } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Invoke-WinUtilTweaks { <# .SYNOPSIS Invokes the function associated with each provided checkbox .PARAMETER CheckBox The checkbox to invoke .PARAMETER undo Indicates whether to undo the operation contained in the checkbox #> param( $CheckBox, $undo = $false ) Write-Debug "Tweaks: $($CheckBox)" if($undo){ $Values = @{ Registry = "OriginalValue" ScheduledTask = "OriginalState" Service = "OriginalType" ScriptType = "UndoScript" } } Else{ $Values = @{ Registry = "Value" ScheduledTask = "State" Service = "StartupType" ScriptType = "InvokeScript" } } if($sync.configs.tweaks.$CheckBox.ScheduledTask){ $sync.configs.tweaks.$CheckBox.ScheduledTask | ForEach-Object { Write-Debug "$($psitem.Name) and state is $($psitem.$($values.ScheduledTask))" Set-WinUtilScheduledTask -Name $psitem.Name -State $psitem.$($values.ScheduledTask) } } if($sync.configs.tweaks.$CheckBox.service){ $sync.configs.tweaks.$CheckBox.service | ForEach-Object { Write-Debug "$($psitem.Name) and state is $($psitem.$($values.service))" Set-WinUtilService -Name $psitem.Name -StartupType $psitem.$($values.Service) } } if($sync.configs.tweaks.$CheckBox.registry){ $sync.configs.tweaks.$CheckBox.registry | ForEach-Object { Write-Debug "$($psitem.Name) and state is $($psitem.$($values.registry))" Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry) } } if($sync.configs.tweaks.$CheckBox.$($values.ScriptType)){ $sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object { Write-Debug "$($psitem) and state is $($psitem.$($values.ScriptType))" $Scriptblock = [scriptblock]::Create($psitem) Invoke-WinUtilScript -ScriptBlock $scriptblock -Name $CheckBox } } if(!$undo){ if($sync.configs.tweaks.$CheckBox.appx){ $sync.configs.tweaks.$CheckBox.appx | ForEach-Object { Write-Debug "UNDO $($psitem.Name)" Remove-WinUtilAPPX -Name $psitem } } } } function Invoke-WinUtilVerboseLogon { <# .SYNOPSIS Disables/Enables VerboseLogon Messages .PARAMETER Enabled Indicates whether to enable or disable VerboseLogon messages #> Param($Enabled) Try{ if ($Enabled -eq $false){ Write-Host "Enabling Verbose Logon Messages" $value = 1 } else { Write-Host "Disabling Verbose Logon Messages" $value = 0 } $Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" Set-ItemProperty -Path $Path -Name VerboseStatus -Value $value } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Remove-WinUtilAPPX { <# .SYNOPSIS Removes all APPX packages that match the given name .PARAMETER Name The name of the APPX package to remove .EXAMPLE Remove-WinUtilAPPX -Name "Microsoft.Microsoft3DViewer" #> param ( $Name ) Try { Write-Host "Removing $Name" Get-AppxPackage "*$Name*" | Remove-AppxPackage -ErrorAction SilentlyContinue Get-AppxProvisionedPackage -Online | Where-Object DisplayName -like "*$Name*" | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue } Catch [System.Exception] { if ($psitem.Exception.Message -like "*The requested operation requires elevation*") { Write-Warning "Unable to uninstall $name due to a Security Exception" } else { Write-Warning "Unable to uninstall $name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } Catch{ Write-Warning "Unable to uninstall $name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Set-WinUtilDNS { <# .SYNOPSIS Sets the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file .PARAMETER DNSProvider The DNS provider to set the DNS server to .EXAMPLE Set-WinUtilDNS -DNSProvider "google" #> param($DNSProvider) if($DNSProvider -eq "Default"){return} Try{ $Adapters = Get-NetAdapter | Where-Object {$_.Status -eq "Up"} Write-Host "Ensuring DNS is set to $DNSProvider on the following interfaces" Write-Host $($Adapters | Out-String) Foreach ($Adapter in $Adapters){ if($DNSProvider -eq "DHCP"){ Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ResetServerAddresses } Else{ Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ServerAddresses ("$($sync.configs.dns.$DNSProvider.Primary)", "$($sync.configs.dns.$DNSProvider.Secondary)") } } } Catch{ Write-Warning "Unable to set DNS Provider due to an unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Set-WinUtilRegistry { <# .SYNOPSIS Modifies the registry based on the given inputs .PARAMETER Name The name of the key to modify .PARAMETER Path The path to the key .PARAMETER Type The type of value to set the key to .PARAMETER Value The value to set the key to .EXAMPLE Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" #> param ( $Name, $Path, $Type, $Value ) Try{ if(!(Test-Path 'HKU:\')){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS} If (!(Test-Path $Path)) { Write-Host "$Path was not found, Creating..." New-Item -Path $Path -Force -ErrorAction Stop | Out-Null } Write-Host "Set $Path\$Name to $Value" Set-ItemProperty -Path $Path -Name $Name -Type $Type -Value $Value -Force -ErrorAction Stop | Out-Null } Catch [System.Security.SecurityException] { Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception" } Catch [System.Management.Automation.ItemNotFoundException] { Write-Warning $psitem.Exception.ErrorRecord } Catch{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } function Set-WinUtilScheduledTask { <# .SYNOPSIS Enables/Disables the provided Scheduled Task .PARAMETER Name The path to the Scheduled Task .PARAMETER State The State to set the Task to .EXAMPLE Set-WinUtilScheduledTask -Name "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -State "Disabled" #> param ( $Name, $State ) Try{ if($State -eq "Disabled"){ Write-Host "Disabling Scheduled Task $Name" Disable-ScheduledTask -TaskName $Name -ErrorAction Stop } if($State -eq "Enabled"){ Write-Host "Enabling Scheduled Task $Name" Enable-ScheduledTask -TaskName $Name -ErrorAction Stop } } Catch [System.Exception]{ if($psitem.Exception.Message -like "*The system cannot find the file specified*"){ Write-Warning "Scheduled Task $name was not Found" } Else{ Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $psitem.Exception.Message } } Catch{ Write-Warning "Unable to run script for $name due to unhandled exception" Write-Warning $psitem.Exception.StackTrace } } Function Set-WinUtilService { <# .SYNOPSIS Changes the startup type of the given service .PARAMETER Name The name of the service to modify .PARAMETER StartupType The startup type to set the service to .EXAMPLE Set-WinUtilService -Name "HomeGroupListener" -StartupType "Manual" #> param ( $Name, $StartupType ) try { Write-Host "Setting Service $Name to $StartupType" # Check if the service exists $service = Get-Service -Name $Name -ErrorAction Stop # Service exists, proceed with changing properties $service | Set-Service -StartupType $StartupType -ErrorAction Stop } catch [System.ServiceProcess.ServiceNotFoundException] { Write-Warning "Service $Name was not found" } catch { Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $_.Exception.Message } } function Set-WinUtilUITheme { <# .SYNOPSIS Sets the theme of the XAML file .PARAMETER inputXML A string representing the XAML object to modify .PARAMETER themeName The name of the theme to set the XAML to. Defaults to 'matrix' .EXAMPLE Set-WinUtilUITheme -inputXAML $inputXAML #> param ( [Parameter(Mandatory=$true, Position=0)] [string] $inputXML, [Parameter(Mandatory=$false, Position=1)] [string] $themeName = 'matrix' ) try { # Convert the JSON to a PowerShell object $themes = $sync.configs.themes # Select the specified theme $selectedTheme = $themes.$themeName if ($selectedTheme) { # Loop through all key-value pairs in the selected theme foreach ($property in $selectedTheme.PSObject.Properties) { $key = $property.Name $value = $property.Value # Add curly braces around the key $formattedKey = "{$key}" # Replace the key with the value in the input XML $inputXML = $inputXML.Replace($formattedKey, $value) } } else { Write-Host "Theme '$themeName' not found." } } catch { Write-Warning "Unable to apply theme" Write-Warning $psitem.Exception.StackTrace } return $inputXML; } function Show-CustomDialog { <# .SYNOPSIS Displays a custom dialog box with an image, heading, message, and an OK button. .DESCRIPTION This function creates a custom dialog box with the specified message and additional elements such as an image, heading, and an OK button. The dialog box is designed with a green border, rounded corners, and a black background. .PARAMETER Message The message to be displayed in the dialog box. .PARAMETER Width The width of the custom dialog window. .PARAMETER Height The height of the custom dialog window. .EXAMPLE Show-CustomDialog -Message "This is a custom dialog with a message and an image above." -Width 300 -Height 200 #> param( [string]$Message, [int]$Width = 300, [int]$Height = 200 ) Add-Type -AssemblyName PresentationFramework # Define theme colors $foregroundColor = [Windows.Media.Brushes]::White $backgroundColor = [Windows.Media.Brushes]::Black $font = New-Object Windows.Media.FontFamily("Consolas") $borderColor = [Windows.Media.Brushes]::Green $buttonBackgroundColor = [Windows.Media.Brushes]::Black $buttonForegroundColor = [Windows.Media.Brushes]::White $shadowColor = [Windows.Media.ColorConverter]::ConvertFromString("#AAAAAAAA") # Create a custom dialog window $dialog = New-Object Windows.Window $dialog.Title = "About" $dialog.Height = $Height $dialog.Width = $Width $dialog.Margin = New-Object Windows.Thickness(10) # Add margin to the entire dialog box $dialog.WindowStyle = [Windows.WindowStyle]::None # Remove title bar and window controls $dialog.ResizeMode = [Windows.ResizeMode]::NoResize # Disable resizing $dialog.WindowStartupLocation = [Windows.WindowStartupLocation]::CenterScreen # Center the window $dialog.Foreground = $foregroundColor $dialog.Background = $backgroundColor $dialog.FontFamily = $font # Create a Border for the green edge with rounded corners $border = New-Object Windows.Controls.Border $border.BorderBrush = $borderColor $border.BorderThickness = New-Object Windows.Thickness(1) # Adjust border thickness as needed $border.CornerRadius = New-Object Windows.CornerRadius(10) # Adjust the radius for rounded corners # Create a drop shadow effect $dropShadow = New-Object Windows.Media.Effects.DropShadowEffect $dropShadow.Color = $shadowColor $dropShadow.Direction = 270 $dropShadow.ShadowDepth = 5 $dropShadow.BlurRadius = 10 # Apply drop shadow effect to the border $dialog.Effect = $dropShadow $dialog.Content = $border # Create a grid for layout inside the Border $grid = New-Object Windows.Controls.Grid $border.Child = $grid # Add the following line to show gridlines #$grid.ShowGridLines = $true # Add the following line to set the background color of the grid $grid.Background = [Windows.Media.Brushes]::Transparent # Add the following line to make the Grid stretch $grid.HorizontalAlignment = [Windows.HorizontalAlignment]::Stretch $grid.VerticalAlignment = [Windows.VerticalAlignment]::Stretch # Add the following line to make the Border stretch $border.HorizontalAlignment = [Windows.HorizontalAlignment]::Stretch $border.VerticalAlignment = [Windows.VerticalAlignment]::Stretch # Set up Row Definitions $row0 = New-Object Windows.Controls.RowDefinition $row0.Height = [Windows.GridLength]::Auto $row1 = New-Object Windows.Controls.RowDefinition $row1.Height = [Windows.GridLength]::new(1, [Windows.GridUnitType]::Star) $row2 = New-Object Windows.Controls.RowDefinition $row2.Height = [Windows.GridLength]::Auto # Add Row Definitions to Grid $grid.RowDefinitions.Add($row0) $grid.RowDefinitions.Add($row1) $grid.RowDefinitions.Add($row2) # Add StackPanel for horizontal layout with margins $stackPanel = New-Object Windows.Controls.StackPanel $stackPanel.Margin = New-Object Windows.Thickness(10) # Add margins around the stack panel $stackPanel.Orientation = [Windows.Controls.Orientation]::Horizontal $stackPanel.HorizontalAlignment = [Windows.HorizontalAlignment]::Left # Align to the left $stackPanel.VerticalAlignment = [Windows.VerticalAlignment]::Top # Align to the top $grid.Children.Add($stackPanel) [Windows.Controls.Grid]::SetRow($stackPanel, 0) # Set the row to the second row (0-based index) $viewbox = New-Object Windows.Controls.Viewbox $viewbox.Width = 25 $viewbox.Height = 25 # Combine the paths into a single string # $cttLogoPath = @" # M174 1094 c-4 -14 -4 -55 -2 -92 3 -57 9 -75 41 -122 41 -60 45 -75 22 -84 -25 -9 -17 -21 30 -44 l45 -22 0 -103 c0 -91 3 -109 26 -155 30 -60 65 -87 204 -157 l95 -48 110 58 c184 96 205 127 205 293 l0 108 45 22 c47 23 55 36 30 46 -22 8 -18 30 9 63 13 16 34 48 46 71 20 37 21 52 15 116 l-6 73 -69 -23 c-38 -12 -137 -59 -220 -103 -82 -45 -160 -81 -171 -81 -12 0 -47 15 -78 34 -85 51 -239 127 -309 151 l-62 22 -6 -23z m500 -689 c20 -8 36 -19 36 -24 0 -18 -53 -51 -80 -51 -28 0 -80 33 -80 51 0 10 55 38 76 39 6 0 28 -7 48 -15z # M177 711 c-19 -88 4 -242 49 -318 43 -74 107 -127 232 -191 176 -90 199 -84 28 7 -169 91 -214 129 -258 220 -29 58 -32 74 -37 190 -4 90 -8 116 -14 92z # M1069 610 c-4 -131 -5 -137 -38 -198 -43 -79 -89 -119 -210 -181 -53 -27 -116 -61 -141 -76 -74 -43 -6 -20 115 40 221 109 296 217 294 425 -1 144 -16 137 -20 -10z # "@ $cttLogoPath = @" M 18.00,14.00 C 18.00,14.00 45.00,27.74 45.00,27.74 45.00,27.74 57.40,34.63 57.40,34.63 57.40,34.63 59.00,43.00 59.00,43.00 59.00,43.00 59.00,83.00 59.00,83.00 55.35,81.66 46.99,77.79 44.72,74.79 41.17,70.10 42.01,59.80 42.00,54.00 42.00,51.62 42.20,48.29 40.98,46.21 38.34,41.74 25.78,38.60 21.28,33.79 16.81,29.02 18.00,20.20 18.00,14.00 Z M 107.00,14.00 C 109.01,19.06 108.93,30.37 104.66,34.21 100.47,37.98 86.38,43.10 84.60,47.21 83.94,48.74 84.01,51.32 84.00,53.00 83.97,57.04 84.46,68.90 83.26,72.00 81.06,77.70 72.54,81.42 67.00,83.00 67.00,83.00 67.00,43.00 67.00,43.00 67.00,43.00 67.99,35.63 67.99,35.63 67.99,35.63 80.00,28.26 80.00,28.26 80.00,28.26 107.00,14.00 107.00,14.00 Z M 19.00,46.00 C 21.36,47.14 28.67,50.71 30.01,52.63 31.17,54.30 30.99,57.04 31.00,59.00 31.04,65.41 30.35,72.16 33.56,78.00 38.19,86.45 46.10,89.04 54.00,93.31 56.55,94.69 60.10,97.20 63.00,97.22 65.50,97.24 68.77,95.36 71.00,94.25 76.42,91.55 84.51,87.78 88.82,83.68 94.56,78.20 95.96,70.59 96.00,63.00 96.01,60.24 95.59,54.63 97.02,52.39 98.80,49.60 103.95,47.87 107.00,47.00 107.00,47.00 107.00,67.00 107.00,67.00 106.90,87.69 96.10,93.85 80.00,103.00 76.51,104.98 66.66,110.67 63.00,110.52 60.33,110.41 55.55,107.53 53.00,106.25 46.21,102.83 36.63,98.57 31.04,93.68 16.88,81.28 19.00,62.88 19.00,46.00 Z "@ # Add SVG path $svgPath = New-Object Windows.Shapes.Path $svgPath.Data = [Windows.Media.Geometry]::Parse($cttLogoPath) $svgPath.Fill = $foregroundColor # Set fill color to white # Add SVG path to Viewbox $viewbox.Child = $svgPath # Add SVG path to the stack panel $stackPanel.Children.Add($viewbox) # Add "Winutil" text $winutilTextBlock = New-Object Windows.Controls.TextBlock $winutilTextBlock.Text = "Winutil" $winutilTextBlock.FontSize = 18 # Adjust font size as needed $winutilTextBlock.Foreground = $foregroundColor $winutilTextBlock.Margin = New-Object Windows.Thickness(10, 5, 10, 5) # Add margins around the text block $stackPanel.Children.Add($winutilTextBlock) # Add TextBlock for information with text wrapping and margins $messageTextBlock = New-Object Windows.Controls.TextBlock $messageTextBlock.Text = $Message $messageTextBlock.TextWrapping = [Windows.TextWrapping]::Wrap # Enable text wrapping $messageTextBlock.HorizontalAlignment = [Windows.HorizontalAlignment]::Left $messageTextBlock.VerticalAlignment = [Windows.VerticalAlignment]::Top $messageTextBlock.Margin = New-Object Windows.Thickness(10) # Add margins around the text block $grid.Children.Add($messageTextBlock) [Windows.Controls.Grid]::SetRow($messageTextBlock, 1) # Set the row to the second row (0-based index) # Add OK button $okButton = New-Object Windows.Controls.Button $okButton.Content = "OK" $okButton.Width = 80 $okButton.Height = 30 $okButton.HorizontalAlignment = [Windows.HorizontalAlignment]::Center $okButton.VerticalAlignment = [Windows.VerticalAlignment]::Bottom $okButton.Margin = New-Object Windows.Thickness(0, 0, 0, 10) $okButton.Background = $buttonBackgroundColor $okButton.Foreground = $buttonForegroundColor $okButton.BorderBrush = $borderColor $okButton.Add_Click({ $dialog.Close() }) $grid.Children.Add($okButton) [Windows.Controls.Grid]::SetRow($okButton, 2) # Set the row to the third row (0-based index) # Handle Escape key press to close the dialog $dialog.Add_KeyDown({ if ($_.Key -eq 'Escape') { $dialog.Close() } }) # Set the OK button as the default button (activated on Enter) $okButton.IsDefault = $true # Show the custom dialog $dialog.ShowDialog() } function Test-WinUtilPackageManager { <# .SYNOPSIS Checks if Winget and/or Choco are installed .PARAMETER winget Check if Winget is installed .PARAMETER choco Check if Chocolatey is installed #> Param( [System.Management.Automation.SwitchParameter]$winget, [System.Management.Automation.SwitchParameter]$choco ) if($winget){ if (Test-Path ~\AppData\Local\Microsoft\WindowsApps\winget.exe) { return $true } } if($choco){ if ((Get-Command -Name choco -ErrorAction Ignore) -and ($chocoVersion = (Get-Item "$env:ChocolateyInstall\choco.exe" -ErrorAction Ignore).VersionInfo.ProductVersion)){ return $true } } return $false } Function Update-WinUtilProgramWinget { <# .SYNOPSIS This will update all programs using Winget #> [ScriptBlock]$wingetinstall = { $host.ui.RawUI.WindowTitle = """Winget Install""" Start-Transcript $ENV:TEMP\winget-update.log -Append winget upgrade --all } $global:WinGetInstall = Start-Process -Verb runas powershell -ArgumentList "-command invoke-command -scriptblock {$wingetinstall} -argumentlist '$($ProgramsToInstall -join ",")'" -PassThru } function Invoke-WPFButton { <# .SYNOPSIS Invokes the function associated with the clicked button .PARAMETER Button The name of the button that was clicked #> Param ([string]$Button) # Use this to get the name of the button #[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info") Switch -Wildcard ($Button){ "WPFTab?BT" {Invoke-WPFTab $Button} "WPFinstall" {Invoke-WPFInstall} "WPFuninstall" {Invoke-WPFUnInstall} "WPFInstallUpgrade" {Invoke-WPFInstallUpgrade} "WPFdesktop" {Invoke-WPFPresets "Desktop"} "WPFlaptop" {Invoke-WPFPresets "laptop"} "WPFminimal" {Invoke-WPFPresets "minimal"} "WPFclear" {Invoke-WPFPresets -preset $null -imported $true} "WPFclearWinget" {Invoke-WPFPresets -preset $null -imported $true -CheckBox "WPFInstall"} "WPFtweaksbutton" {Invoke-WPFtweaksbutton} "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enabled"} "WPFRemoveUltPerf" {Invoke-WPFUltimatePerformance -State "Disabled"} "WPFundoall" {Invoke-WPFundoall} "WPFFeatureInstall" {Invoke-WPFFeatureInstall} "WPFPanelDISM" {Invoke-WPFPanelDISM} "WPFPanelAutologin" {Invoke-WPFPanelAutologin} "WPFPanelcontrol" {Invoke-WPFControlPanel -Panel $button} "WPFPanelnetwork" {Invoke-WPFControlPanel -Panel $button} "WPFPanelpower" {Invoke-WPFControlPanel -Panel $button} "WPFPanelregion" {Invoke-WPFControlPanel -Panel $button} "WPFPanelsound" {Invoke-WPFControlPanel -Panel $button} "WPFPanelsystem" {Invoke-WPFControlPanel -Panel $button} "WPFPaneluser" {Invoke-WPFControlPanel -Panel $button} "WPFUpdatesdefault" {Invoke-WPFUpdatesdefault} "WPFFixesUpdate" {Invoke-WPFFixesUpdate} "WPFFixesWinget" {Invoke-WPFFixesWinget} "WPFFixesNetwork" {Invoke-WPFFixesNetwork} "WPFUpdatesdisable" {Invoke-WPFUpdatesdisable} "WPFUpdatessecurity" {Invoke-WPFUpdatessecurity} "WPFWinUtilShortcut" {Invoke-WPFShortcut -ShortcutToAdd "WinUtil"} "WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"} "WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"} "WPFGetIso" {Invoke-WPFGetIso} "WPFMicrowin" {Invoke-WPFMicrowin} "WPFCloseButton" {Invoke-WPFCloseButton} } } function Invoke-WPFCloseButton { <# .SYNOPSIS Close application .PARAMETER Button #> $sync["Form"].Close() Write-Host "Bye bye!" } function Invoke-WPFControlPanel { <# .SYNOPSIS Opens the requested legacy panel .PARAMETER Panel The panel to open #> param($Panel) switch ($Panel){ "WPFPanelcontrol" {cmd /c control} "WPFPanelnetwork" {cmd /c ncpa.cpl} "WPFPanelpower" {cmd /c powercfg.cpl} "WPFPanelregion" {cmd /c intl.cpl} "WPFPanelsound" {cmd /c mmsys.cpl} "WPFPanelsystem" {cmd /c sysdm.cpl} "WPFPaneluser" {cmd /c "control userpasswords2"} } } function Invoke-WPFFeatureInstall { <# .SYNOPSIS Installs selected Windows Features #> if($sync.ProcessRunning){ $msg = "[Invoke-WPFFeatureInstall] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $Features = (Get-WinUtilCheckBoxes)["WPFFeatures"] Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock { param($Features, $DebugPreference) $sync.ProcessRunning = $true Invoke-WinUtilFeatureInstall $Features $sync.ProcessRunning = $false Write-Host "===================================" Write-Host "--- Features are Installed ---" Write-Host "--- A Reboot may be required ---" Write-Host "===================================" } } function Invoke-WPFFixesNetwork { <# .SYNOPSIS Resets various network configurations #> Write-Host "Resetting Network with netsh" # Reset WinSock catalog to a clean state Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winsock", "reset" # Resets WinHTTP proxy setting to DIRECT Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winhttp", "reset", "proxy" # Removes all user configured IP settings Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "int", "ip", "reset" Write-Host "Process complete. Please reboot your computer." $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Network Reset " $Messageboxbody = ("Stock settings loaded.`n Please reboot your computer") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "==========================================" Write-Host "-- Network Configuration has been Reset --" Write-Host "==========================================" } function Invoke-WPFFixesUpdate { <# .SYNOPSIS Performs various tasks in an attempt to repair Windows Update .DESCRIPTION 1. (Aggressive Only) Scans the system for corruption using chkdsk, SFC, and DISM Steps: 1. Runs chkdsk /scan /perf /scan - Runs an online scan on the volume /perf - Uses more system resources to complete a scan as fast as possible 2. Runs SFC /scannow /scannow - Scans integrity of all protected system files and repairs files with problems when possible 3. Runs DISM /Online /Cleanup-Image /RestoreHealth /Online - Targets the running operating system /Cleanup-Image - Performs cleanup and recovery operations on the image /RestoreHealth - Scans the image for component store corruption and attempts to repair the corruption using Windows Update 4. Runs SFC /scannow Ran twice in case DISM repaired SFC 2. Stops Windows Update Services 3. Remove the QMGR Data file, which stores BITS jobs 4. (Aggressive Only) Renames the DataStore and CatRoot2 folders DataStore - Contains the Windows Update History and Log Files CatRoot2 - Contains the Signatures for Windows Update Packages 5. Renames the Windows Update Download Folder 6. Deletes the Windows Update Log 7. (Aggressive Only) Resets the Security Descriptors on the Windows Update Services 8. Reregisters the BITS and Windows Update DLLs 9. Removes the WSUS client settings 10. Resets WinSock 11. Gets and deletes all BITS jobs 12. Sets the startup type of the Windows Update Services then starts them 13. Forces Windows Update to check for updates .PARAMETER Aggressive If specified, the script will take additional steps to repair Windows Update that are more dangerous, take a significant amount of time, or are generally unnecessary #> param($Aggressive = $false) Write-Progress -Id 0 -Activity "Repairing Windows Update" -PercentComplete 0 # Wait for the first progress bar to show, otherwise the second one won't show Start-Sleep -Milliseconds 200 if ($Aggressive) { # Scan system for corruption Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Scanning for corruption..." -PercentComplete 0 Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running chkdsk..." -PercentComplete 0 # 2>&1 redirects stdout, alowing iteration over the output chkdsk.exe /scan /perf 2>&1 | ForEach-Object { # Write stdout to the Verbose stream Write-Verbose $_ # Get the index of the total percentage $index = $_.IndexOf("Total:") if ( # If the percent is found ($percent = try {( $_.Substring( $index + 6, $_.IndexOf("%", $index) - $index - 6 ) ).Trim()} catch {0}) ` <# And the current percentage is greater than the previous one #>` -and $percent -gt $oldpercent ){ # Update the progress bar $oldpercent = $percent Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running chkdsk... ($percent%)" -PercentComplete $percent } } Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC..." -PercentComplete 0 $oldpercent = 0 # SFC has a bug when redirected which causes it to output only when the stdout buffer is full, causing the progress bar to move in chunks sfc /scannow 2>&1 | ForEach-Object { # Write stdout to the Verbose stream Write-Verbose $_ # Filter for lines that contain a percentage that is greater than the previous one if ( ( # Use a different method to get the percentage that accounts for SFC's Unicode output [int]$percent = try {( ( $_.Substring( $_.IndexOf("n") + 2, $_.IndexOf("%") - $_.IndexOf("n") - 2 ).ToCharArray() | Where-Object {$_} ) -join '' ).TrimStart()} catch {0} ) -and $percent -gt $oldpercent ){ # Update the progress bar $oldpercent = $percent Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC... ($percent%)" -PercentComplete $percent } } Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running DISM..." -PercentComplete 0 $oldpercent = 0 DISM /Online /Cleanup-Image /RestoreHealth | ForEach-Object { # Write stdout to the Verbose stream Write-Verbose $_ # Filter for lines that contain a percentage that is greater than the previous one if ( ($percent = try { [int]($_ -replace "\[" -replace "=" -replace " " -replace "%" -replace "\]") } catch {0}) ` -and $percent -gt $oldpercent ){ # Update the progress bar $oldpercent = $percent Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running DISM... ($percent%)" -PercentComplete $percent } } Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC again..." -PercentComplete 0 $oldpercent = 0 sfc /scannow 2>&1 | ForEach-Object { # Write stdout to the Verbose stream Write-Verbose $_ # Filter for lines that contain a percentage that is greater than the previous one if ( ( [int]$percent = try {( ( $_.Substring( $_.IndexOf("n") + 2, $_.IndexOf("%") - $_.IndexOf("n") - 2 ).ToCharArray() | Where-Object {$_} ) -join '' ).TrimStart()} catch {0} ) -and $percent -gt $oldpercent ){ # Update the progress bar $oldpercent = $percent Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC... ($percent%)" -PercentComplete $percent } } Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Completed" -PercentComplete 100 } Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Stopping Windows Update Services..." -PercentComplete 10 # Stop the Windows Update Services Write-Progress -Id 2 -ParentId 0 -Activity "Stopping Services" -Status "Stopping BITS..." -PercentComplete 0 Stop-Service -Name BITS -Force Write-Progress -Id 2 -ParentId 0 -Activity "Stopping Services" -Status "Stopping wuauserv..." -PercentComplete 20 Stop-Service -Name wuauserv -Force Write-Progress -Id 2 -ParentId 0 -Activity "Stopping Services" -Status "Stopping appidsvc..." -PercentComplete 40 Stop-Service -Name appidsvc -Force Write-Progress -Id 2 -ParentId 0 -Activity "Stopping Services" -Status "Stopping cryptsvc..." -PercentComplete 60 Stop-Service -Name cryptsvc -Force Write-Progress -Id 2 -ParentId 0 -Activity "Stopping Services" -Status "Completed" -PercentComplete 100 # Remove the QMGR Data file Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Renaming/Removing Files..." -PercentComplete 20 Write-Progress -Id 3 -ParentId 0 -Activity "Renaming/Removing Files" -Status "Removing QMGR Data files..." -PercentComplete 0 Remove-Item "$env:allusersprofile\Application Data\Microsoft\Network\Downloader\qmgr*.dat" -ErrorAction SilentlyContinue if ($Aggressive) { # Rename the Windows Update Log and Signature Folders Write-Progress -Id 3 -ParentId 0 -Activity "Renaming/Removing Files" -Status "Renaming the Windows Update Log, Download, and Signature Folder..." -PercentComplete 20 Rename-Item $env:systemroot\SoftwareDistribution\DataStore DataStore.bak -ErrorAction SilentlyContinue Rename-Item $env:systemroot\System32\Catroot2 catroot2.bak -ErrorAction SilentlyContinue } # Rename the Windows Update Download Folder Write-Progress -Id 3 -ParentId 0 -Activity "Renaming/Removing Files" -Status "Renaming the Windows Update Download Folder..." -PercentComplete 20 Rename-Item $env:systemroot\SoftwareDistribution\Download Download.bak -ErrorAction SilentlyContinue # Delete the legacy Windows Update Log Write-Progress -Id 3 -ParentId 0 -Activity "Renaming/Removing Files" -Status "Removing the old Windows Update log..." -PercentComplete 80 Remove-Item $env:systemroot\WindowsUpdate.log -ErrorAction SilentlyContinue Write-Progress -Id 3 -ParentId 0 -Activity "Renaming/Removing Files" -Status "Completed" -PercentComplete 100 if ($Aggressive) { # Reset the Security Descriptors on the Windows Update Services Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Resetting the WU Service Security Descriptors..." -PercentComplete 25 Write-Progress -Id 4 -ParentId 0 -Activity "Resetting the WU Service Security Descriptors" -Status "Resetting the BITS Security Descriptor..." -PercentComplete 0 Start-Process -NoNewWindow -FilePath "sc.exe" -ArgumentList "sdset", "bits", "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" Write-Progress -Id 4 -ParentId 0 -Activity "Resetting the WU Service Security Descriptors" -Status "Resetting the wuauserv Security Descriptor..." -PercentComplete 50 Start-Process -NoNewWindow -FilePath "sc.exe" -ArgumentList "sdset", "wuauserv", "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" Write-Progress -Id 4 -ParentId 0 -Activity "Resetting the WU Service Security Descriptors" -Status "Completed" -PercentComplete 100 } # Reregister the BITS and Windows Update DLLs Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Reregistering DLLs..." -PercentComplete 40 $oldLocation = Get-Location Set-Location $env:systemroot\system32 $i = 0 $DLLs = @( "atl.dll", "urlmon.dll", "mshtml.dll", "shdocvw.dll", "browseui.dll", "jscript.dll", "vbscript.dll", "scrrun.dll", "msxml.dll", "msxml3.dll", "msxml6.dll", "actxprxy.dll", "softpub.dll", "wintrust.dll", "dssenh.dll", "rsaenh.dll", "gpkcsp.dll", "sccbase.dll", "slbcsp.dll", "cryptdlg.dll", "oleaut32.dll", "ole32.dll", "shell32.dll", "initpki.dll", "wuapi.dll", "wuaueng.dll", "wuaueng1.dll", "wucltui.dll", "wups.dll", "wups2.dll", "wuweb.dll", "qmgr.dll", "qmgrprxy.dll", "wucltux.dll", "muweb.dll", "wuwebv.dll" ) foreach ($dll in $DLLs) { Write-Progress -Id 5 -ParentId 0 -Activity "Reregistering DLLs" -Status "Registering $dll..." -PercentComplete ($i / $DLLs.Count * 100) $i++ Start-Process -NoNewWindow -FilePath "regsvr32.exe" -ArgumentList "/s", $dll } Set-Location $oldLocation Write-Progress -Id 5 -ParentId 0 -Activity "Reregistering DLLs" -Status "Completed" -PercentComplete 100 # Remove the WSUS client settings if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate") { Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Removing WSUS client settings..." -PercentComplete 60 Write-Progress -Id 6 -ParentId 0 -Activity "Removing WSUS client settings" -PercentComplete 0 Start-Process -NoNewWindow -FilePath "REG" -ArgumentList "DELETE", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate", "/v", "AccountDomainSid", "/f" -RedirectStandardError $true Start-Process -NoNewWindow -FilePath "REG" -ArgumentList "DELETE", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate", "/v", "PingID", "/f" -RedirectStandardError $true Start-Process -NoNewWindow -FilePath "REG" -ArgumentList "DELETE", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate", "/v", "SusClientId", "/f" -RedirectStandardError $true Write-Progress -Id 6 -ParentId 0 -Activity "Removing WSUS client settings" -Status "Completed" -PercentComplete 100 } # Reset WinSock Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Resetting WinSock..." -PercentComplete 65 Write-Progress -Id 7 -ParentId 0 -Activity "Resetting WinSock" -Status "Resetting WinSock..." -PercentComplete 0 Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winsock", "reset" -RedirectStandardOutput $true Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winhttp", "reset", "proxy" -RedirectStandardOutput $true Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "int", "ip", "reset" -RedirectStandardOutput $true Write-Progress -Id 7 -ParentId 0 -Activity "Resetting WinSock" -Status "Completed" -PercentComplete 100 # Get and delete all BITS jobs Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Deleting BITS jobs..." -PercentComplete 75 Write-Progress -Id 8 -ParentId 0 -Activity "Deleting BITS jobs" -Status "Deleting BITS jobs..." -PercentComplete 0 Get-BitsTransfer | Remove-BitsTransfer Write-Progress -Id 8 -ParentId 0 -Activity "Deleting BITS jobs" -Status "Completed" -PercentComplete 100 # Change the startup type of the Windows Update Services and start them Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Starting Windows Update Services..." -PercentComplete 90 Write-Progress -Id 9 -ParentId 0 -Activity "Starting Windows Update Services" -Status "Starting BITS..." -PercentComplete 0 Get-Service BITS | Set-Service -StartupType Manual -PassThru | Start-Service Write-Progress -Id 9 -ParentId 0 -Activity "Starting Windows Update Services" -Status "Starting wuauserv..." -PercentComplete 25 Get-Service wuauserv | Set-Service -StartupType Manual -PassThru | Start-Service Write-Progress -Id 9 -ParentId 0 -Activity "Starting Windows Update Services" -Status "Starting AppIDSvc..." -PercentComplete 50 # The AppIDSvc service is protected, so the startup type has to be changed in the registry Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\AppIDSvc" -Name "Start" -Value "3" # Manual Start-Service AppIDSvc Write-Progress -Id 9 -ParentId 0 -Activity "Starting Windows Update Services" -Status "Starting CryptSvc..." -PercentComplete 75 Get-Service CryptSvc | Set-Service -StartupType Manual -PassThru | Start-Service Write-Progress -Id 9 -ParentId 0 -Activity "Starting Windows Update Services" -Status "Completed" -PercentComplete 100 # Force Windows Update to check for updates Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Forcing discovery..." -PercentComplete 95 Write-Progress -Id 10 -ParentId 0 -Activity "Forcing discovery" -Status "Forcing discovery..." -PercentComplete 0 (New-Object -ComObject Microsoft.Update.AutoUpdate).DetectNow() Start-Process -NoNewWindow -FilePath "wuauclt" -ArgumentList "/resetauthorization", "/detectnow" Write-Progress -Id 10 -ParentId 0 -Activity "Forcing discovery" -Status "Completed" -PercentComplete 100 Write-Progress -Id 0 -Activity "Repairing Windows Update" -Status "Completed" -PercentComplete 100 $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Reset Windows Update " $Messageboxbody = ("Stock settings loaded.`n Please reboot your computer") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "===============================================" Write-Host "-- Reset All Windows Update Settings to Stock -" Write-Host "===============================================" # Remove the progress bars Write-Progress -Id 0 -Activity "Repairing Windows Update" -Completed Write-Progress -Id 1 -Activity "Scanning for corruption" -Completed Write-Progress -Id 2 -Activity "Stopping Services" -Completed Write-Progress -Id 3 -Activity "Renaming/Removing Files" -Completed Write-Progress -Id 4 -Activity "Resetting the WU Service Security Descriptors" -Completed Write-Progress -Id 5 -Activity "Reregistering DLLs" -Completed Write-Progress -Id 6 -Activity "Removing WSUS client settings" -Completed Write-Progress -Id 7 -Activity "Resetting WinSock" -Completed Write-Progress -Id 8 -Activity "Deleting BITS jobs" -Completed Write-Progress -Id 9 -Activity "Starting Windows Update Services" -Completed Write-Progress -Id 10 -Activity "Forcing discovery" -Completed } function Invoke-WPFFixesWinget { <# .SYNOPSIS Fixes Winget by running choco install winget .DESCRIPTION BravoNorris for the fantastic idea of a button to reinstall winget #> Start-Process -FilePath "choco" -ArgumentList "install winget -y" -NoNewWindow -Wait } Function Invoke-WPFFormVariables { <# .SYNOPSIS Prints the logo #> #If ($global:ReadmeDisplay -ne $true) { Write-Host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow; $global:ReadmeDisplay = $true } Write-Host "" Write-Host " CCCCCCCCCCCCCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT " Write-Host " CCC::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T " Write-Host "CC:::::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T " Write-Host "C:::::CCCCCCCC::::CT:::::TT:::::::TT:::::TT:::::TT:::::::TT:::::T " Write-Host "C:::::C CCCCCCTTTTTT T:::::T TTTTTTTTTTTT T:::::T TTTTTT" Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C T:::::T T:::::T " Write-Host "C:::::C CCCCCC T:::::T T:::::T " Write-Host "C:::::CCCCCCCC::::C TT:::::::TT TT:::::::TT " Write-Host "CC:::::::::::::::C T:::::::::T T:::::::::T " Write-Host "CCC::::::::::::C T:::::::::T T:::::::::T " Write-Host " CCCCCCCCCCCCC TTTTTTTTTTT TTTTTTTTTTT " Write-Host "" Write-Host "====Chris Titus Tech=====" Write-Host "=====Windows Toolbox=====" #====DEBUG GUI Elements==== #Write-Host "Found the following interactable elements from our form" -ForegroundColor Cyan #get-variable WPF* } function Invoke-WPFGetInstalled { <# .SYNOPSIS Invokes the function that gets the checkboxes to check in a new runspace .PARAMETER checkbox Indicates whether to check for installed 'winget' programs or applied 'tweaks' #> param($checkbox) if($sync.ProcessRunning){ $msg = "[Invoke-WPFGetInstalled] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } if(!(Test-WinUtilPackageManager -winget) -and $checkbox -eq "winget"){ Write-Host "===========================================" Write-Host "-- Winget is not installed ---" Write-Host "===========================================" return } Invoke-WPFRunspace -ArgumentList $checkbox -DebugPreference $DebugPreference -ScriptBlock { param($checkbox, $DebugPreference) $sync.ProcessRunning = $true if($checkbox -eq "winget"){ Write-Host "Getting Installed Programs..." } if($checkbox -eq "tweaks"){ Write-Host "Getting Installed Tweaks..." } $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox $sync.form.Dispatcher.invoke({ foreach($checkbox in $Checkboxes){ $sync.$checkbox.ischecked = $True } }) Write-Host "Done..." $sync.ProcessRunning = $false } } function Invoke-WPFGetIso { <# .DESCRIPTION Function to get the path to Iso file for MicroWin, unpack that isom=, read basic information and populate the UI Options #> Write-Host "Invoking WPFGetIso" if($sync.ProcessRunning){ $msg = "GetIso process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Write-Host " _ __ __ _ " Write-Host " /\/\ (_) ___ _ __ ___ / / /\ \ \(_) _ __ " Write-Host " / \ | | / __|| '__| / _ \ \ \/ \/ /| || '_ \ " Write-Host "/ /\/\ \| || (__ | | | (_) | \ /\ / | || | | | " Write-Host "\/ \/|_| \___||_| \___/ \/ \/ |_||_| |_| " $oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe' $oscdImgFound = [bool] (Get-Command -ErrorAction Ignore -Type Application oscdimg.exe) -or (Test-Path $oscdimgPath -PathType Leaf) Write-Host "oscdimg.exe on system: $oscdImgFound" if (!$oscdImgFound) { $downloadFromGitHub = $sync.WPFMicrowinDownloadFromGitHub.IsChecked if (!$downloadFromGitHub) { # only show the message to people who did check the box to download from github, if you check the box # you consent to downloading it, no need to show extra dialogs [System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it using choco. This might take a long time.") # the step below needs choco to download oscdimg $chocoFound = [bool] (Get-Command -ErrorAction Ignore -Type Application choco) Write-Host "choco on system: $chocoFound" if (!$chocoFound) { [System.Windows.MessageBox]::Show("choco.exe is not found on the system, you need choco to download oscdimg.exe") return } Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install windows-adk-oscdimg" [System.Windows.MessageBox]::Show("oscdimg is installed, now close, reopen PowerShell terminal and re-launch winutil.ps1") return } else { [System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it from github. This might take a long time.") Get-Oscdimg -oscdimgPath $oscdimgPath $oscdImgFound = Test-Path $oscdimgPath -PathType Leaf if (!$oscdImgFound) { $msg = "oscdimg was not downloaded can not proceed" [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) return } else { Write-Host "oscdimg.exe was successfully downloaded from github" } } } [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog $openFileDialog.initialDirectory = $initialDirectory $openFileDialog.filter = "ISO files (*.iso)| *.iso" $openFileDialog.ShowDialog() | Out-Null $filePath = $openFileDialog.FileName if ([string]::IsNullOrEmpty($filePath)) { Write-Host "No ISO is chosen" return } Write-Host "File path $($filePath)" if (-not (Test-Path -Path $filePath -PathType Leaf)) { $msg = "File you've chosen doesn't exist" [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) return } try { Write-Host "Mounting Iso. Please wait." $mountedISO = Mount-DiskImage -PassThru "$filePath" Write-Host "Done mounting Iso $mountedISO" $driveLetter = (Get-Volume -DiskImage $mountedISO).DriveLetter Write-Host "Iso mounted to '$driveLetter'" } catch { # @ChrisTitusTech please copy this wiki and change the link below to your copy of the wiki Write-Error "Failed to mount the image. Error: $($_.Exception.Message)" Write-Error "This is NOT winutil's problem, your ISO might be corrupt, or there is a problem on the system" Write-Error "Please refer to this wiki for more details https://github.com/ChrisTitusTech/winutil/blob/main/wiki/Error-in-Winutil-MicroWin-during-ISO-mounting%2Cmd" return } # storing off values in hidden fields for further steps # there is probably a better way of doing this, I don't have time to figure this out $sync.MicrowinIsoDrive.Text = $driveLetter Write-Host "Setting up mount dir and scratch dirs" $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $randomNumber = Get-Random -Minimum 1 -Maximum 9999 $randomMicrowin = "Microwin_${timestamp}_${randomNumber}" $randomMicrowinScratch = "MicrowinScratch_${timestamp}_${randomNumber}" $mountDir = Join-Path $env:TEMP $randomMicrowin $scratchDir = Join-Path $env:TEMP $randomMicrowinScratch $sync.MicrowinMountDir.Text = $mountDir $sync.MicrowinScratchDir.Text = $scratchDir Write-Host "Done setting up mount dir and scratch dirs" Write-Host "Scratch dir is $scratchDir" Write-Host "Image dir is $mountDir" try { #$data = @($driveLetter, $filePath) New-Item -ItemType Directory -Force -Path "$($mountDir)" | Out-Null New-Item -ItemType Directory -Force -Path "$($scratchDir)" | Out-Null Write-Host "Copying Windows image. This will take awhile, please don't use UI or cancel this step!" # xcopy we can verify files and also not copy files that already exist, but hard to measure # xcopy.exe /E /I /H /R /Y /J $DriveLetter":" $mountDir >$null $totalTime = Measure-Command { Copy-Files "$($driveLetter):" $mountDir -Recurse -Force } Write-Host "Copy complete! Total Time: $($totalTime.Minutes)m$($totalTime.Seconds)s" $wimFile = "$mountDir\sources\install.wim" Write-Host "Getting image information $wimFile" if (-not (Test-Path -Path $wimFile -PathType Leaf)) { $msg = "Install.wim file doesn't exist in the image, this could happen if you use unofficial Windows images, or a Media creation tool, which creates a final image that can not be modified. Please don't use shady images from the internet, use only official images. Here are instructions how to download ISO images if the Microsoft website is not showing the link to download and ISO. https://www.techrepublic.com/article/how-to-download-a-windows-10-iso-file-without-using-the-media-creation-tool/" Write-Host $msg [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) throw } $sync.MicrowinWindowsFlavors.Items.Clear() Get-WindowsImage -ImagePath $wimFile | ForEach-Object { $imageIdx = $_.ImageIndex $imageName = $_.ImageName $sync.MicrowinWindowsFlavors.Items.Add("$imageIdx : $imageName") } $sync.MicrowinWindowsFlavors.SelectedIndex = 0 Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage Write-Host "Selected value '$($sync.MicrowinWindowsFlavors.SelectedValue)'....." $sync.MicrowinOptionsPanel.Visibility = 'Visible' } catch { Write-Host "Dismounting bad image..." Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage Remove-Item -Recurse -Force "$($scratchDir)" Remove-Item -Recurse -Force "$($mountDir)" } Write-Host "Done reading and unpacking ISO" Write-Host "" Write-Host "*********************************" Write-Host "Check the UI for further steps!!!" $sync.ProcessRunning = $false } function Invoke-WPFImpex { <# .SYNOPSIS Handles importing and exporting of the checkboxes checked for the tweaks section .PARAMETER type Indicates whether to 'import' or 'export' .PARAMETER checkbox The checkbox to export to a file or apply the imported file to .EXAMPLE Invoke-WPFImpex -type "export" #> param( $type, $Config = $null ) if ($type -eq "export"){ $FileBrowser = New-Object System.Windows.Forms.SaveFileDialog } if ($type -eq "import"){ $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog } if (-not $Config){ $FileBrowser.InitialDirectory = [Environment]::GetFolderPath('Desktop') $FileBrowser.Filter = "JSON Files (*.json)|*.json" $FileBrowser.ShowDialog() | Out-Null if($FileBrowser.FileName -eq ""){ return } else{ $Config = $FileBrowser.FileName } } if ($type -eq "export"){ $jsonFile = Get-WinUtilCheckBoxes -unCheck $false $jsonFile | ConvertTo-Json | Out-File $FileBrowser.FileName -Force } if ($type -eq "import"){ $jsonFile = Get-Content $Config | ConvertFrom-Json $flattenedJson = @() $jsonFile.PSObject.Properties | ForEach-Object { $category = $_.Name foreach ($checkboxName in $_.Value) { if ($category -ne "Install") { $flattenedJson += $checkboxName } } } Invoke-WPFPresets -preset $flattenedJson -imported $true } } function Invoke-WPFInstall { <# .SYNOPSIS Installs the selected programs using winget #> if($sync.ProcessRunning){ $msg = "[Invoke-WPFInstall] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] if ($wingetinstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Invoke-WPFRunspace -ArgumentList $WingetInstall -DebugPreference $DebugPreference -ScriptBlock { param($WingetInstall, $DebugPreference) try{ $sync.ProcessRunning = $true Install-WinUtilWinget Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall Write-Host "===========================================" Write-Host "-- Installs have finished ---" Write-Host "===========================================" } Catch { Write-Host "===========================================" Write-Host "-- Winget failed to install ---" Write-Host "===========================================" } Start-Sleep -Seconds 5 $sync.ProcessRunning = $False } } function Invoke-WPFInstallUpgrade { <# .SYNOPSIS Invokes the function that upgrades all installed programs using winget #> if(!(Test-WinUtilPackageManager -winget)){ Write-Host "===========================================" Write-Host "-- Winget is not installed ---" Write-Host "===========================================" return } if(Get-WinUtilInstallerProcess -Process $global:WinGetInstall){ $msg = "[Invoke-WPFInstallUpgrade] Install process is currently running. Please check for a powershell window labeled 'Winget Install'" [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Update-WinUtilProgramWinget Write-Host "===========================================" Write-Host "-- Updates started ---" Write-Host "-- You can close this window if desired ---" Write-Host "===========================================" } function Invoke-WPFMicrowin { <# .DESCRIPTION Invoke MicroWin routines... #> if($sync.ProcessRunning) { $msg = "GetIso process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } # Define the constants for Windows API Add-Type @" using System; using System.Runtime.InteropServices; public class PowerManagement { [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags); [FlagsAttribute] public enum EXECUTION_STATE : uint { ES_SYSTEM_REQUIRED = 0x00000001, ES_DISPLAY_REQUIRED = 0x00000002, ES_CONTINUOUS = 0x80000000, } } "@ # Prevent the machine from sleeping [PowerManagement]::SetThreadExecutionState([PowerManagement]::EXECUTION_STATE::ES_CONTINUOUS -bor [PowerManagement]::EXECUTION_STATE::ES_SYSTEM_REQUIRED -bor [PowerManagement]::EXECUTION_STATE::ES_DISPLAY_REQUIRED) # Ask the user where to save the file $SaveDialog = New-Object System.Windows.Forms.SaveFileDialog $SaveDialog.InitialDirectory = [Environment]::GetFolderPath('Desktop') $SaveDialog.Filter = "ISO images (*.iso)|*.iso" $SaveDialog.ShowDialog() | Out-Null if ($SaveDialog.FileName -eq "") { Write-Host "No file name for the target image was specified" return } Write-Host "Target ISO location: $($SaveDialog.FileName)" $index = $sync.MicrowinWindowsFlavors.SelectedValue.Split(":")[0].Trim() Write-Host "Index chosen: '$index' from $($sync.MicrowinWindowsFlavors.SelectedValue)" $keepPackages = $sync.WPFMicrowinKeepProvisionedPackages.IsChecked $keepProvisionedPackages = $sync.WPFMicrowinKeepAppxPackages.IsChecked $keepDefender = $sync.WPFMicrowinKeepDefender.IsChecked $keepEdge = $sync.WPFMicrowinKeepEdge.IsChecked $copyToUSB = $sync.WPFMicrowinCopyToUsb.IsChecked $injectDrivers = $sync.MicrowinInjectDrivers.IsChecked $mountDir = $sync.MicrowinMountDir.Text $scratchDir = $sync.MicrowinScratchDir.Text $imgVersion = (Get-WindowsImage -ImagePath $mountDir\sources\install.wim -Index $index).Version # Detect image version to avoid performing MicroWin processing on Windows 8 and earlier if ((Is-CompatibleImage $imgVersion) -eq $false) { $msg = "This image is not compatible with MicroWin processing. Make sure it isn't a Windows 8 or earlier image." $dlg_msg = $msg + "`n`nIf you want more information, the version of the image selected is $($imgVersion)`n`nIf an image has been incorrectly marked as incompatible, report an issue to the developers." Write-Host $msg [System.Windows.MessageBox]::Show($dlg_msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Exclamation) return } $mountDirExists = Test-Path $mountDir $scratchDirExists = Test-Path $scratchDir if (-not $mountDirExists -or -not $scratchDirExists) { Write-Error "Required directories '$mountDirExists' '$scratchDirExists' and do not exist." return } try { Write-Host "Mounting Windows image. This may take a while." dism /mount-image /imagefile:$mountDir\sources\install.wim /index:$index /mountdir:$scratchDir Write-Host "Mounting complete! Performing removal of applications..." if ($injectDrivers) { $driverPath = $sync.MicrowinDriverLocation.Text if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { Write-Host "Path to drivers is invalid continuing without driver injection" } } Write-Host "Remove Features from the image" Remove-Features -keepDefender:$keepDefender Write-Host "Removing features complete!" Write-Host "Removing Appx Bloat" if (!$keepPackages) { Remove-Packages } if (!$keepProvisionedPackages) { Remove-ProvisionedPackages -keepSecurity:$keepDefender } # special code, for some reason when you try to delete some inbox apps # we have to get and delete log files directory. Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\WebThreatDefSvc" -Directory # Defender is hidden in 2 places we removed a feature above now need to remove it from the disk if (!$keepDefender) { Write-Host "Removing Defender" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Defender" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Defender" } if (!$keepEdge) { Write-Host "Removing Edge" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Microsoft" -mask "*edge*" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Microsoft" -mask "*edge*" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*edge*" -Directory } Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\DiagTrack" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\InboxApps" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\SecurityHealthSystray.exe" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\LocationNotificationWindows.exe" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Photo Viewer" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Photo Viewer" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Media Player" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Media Player" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Mail" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Mail" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Internet Explorer" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Internet Explorer" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\GameBarPresenceWriter" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\OneDriveSetup.exe" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\OneDrive.ico" Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*Windows.Search*" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*narratorquickstart*" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*Xbox*" -Directory Remove-FileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*ParentalControls*" -Directory Write-Host "Removal complete!" Write-Host "Create unattend.xml" New-Unattend Write-Host "Done Create unattend.xml" Write-Host "Copy unattend.xml file into the ISO" New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\Panther" Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\Windows\Panther\unattend.xml" -force New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\System32\Sysprep" Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\Windows\System32\Sysprep\unattend.xml" -force Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\unattend.xml" -force Write-Host "Done Copy unattend.xml" Write-Host "Create FirstRun" New-FirstRun Write-Host "Done create FirstRun" Write-Host "Copy FirstRun.ps1 into the ISO" Copy-Item "$env:temp\FirstStartup.ps1" "$($scratchDir)\Windows\FirstStartup.ps1" -force Write-Host "Done copy FirstRun.ps1" Write-Host "Copy link to winutil.ps1 into the ISO" $desktopDir = "$($scratchDir)\Windows\Users\Default\Desktop" New-Item -ItemType Directory -Force -Path "$desktopDir" dism /English /image:$($scratchDir) /set-profilepath:"$($scratchDir)\Windows\Users\Default" $command = "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'irm https://christitus.com/win | iex'" $shortcutPath = "$desktopDir\WinUtil.lnk" $shell = New-Object -ComObject WScript.Shell $shortcut = $shell.CreateShortcut($shortcutPath) if (Test-Path -Path "$env:TEMP\cttlogo.png") { $pngPath = "$env:TEMP\cttlogo.png" $icoPath = "$env:TEMP\cttlogo.ico" ConvertTo-Icon -bitmapPath $pngPath -iconPath $icoPath Write-Host "ICO file created at: $icoPath" Copy-Item "$env:TEMP\cttlogo.png" "$($scratchDir)\Windows\cttlogo.png" -force Copy-Item "$env:TEMP\cttlogo.ico" "$($scratchDir)\Windows\cttlogo.ico" -force $shortcut.IconLocation = "c:\Windows\cttlogo.ico" } $shortcut.TargetPath = "powershell.exe" $shortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -Command `"$command`"" $shortcut.Save() Write-Host "Shortcut to winutil created at: $shortcutPath" # *************************** Automation black *************************** Write-Host "Copy checkinstall.cmd into the ISO" New-CheckInstall Copy-Item "$env:temp\checkinstall.cmd" "$($scratchDir)\Windows\checkinstall.cmd" -force Write-Host "Done copy checkinstall.cmd" Write-Host "Creating a directory that allows to bypass Wifi setup" New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\System32\OOBE\BYPASSNRO" Write-Host "Loading registry" reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS" reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default" reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat" reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM" Write-Host "Disabling Teams" reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v "ConfigureChatAutoInstall" /t REG_DWORD /d 0 /f >$null 2>&1 reg add "HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat" /v ChatIcon /t REG_DWORD /d 2 /f >$null 2>&1 reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarMn" /t REG_DWORD /d 0 /f >$null 2>&1 reg query "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v "ConfigureChatAutoInstall" >$null 2>&1 # Write-Host Error code $LASTEXITCODE Write-Host "Done disabling Teams" Write-Host "Bypassing system requirements (system image)" reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassCPUCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassRAMCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassSecureBootCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassStorageCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassTPMCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f if (!$keepEdge) { Write-Host "Removing Edge icon from taskbar" reg delete "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband" /v "Favorites" /f >$null 2>&1 reg delete "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband" /v "FavoritesChanges" /f >$null 2>&1 reg delete "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband" /v "Pinned" /f >$null 2>&1 reg delete "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband" /v "LayoutCycle" /f >$null 2>&1 Write-Host "Edge icon removed from taskbar" } reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "SearchboxTaskbarMode" /t REG_DWORD /d 0 /f Write-Host "Setting all services to start manually" reg add "HKLM\zSOFTWARE\CurrentControlSet\Services" /v Start /t REG_DWORD /d 3 /f # Write-Host $LASTEXITCODE Write-Host "Enabling Local Accounts on OOBE" reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v "BypassNRO" /t REG_DWORD /d "1" /f Write-Host "Disabling Sponsored Apps" reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OemPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f reg add "HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f reg add "HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\Start" /v "ConfigureStartPins" /t REG_SZ /d '{\"pinnedList\": [{}]}' /f Write-Host "Done removing Sponsored Apps" Write-Host "Disabling Reserved Storage" reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager" /v "ShippedWithReserves" /t REG_DWORD /d 0 /f Write-Host "Changing theme to dark. This only works on Activated Windows" reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "AppsUseLightTheme" /t REG_DWORD /d 0 /f reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "SystemUsesLightTheme" /t REG_DWORD /d 0 /f } catch { Write-Error "An unexpected error occurred: $_" } finally { Write-Host "Unmounting Registry..." reg unload HKLM\zCOMPONENTS reg unload HKLM\zDEFAULT reg unload HKLM\zNTUSER reg unload HKLM\zSOFTWARE reg unload HKLM\zSYSTEM Write-Host "Cleaning up image..." dism /English /image:$scratchDir /Cleanup-Image /StartComponentCleanup /ResetBase Write-Host "Cleanup complete." Write-Host "Unmounting image..." dism /unmount-image /mountdir:$scratchDir /commit } try { Write-Host "Exporting image into $mountDir\sources\install2.wim" dism /Export-Image /SourceImageFile:"$mountDir\sources\install.wim" /SourceIndex:$index /DestinationImageFile:"$mountDir\sources\install2.wim" /compress:max Write-Host "Remove old '$mountDir\sources\install.wim' and rename $mountDir\sources\install2.wim" Remove-Item "$mountDir\sources\install.wim" Rename-Item "$mountDir\sources\install2.wim" "$mountDir\sources\install.wim" if (-not (Test-Path -Path "$mountDir\sources\install.wim")) { Write-Error "Something went wrong and '$mountDir\sources\install.wim' doesn't exist. Please report this bug to the devs" return } Write-Host "Windows image completed. Continuing with boot.wim." # Next step boot image Write-Host "Mounting boot image $mountDir\sources\boot.wim into $scratchDir" dism /mount-image /imagefile:"$mountDir\sources\boot.wim" /index:2 /mountdir:"$scratchDir" if ($injectDrivers) { $driverPath = $sync.MicrowinDriverLocation.Text if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { Write-Host "Path to drivers is invalid continuing without driver injection" } } Write-Host "Loading registry..." reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS" >$null reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default" >$null reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat" >$null reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" >$null reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM" >$null Write-Host "Bypassing system requirements on the setup image" reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassCPUCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassRAMCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassSecureBootCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassStorageCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassTPMCheck" /t REG_DWORD /d 1 /f reg add "HKLM\zSYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f # Fix Computer Restarted Unexpectedly Error on New Bare Metal Install reg add "HKLM\zSYSTEM\Setup\Status\ChildCompletion" /v "setup.exe" /t REG_DWORD /d 3 /f } catch { Write-Error "An unexpected error occurred: $_" } finally { Write-Host "Unmounting Registry..." reg unload HKLM\zCOMPONENTS reg unload HKLM\zDEFAULT reg unload HKLM\zNTUSER reg unload HKLM\zSOFTWARE reg unload HKLM\zSYSTEM Write-Host "Unmounting image..." dism /unmount-image /mountdir:$scratchDir /commit Write-Host "Creating ISO image" # if we downloaded oscdimg from github it will be in the temp directory so use it # if it is not in temp it is part of ADK and is in global PATH so just set it to oscdimg.exe $oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe' $oscdImgFound = Test-Path $oscdimgPath -PathType Leaf if (!$oscdImgFound) { $oscdimgPath = "oscdimg.exe" } Write-Host "[INFO] Using oscdimg.exe from: $oscdimgPath" #& oscdimg.exe -m -o -u2 -udfver102 -bootdata:2#p0,e,b$mountDir\boot\etfsboot.com#pEF,e,b$mountDir\efi\microsoft\boot\efisys.bin $mountDir $env:temp\microwin.iso #Start-Process -FilePath $oscdimgPath -ArgumentList "-m -o -u2 -udfver102 -bootdata:2#p0,e,b$mountDir\boot\etfsboot.com#pEF,e,b$mountDir\efi\microsoft\boot\efisys.bin $mountDir $env:temp\microwin.iso" -NoNewWindow -Wait #Start-Process -FilePath $oscdimgPath -ArgumentList '-m -o -u2 -udfver102 -bootdata:2#p0,e,b$mountDir\boot\etfsboot.com#pEF,e,b$mountDir\efi\microsoft\boot\efisys.bin $mountDir `"$($SaveDialog.FileName)`"' -NoNewWindow -Wait $oscdimgProc = New-Object System.Diagnostics.Process $oscdimgProc.StartInfo.FileName = $oscdimgPath $oscdimgProc.StartInfo.Arguments = "-m -o -u2 -udfver102 -bootdata:2#p0,e,b$mountDir\boot\etfsboot.com#pEF,e,b$mountDir\efi\microsoft\boot\efisys.bin $mountDir `"$($SaveDialog.FileName)`"" $oscdimgProc.StartInfo.CreateNoWindow = $True $oscdimgProc.StartInfo.WindowStyle = "Hidden" $oscdimgProc.StartInfo.UseShellExecute = $False $oscdimgProc.Start() $oscdimgProc.WaitForExit() if ($copyToUSB) { Write-Host "Copying target ISO to the USB drive" #Copy-ToUSB("$env:temp\microwin.iso") Copy-ToUSB("$($SaveDialog.FileName)") if ($?) { Write-Host "Done Copying target ISO to USB drive!" } else { Write-Host "ISO copy failed." } } Write-Host " _____ " Write-Host "(____ \ " Write-Host " _ \ \ ___ ____ ____ " Write-Host "| | | / _ \| _ \ / _ ) " Write-Host "| |__/ / |_| | | | ( (/ / " Write-Host "|_____/ \___/|_| |_|\____) " # Check if the ISO was successfully created - CTT edit if ($LASTEXITCODE -eq 0) { Write-Host "`n`nPerforming Cleanup..." Remove-Item -Recurse -Force "$($scratchDir)" Remove-Item -Recurse -Force "$($mountDir)" #$msg = "Done. ISO image is located here: $env:temp\microwin.iso" $msg = "Done. ISO image is located here: $($SaveDialog.FileName)" Write-Host $msg [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information) } else { Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed." } $sync.MicrowinOptionsPanel.Visibility = 'Collapsed' #$sync.MicrowinFinalIsoLocation.Text = "$env:temp\microwin.iso" $sync.MicrowinFinalIsoLocation.Text = "$($SaveDialog.FileName)" # Allow the machine to sleep again (optional) [PowerManagement]::SetThreadExecutionState(0) $sync.ProcessRunning = $false } } function Invoke-WPFPanelAutologin { <# .SYNOPSIS Enables autologin using Sysinternals Autologon.exe #> curl.exe -ss "https://live.sysinternals.com/Autologon.exe" -o $env:temp\autologin.exe # Official Microsoft recommendation https://learn.microsoft.com/en-us/sysinternals/downloads/autologon cmd /c $env:temp\autologin.exe /accepteula } function Invoke-WPFPanelDISM { <# .SYNOPSIS Checks for system corruption using Chkdsk, SFC, and DISM .DESCRIPTION 1. Chkdsk - Fixes disk and filesystem corruption 2. SFC Run 1 - Fixes system file corruption, and fixes DISM if it was corrupted 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted 4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image .NOTES Command Arguments: 1. Chkdsk /Scan - Runs an online scan on the system drive, attempts to fix any corruption, and queues other corruption for fixing on reboot 2. SFC /ScanNow - Performs a scan of the system files and fixes any corruption 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted /Online - Fixes the currently running system image /Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files /Restorehealth - Performs a scan of the image and fixes any corruption #> Start-Process PowerShell -ArgumentList "Write-Host '(1/4) Chkdsk' -ForegroundColor Green; Chkdsk /scan; Write-Host '`n(2/4) SFC - 1st scan' -ForegroundColor Green; sfc /scannow; Write-Host '`n(3/4) DISM' -ForegroundColor Green; DISM /Online /Cleanup-Image /Restorehealth; Write-Host '`n(4/4) SFC - 2nd scan' -ForegroundColor Green; sfc /scannow; Read-Host '`nPress Enter to Continue'" -verb runas } function Invoke-WPFPresets { <# .SYNOPSIS Sets the options in the tweaks panel to the given preset .PARAMETER preset The preset to set the options to .PARAMETER imported If the preset is imported from a file, defaults to false .PARAMETER checkbox The checkbox to set the options to, defaults to 'WPFTweaks' #> param( $preset, [bool]$imported = $false ) if($imported -eq $true){ $CheckBoxesToCheck = $preset } Else{ $CheckBoxesToCheck = $sync.configs.preset.$preset } $CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" } Write-Debug "Getting checkboxes to set $($CheckBoxes.Count)" $CheckBoxesToCheck | ForEach-Object { if ($_ -ne $null) { Write-Debug $_ } } foreach ($CheckBox in $CheckBoxes) { $checkboxName = $CheckBox.Key if (-not $CheckBoxesToCheck) { $sync.$checkboxName.IsChecked = $false continue } # Check if the checkbox name exists in the flattened JSON hashtable if ($CheckBoxesToCheck.Contains($checkboxName)) { # If it exists, set IsChecked to true $sync.$checkboxName.IsChecked = $true Write-Debug "$checkboxName is checked" } else { # If it doesn't exist, set IsChecked to false $sync.$checkboxName.IsChecked = $false Write-Debug "$checkboxName is not checked" } } } function Invoke-WPFRunspace { <# .SYNOPSIS Creates and invokes a runspace using the given scriptblock and argumentlist .PARAMETER ScriptBlock The scriptblock to invoke in the runspace .PARAMETER ArgumentList A list of arguments to pass to the runspace .EXAMPLE Invoke-WPFRunspace ` -ScriptBlock $sync.ScriptsInstallPrograms ` -ArgumentList "Installadvancedip,Installbitwarden" ` #> [CmdletBinding()] Param ( $ScriptBlock, $ArgumentList, $DebugPreference ) # Create a PowerShell instance $script:powershell = [powershell]::Create() # Add Scriptblock and Arguments to runspace $script:powershell.AddScript($ScriptBlock) $script:powershell.AddArgument($ArgumentList) $script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block $script:powershell.RunspacePool = $sync.runspace # Execute the RunspacePool $script:handle = $script:powershell.BeginInvoke() # Clean up the RunspacePool threads when they are complete, and invoke the garbage collector to clean up the memory if ($script:handle.IsCompleted) { $script:powershell.EndInvoke($script:handle) $script:powershell.Dispose() $sync.runspace.Dispose() $sync.runspace.Close() [System.GC]::Collect() } } function Invoke-WPFShortcut { <# .SYNOPSIS Creates a shortcut and prompts for a save location .PARAMETER ShortcutToAdd The name of the shortcut to add #> param($ShortcutToAdd) $iconPath = $null Switch ($ShortcutToAdd) { "WinUtil" { $SourceExe = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" $IRM = 'irm https://christitus.com/win | iex' $Powershell = '-ExecutionPolicy Bypass -Command "Start-Process powershell.exe -verb runas -ArgumentList' $ArgumentsToSourceExe = "$powershell '$IRM'" $DestinationName = "WinUtil.lnk" if (Test-Path -Path "$env:TEMP\cttlogo.png") { $iconPath = "$env:SystempRoot\cttlogo.ico" ConvertTo-Icon -bitmapPath "$env:TEMP\cttlogo.png" -iconPath $iconPath } } } $FileBrowser = New-Object System.Windows.Forms.SaveFileDialog $FileBrowser.InitialDirectory = [Environment]::GetFolderPath('Desktop') $FileBrowser.Filter = "Shortcut Files (*.lnk)|*.lnk" $FileBrowser.FileName = $DestinationName $FileBrowser.ShowDialog() | Out-Null $WshShell = New-Object -comObject WScript.Shell $Shortcut = $WshShell.CreateShortcut($FileBrowser.FileName) $Shortcut.TargetPath = $SourceExe $Shortcut.Arguments = $ArgumentsToSourceExe if ($iconPath -ne $null) { $shortcut.IconLocation = $iconPath } $Shortcut.Save() Write-Host "Shortcut for $ShortcutToAdd has been saved to $($FileBrowser.FileName)" } function Invoke-WPFTab { <# .SYNOPSIS Sets the selected tab to the tab that was clicked .PARAMETER ClickedTab The name of the tab that was clicked #> Param ($ClickedTab) $tabNav = Get-WinUtilVariables | Where-Object {$psitem -like "WPFTabNav"} $tabNumber = [int]($ClickedTab -replace "WPFTab","" -replace "BT","") - 1 $filter = Get-WinUtilVariables -Type ToggleButton | Where-Object {$psitem -like "WPFTab?BT"} $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object { if ($ClickedTab -ne $PSItem.name) { $sync[$PSItem.Name].IsChecked = $false # $tabNumber = [int]($PSItem.Name -replace "WPFTab","" -replace "BT","") - 1 # $sync.$tabNav.Items[$tabNumber].IsSelected = $false } else { $sync["$ClickedTab"].IsChecked = $true $tabNumber = [int]($ClickedTab-replace "WPFTab","" -replace "BT","") - 1 $sync.$tabNav.Items[$tabNumber].IsSelected = $true } } } function Invoke-WPFToggle { <# .SYNOPSIS Invokes the scriptblock for the given toggle .PARAMETER Button The name of the toggle to invoke #> Param ([string]$Button) # Use this to get the name of the button #[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info") Switch -Wildcard ($Button){ "WPFToggleDarkMode" {Invoke-WinUtilDarkMode -DarkMoveEnabled $(Get-WinUtilToggleStatus WPFToggleDarkMode)} "WPFToggleBingSearch" {Invoke-WinUtilBingSearch $(Get-WinUtilToggleStatus WPFToggleBingSearch)} "WPFToggleNumLock" {Invoke-WinUtilNumLock $(Get-WinUtilToggleStatus WPFToggleNumLock)} "WPFToggleVerboseLogon" {Invoke-WinUtilVerboseLogon $(Get-WinUtilToggleStatus WPFToggleVerboseLogon)} "WPFToggleShowExt" {Invoke-WinUtilShowExt $(Get-WinUtilToggleStatus WPFToggleShowExt)} "WPFToggleSnapFlyout" {Invoke-WinUtilSnapFlyout $(Get-WinUtilToggleStatus WPFToggleSnapFlyout)} "WPFToggleMouseAcceleration" {Invoke-WinUtilMouseAcceleration $(Get-WinUtilToggleStatus WPFToggleMouseAcceleration)} } } function Invoke-WPFtweaksbutton { <# .SYNOPSIS Invokes the functions associated with each group of checkboxes #> if($sync.ProcessRunning){ $msg = "[Invoke-WPFtweaksbutton] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $Tweaks = (Get-WinUtilCheckBoxes)["WPFTweaks"] Set-WinUtilDNS -DNSProvider $sync["WPFchangedns"].text if ($tweaks.count -eq 0 -and $sync["WPFchangedns"].text -eq "Default"){ $msg = "Please check the tweaks you wish to perform." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Write-Debug "Number of tweaks to process: $($Tweaks.Count)" Invoke-WPFRunspace -ArgumentList $Tweaks -DebugPreference $DebugPreference -ScriptBlock { param($Tweaks, $DebugPreference) Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)" $sync.ProcessRunning = $true $cnt = 0 # Execute other selected tweaks foreach ($tweak in $Tweaks) { Write-Debug "This is a tweak to run $tweak count: $cnt" Invoke-WinUtilTweaks $tweak $cnt += 1 } $sync.ProcessRunning = $false Write-Host "=================================" Write-Host "-- Tweaks are Finished ---" Write-Host "=================================" # $ButtonType = [System.Windows.MessageBoxButton]::OK # $MessageboxTitle = "Tweaks are Finished " # $Messageboxbody = ("Done") # $MessageIcon = [System.Windows.MessageBoxImage]::Information # [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) } } Function Invoke-WPFUltimatePerformance { <# .SYNOPSIS Creates or removes the Ultimate Performance power scheme .PARAMETER State Indicates whether to enable or disable the Ultimate Performance power scheme #> param($State) Try{ if($state -eq "Enabled"){ # Define the name and GUID of the power scheme $powerSchemeName = "Ultimate Performance" $powerSchemeGuid = "e9a42b02-d5df-448d-aa00-03f14749eb61" # Get all power schemes $schemes = powercfg /list | Out-String -Stream # Check if the power scheme already exists $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } if ($null -eq $ultimateScheme) { Write-Host "Power scheme '$powerSchemeName' not found. Adding..." # Add the power scheme powercfg /duplicatescheme $powerSchemeGuid powercfg -attributes SUB_SLEEP 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0 -ATTRIB_HIDE powercfg -setactive $powerSchemeGuid powercfg -change -monitor-timeout-ac 0 Write-Host "Power scheme added successfully." } else { Write-Host "Power scheme '$powerSchemeName' already exists." } } elseif($state -eq "Disabled"){ # Define the name of the power scheme $powerSchemeName = "Ultimate Performance" # Get all power schemes $schemes = powercfg /list | Out-String -Stream # Find the scheme to be removed $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } # If the scheme exists, remove it if ($null -ne $ultimateScheme) { # Extract the GUID of the power scheme $guid = ($ultimateScheme -split '\s+')[3] if($null -ne $guid){ Write-Host "Found power scheme '$powerSchemeName' with GUID $guid. Removing..." # Remove the power scheme powercfg /delete $guid Write-Host "Power scheme removed successfully." } else { Write-Host "Could not find GUID for power scheme '$powerSchemeName'." } } else { Write-Host "Power scheme '$powerSchemeName' not found." } } } Catch{ Write-Warning $psitem.Exception.Message } } function Invoke-WPFundoall { <# .SYNOPSIS Undoes every selected tweak #> if($sync.ProcessRunning){ $msg = "[Invoke-WPFundoall] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $Tweaks = (Get-WinUtilCheckBoxes)["WPFTweaks"] if ($tweaks.count -eq 0){ $msg = "Please check the tweaks you wish to undo." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Invoke-WPFRunspace -ArgumentList $Tweaks -DebugPreference $DebugPreference -ScriptBlock { param($Tweaks, $DebugPreference) $sync.ProcessRunning = $true Foreach ($tweak in $tweaks){ Invoke-WinUtilTweaks $tweak -undo $true } $sync.ProcessRunning = $false Write-Host "==================================" Write-Host "--- Undo Tweaks are Finished ---" Write-Host "==================================" $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Tweaks are Finished " $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) } <# Write-Host "Creating Restore Point in case something bad happens" Enable-ComputerRestore -Drive "$env:SystemDrive" Checkpoint-Computer -Description "RestorePoint1" -RestorePointType "MODIFY_SETTINGS" Write-Host "Enabling Telemetry..." Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 1 Write-Host "Enabling Wi-Fi Sense" Set-ItemProperty -Path "HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting" -Name "Value" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots" -Name "Value" -Type DWord -Value 1 Write-Host "Enabling Application suggestions..." Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "ContentDeliveryAllowed" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "OemPreInstalledAppsEnabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "PreInstalledAppsEnabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "PreInstalledAppsEverEnabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SilentInstalledAppsEnabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338387Enabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338388Enabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338389Enabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-353698Enabled" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SystemPaneSuggestionsEnabled" -Type DWord -Value 1 If (Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent") { Remove-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsConsumerFeatures" -Type DWord -Value 0 Write-Host "Enabling Activity History..." Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "EnableActivityFeed" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "PublishUserActivities" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "UploadUserActivities" -Type DWord -Value 1 Write-Host "Enable Location Tracking..." If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\location") { Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\location" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\location" -Name "Value" -Type String -Value "Allow" Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}" -Name "SensorPermissionState" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\lfsvc\Service\Configuration" -Name "Status" -Type DWord -Value 1 Write-Host "Enabling automatic Maps updates..." Set-ItemProperty -Path "HKLM:\SYSTEM\Maps" -Name "AutoUpdateEnabled" -Type DWord -Value 1 Write-Host "Enabling Feedback..." If (Test-Path "HKCU:\SOFTWARE\Microsoft\Siuf\Rules") { Remove-Item -Path "HKCU:\SOFTWARE\Microsoft\Siuf\Rules" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Siuf\Rules" -Name "NumberOfSIUFInPeriod" -Type DWord -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "DoNotShowFeedbackNotifications" -Type DWord -Value 0 Write-Host "Enabling Tailored Experiences..." If (Test-Path "HKCU:\SOFTWARE\Policies\Microsoft\Windows\CloudContent") { Remove-Item -Path "HKCU:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKCU:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableTailoredExperiencesWithDiagnosticData" -Type DWord -Value 0 Write-Host "Disabling Advertising ID..." If (Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo") { Remove-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo" -Name "DisabledByGroupPolicy" -Type DWord -Value 0 Write-Host "Allow Error reporting..." Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting" -Name "Disabled" -Type DWord -Value 0 Write-Host "Allowing Diagnostics Tracking Service..." Stop-Service "DiagTrack" -WarningAction SilentlyContinue Set-Service "DiagTrack" -StartupType Manual Write-Host "Allowing WAP Push Service..." Stop-Service "dmwappushservice" -WarningAction SilentlyContinue Set-Service "dmwappushservice" -StartupType Manual Write-Host "Allowing Home Groups services..." Stop-Service "HomeGroupListener" -WarningAction SilentlyContinue Set-Service "HomeGroupListener" -StartupType Manual Stop-Service "HomeGroupProvider" -WarningAction SilentlyContinue Set-Service "HomeGroupProvider" -StartupType Manual Write-Host "Enabling Storage Sense..." New-Item -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy" | Out-Null Write-Host "Allowing Superfetch service..." Stop-Service "SysMain" -WarningAction SilentlyContinue Set-Service "SysMain" -StartupType Manual Write-Host "Setting BIOS time to Local Time instead of UTC..." Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Type DWord -Value 0 Write-Host "Enabling Hibernation..." Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Session Manager\Power" -Name "HibernteEnabled" -Type Dword -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FlyoutMenuSettings" -Name "ShowHibernateOption" -Type Dword -Value 1 Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Personalization" -Name "NoLockScreen" -ErrorAction SilentlyContinue Write-Host "Hiding file operations details..." If (Test-Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\OperationStatusManager") { Remove-Item -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\OperationStatusManager" -Recurse -ErrorAction SilentlyContinue } Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\OperationStatusManager" -Name "EnthusiastMode" -Type DWord -Value 0 Write-Host "Showing Task View button..." Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ShowTaskViewButton" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People" -Name "PeopleBand" -Type DWord -Value 1 Write-Host "Changing default Explorer view to Quick Access..." Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "LaunchTo" -Type DWord -Value 0 Write-Host "Unrestricting AutoLogger directory" $autoLoggerDir = "$env:PROGRAMDATA\Microsoft\Diagnosis\ETLLogs\AutoLogger" icacls $autoLoggerDir /grant:r SYSTEM:`(OI`)`(CI`)F | Out-Null Write-Host "Enabling and starting Diagnostics Tracking Service" Set-Service "DiagTrack" -StartupType Automatic Start-Service "DiagTrack" Write-Host "Hiding known file extensions" Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideFileExt" -Type DWord -Value 1 Write-Host "Reset Local Group Policies to Stock Defaults" # cmd /c secedit /configure /cfg %windir%\inf\defltbase.inf /db defltbase.sdb /verbose cmd /c RD /S /Q "%WinDir%\System32\GroupPolicyUsers" cmd /c RD /S /Q "%WinDir%\System32\GroupPolicy" cmd /c gpupdate /force # Considered using Invoke-GPUpdate but requires module most people won't have installed Write-Host "Adjusting visual effects for appearance..." Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "DragFullWindows" -Type String -Value 1 Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "MenuShowDelay" -Type String -Value 400 Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "UserPreferencesMask" -Type Binary -Value ([byte[]](158, 30, 7, 128, 18, 0, 0, 0)) Set-ItemProperty -Path "HKCU:\Control Panel\Desktop\WindowMetrics" -Name "MinAnimate" -Type String -Value 1 Set-ItemProperty -Path "HKCU:\Control Panel\Keyboard" -Name "KeyboardDelay" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ListviewAlphaSelect" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ListviewShadow" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarAnimations" -Type DWord -Value 1 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects" -Name "VisualFXSetting" -Type DWord -Value 3 Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\DWM" -Name "EnableAeroPeek" -Type DWord -Value 1 Remove-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "HungAppTimeout" -ErrorAction SilentlyContinue Write-Host "Restoring Clipboard History..." Remove-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Clipboard" -Name "EnableClipboardHistory" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "AllowClipboardHistory" -ErrorAction SilentlyContinue Write-Host "Enabling Notifications and Action Center" Remove-Item -Path HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer -Force Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\PushNotifications" -Name "ToastEnabled" Write-Host "Restoring Default Right Click Menu Layout" Remove-Item -Path "HKCU:\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" -Recurse -Confirm:$false -Force Write-Host "Reset News and Interests" Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Feeds" -Name "EnableFeeds" -Type DWord -Value 1 # Remove "News and Interest" from taskbar Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Feeds" -Name "ShellFeedsTaskbarViewMode" -Type DWord -Value 0 Write-Host "Done - Reverted to Stock Settings" Write-Host "Essential Undo Completed" $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Undo All" $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "=================================" Write-Host "--- Undo All is Finished ---" Write-Host "=================================" #> } function Invoke-WPFUnInstall { <# .SYNOPSIS Uninstalls the selected programs #> if($sync.ProcessRunning){ $msg = "[Invoke-WPFUnInstall] Install process is currently running" [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] if ($wingetinstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } $ButtonType = [System.Windows.MessageBoxButton]::YesNo $MessageboxTitle = "Are you sure?" $Messageboxbody = ("This will uninstall the following applications: `n $WingetInstall") $MessageIcon = [System.Windows.MessageBoxImage]::Information $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) if($confirm -eq "No"){return} Invoke-WPFRunspace -ArgumentList $WingetInstall -DebugPreference $DebugPreference -ScriptBlock { param($WingetInstall, $DebugPreference) try{ $sync.ProcessRunning = $true # Install all selected programs in new window Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall -Manage "Uninstalling" $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Uninstalls are Finished " $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "===========================================" Write-Host "-- Uninstalls have finished ---" Write-Host "===========================================" } Catch { Write-Host "===========================================" Write-Host "-- Winget failed to install ---" Write-Host "===========================================" } $sync.ProcessRunning = $False } } function Invoke-WPFUpdatesdefault { <# .SYNOPSIS Resets Windows Update settings to default #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Type DWord -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Type DWord -Value 3 If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) { New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Name "DODownloadMode" -Type DWord -Value 1 $services = @( "BITS" "wuauserv" ) foreach ($service in $services) { # -ErrorAction SilentlyContinue is so it doesn't write an error to stdout if a service doesn't exist Write-Host "Setting $service StartupType to Automatic" Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Automatic } Write-Host "Enabling driver offering through Windows Update..." Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Name "PreventDeviceMetadataFromNetwork" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontPromptForWindowsUpdate" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontSearchWindowsUpdate" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DriverUpdateWizardWuSearchEnabled" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ExcludeWUDriversInQualityUpdate" -ErrorAction SilentlyContinue Write-Host "Enabling Windows Update automatic restart..." Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoRebootWithLoggedOnUsers" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUPowerManagement" -ErrorAction SilentlyContinue Write-Host "Enabled driver offering through Windows Update" Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -ErrorAction SilentlyContinue Write-Host "===================================================" Write-Host "--- Windows Update Settings Reset to Default ---" Write-Host "===================================================" } function Invoke-WPFUpdatesdisable { <# .SYNOPSIS Disables Windows Update .NOTES Disabling Windows Update is not recommended. This is only for advanced users who know what they are doing. #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Type DWord -Value 1 If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) { New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Name "DODownloadMode" -Type DWord -Value 0 $services = @( "BITS" "wuauserv" ) foreach ($service in $services) { # -ErrorAction SilentlyContinue is so it doesn't write an error to stdout if a service doesn't exist Write-Host "Setting $service StartupType to Disabled" Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Disabled } Write-Host "=================================" Write-Host "--- Updates ARE DISABLED ---" Write-Host "=================================" } function Invoke-WPFUpdatessecurity { <# .SYNOPSIS Sets Windows Update to recommended settings .DESCRIPTION 1. Disables driver offering through Windows Update 2. Disables Windows Update automatic restart 3. Sets Windows Update to Semi-Annual Channel (Targeted) 4. Defers feature updates for 365 days 5. Defers quality updates for 4 days #> Write-Host "Disabling driver offering through Windows Update..." If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Name "PreventDeviceMetadataFromNetwork" -Type DWord -Value 1 If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontPromptForWindowsUpdate" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontSearchWindowsUpdate" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DriverUpdateWizardWuSearchEnabled" -Type DWord -Value 0 If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ExcludeWUDriversInQualityUpdate" -Type DWord -Value 1 Write-Host "Disabling Windows Update automatic restart..." If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoRebootWithLoggedOnUsers" -Type DWord -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUPowerManagement" -Type DWord -Value 0 Write-Host "Disabled driver offering through Windows Update" If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) { New-Item -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Force | Out-Null } Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -Type DWord -Value 20 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -Type DWord -Value 365 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -Type DWord -Value 4 $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Set Security Updates" $Messageboxbody = ("Recommended Update settings loaded") $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "=================================" Write-Host "-- Updates Set to Recommended ---" Write-Host "=================================" } $inputXML = ' Install Tweaks Config Updates MicroWin Choose Windows SKU Choose Windows features you want to remove from the ISO