diff --git a/functions/private/ConvertTo-Icon.ps1 b/functions/private/ConvertTo-Icon.ps1 index 44f4d6be..d0e7ac08 100644 --- a/functions/private/ConvertTo-Icon.ps1 +++ b/functions/private/ConvertTo-Icon.ps1 @@ -57,9 +57,9 @@ function ConvertTo-Icon { #> param( - [Parameter(Mandatory=$true, position=0)] + [Parameter(Mandatory, position=0)] [string]$bitmapPath, - [Parameter(Mandatory=$true, position=1)] + [Parameter(Mandatory, position=1)] [string]$iconPath, [Parameter(position=2)] [bool]$overrideIconFile = $true diff --git a/functions/private/Get-Oscdimg.ps1 b/functions/private/Get-Oscdimg.ps1 index 38ea3b2c..4680a39b 100644 --- a/functions/private/Get-Oscdimg.ps1 +++ b/functions/private/Get-Oscdimg.ps1 @@ -1,15 +1,17 @@ function Get-Oscdimg { <# - .DESCRIPTION This function will download oscdimg file from github Release folders and put it into env:temp folder .EXAMPLE Get-Oscdimg #> - param( [Parameter(Mandatory=$true)] + + param( + [Parameter(Mandatory, position=0)] [string]$oscdimgPath ) + $oscdimgPath = "$env:TEMP\oscdimg.exe" $downloadUrl = "https://github.com/ChrisTitusTech/winutil/raw/main/releases/oscdimg.exe" Invoke-RestMethod -Uri $downloadUrl -OutFile $oscdimgPath diff --git a/functions/private/Get-TabXaml.ps1 b/functions/private/Get-TabXaml.ps1 index e78b7492..889c25c7 100644 --- a/functions/private/Get-TabXaml.ps1 +++ b/functions/private/Get-TabXaml.ps1 @@ -1,19 +1,23 @@ function Get-TabXaml { <# - .SYNOPSIS - Generates XAML for a tab in the WinUtil GUI - This function is used to generate the XAML for the applications tab in the WinUtil GUI - It takes the tabname and the number of columns to display the applications in as input and returns the XAML for the tab as output - .PARAMETER tabname - The name of the tab to generate XAML for - Note: the 'tabname' parameter must equal one of the json files found in $sync.configs variable - Otherwise, it'll throw an exception - .PARAMETER columncount - The number of columns to display the applications in, default is 0 - .OUTPUTS - The XAML for the tab - .EXAMPLE - Get-TabXaml "applications" 3 + .SYNOPSIS + Generates XAML for a tab in the WinUtil GUI + This function is used to generate the XAML for the applications tab in the WinUtil GUI + It takes the tabname and the number of columns to display the applications in as input and returns the XAML for the tab as output + + .PARAMETER tabname + The name of the tab to generate XAML for + Note: the 'tabname' parameter must equal one of the json files found in $sync.configs variable + Otherwise, it'll throw an exception + + .PARAMETER columncount + The number of columns to display the applications in, default is 0 + + .OUTPUTS + The XAML for the tab + + .EXAMPLE + Get-TabXaml "applications" 3 #> diff --git a/functions/private/Get-WPFObjectName.ps1 b/functions/private/Get-WPFObjectName.ps1 index 54062ffb..5875bfbf 100644 --- a/functions/private/Get-WPFObjectName.ps1 +++ b/functions/private/Get-WPFObjectName.ps1 @@ -1,27 +1,31 @@ function Get-WPFObjectName { - <# - .SYNOPSIS - This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation. - To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name. - .PARAMETER type - The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...) - .PARAMETER name - The name or description to be used for the object. (invalid characters are removed) - .OUTPUTS - A string that can be used as a object/variable name in powershell. - For example: WPFLabelMicrosoftTools + <# + .SYNOPSIS + This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation. + To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name. - .EXAMPLE - Get-WPFObjectName -type Label -name "Microsoft Tools" + .PARAMETER type + The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...) + + .PARAMETER name + The name or description to be used for the object. (invalid characters are removed) + + .OUTPUTS + A string that can be used as a object/variable name in powershell. + For example: WPFLabelMicrosoftTools + + .EXAMPLE + Get-WPFObjectName -type Label -name "Microsoft Tools" #> - param( [Parameter(Mandatory=$true)] - $type, - $name -) + param( + [Parameter(Mandatory, position=0)] + [string]$type, -$Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', '' + [Parameter(position=1)] + [string]$name + ) -return $Output - -} \ No newline at end of file + $Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', '' + return $Output +} diff --git a/functions/private/Invoke-MicroWin-Helper.ps1 b/functions/private/Invoke-MicroWin-Helper.ps1 index ace66cf7..76efe85d 100644 --- a/functions/private/Invoke-MicroWin-Helper.ps1 +++ b/functions/private/Invoke-MicroWin-Helper.ps1 @@ -1,48 +1,45 @@ function Test-CompatibleImage() { -<# + <# + .SYNOPSIS + Checks the version of a Windows image and determines whether or not it is compatible with a specific feature depending on a desired version - .SYNOPSIS - Checks the version of a Windows image and determines whether or not it is compatible with a specific feature depending on a desired version + .PARAMETER Name + imgVersion - The version of the Windows image + desiredVersion - The version to compare the image version with + #> - .PARAMETER Name - imgVersion - The version of the Windows image - desiredVersion - The version to compare the image version with + param + ( + [Parameter(Mandatory, position=0)] + [string]$imgVersion, -#> + [Parameter(Mandatory, position=1)] + [Version]$desiredVersion + ) - param - ( - [Parameter(Mandatory = $true, Position=0)] [string] $imgVersion, - [Parameter(Mandatory = $true, Position=1)] [Version] $desiredVersion - ) - - try { - $version = [Version]$imgVersion - return $version -ge $desiredVersion - } catch { - return $False - } + try { + $version = [Version]$imgVersion + return $version -ge $desiredVersion + } catch { + return $False + } } function Remove-Features([switch] $dumpFeatures = $false, [switch] $keepDefender = $false) { -<# + <# + .SYNOPSIS + Removes certain features from ISO image - .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? - .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 - -#> - try - { + .EXAMPLE + Remove-Features -keepDefender:$false + #> + try { $featlist = (Get-WindowsOptionalFeature -Path $scratchDir).FeatureName - if ($dumpFeatures) - { + if ($dumpFeatures) { $featlist > allfeaturesdump.txt } @@ -57,26 +54,22 @@ function Remove-Features([switch] $dumpFeatures = $false, [switch] $keepDefender if ($keepDefender) { $featlist = $featlist | Where-Object { $_ -NotLike "*Defender*" }} - foreach($feature in $featlist) - { + foreach($feature in $featlist) { $status = "Removing feature $feature" Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100) Write-Debug "Removing feature $feature" Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $feature -Remove -ErrorAction SilentlyContinue -NoRestart } Write-Progress -Activity "Removing features" -Status "Ready" -Completed - Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in \Sources." + Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in \Sources." } - catch - { + catch { Write-Host "Unable to get information about the features. MicroWin processing will continue, but features will not be processed" } } -function Remove-Packages -{ - try - { +function Remove-Packages { + try { $pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName $pkglist = $pkglist | Where-Object { @@ -117,8 +110,7 @@ function Remove-Packages $_ -NotLike "*UI.XaML*" } - foreach ($pkg in $pkglist) - { + foreach ($pkg in $pkglist) { try { $status = "Removing $pkg" Write-Progress -Activity "Removing Apps" -Status $status -PercentComplete ($counter++/$pkglist.Count*100) @@ -130,28 +122,24 @@ function Remove-Packages continue } } - Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed + Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed } - catch - { - Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed" + catch { + Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed" } } -function Remove-ProvisionedPackages([switch] $keepSecurity = $false) -{ -<# +function Remove-ProvisionedPackages([switch] $keepSecurity = $false) { + <# + .SYNOPSIS + Removes AppX packages from a Windows image during MicroWin processing - .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 - .PARAMETER Name - keepSecurity - Boolean that determines whether to keep "Microsoft.SecHealthUI" (Windows Security) in the Windows image - - .EXAMPLE - Remove-ProvisionedPackages -keepSecurity:$false - -#> + .EXAMPLE + Remove-ProvisionedPackages -keepSecurity:$false + #> $appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object { $_.PackageName -NotLike "*AppInstaller*" -AND $_.PackageName -NotLike "*Store*" -and @@ -165,14 +153,12 @@ function Remove-ProvisionedPackages([switch] $keepSecurity = $false) $_.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) + 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) try { Remove-AppxProvisionedPackage -Path $scratchDir -PackageName $appx.PackageName -ErrorAction SilentlyContinue } @@ -180,17 +166,15 @@ function Remove-ProvisionedPackages([switch] $keepSecurity = $false) Write-Host "Application $($appx.PackageName) could not be removed" continue } - } - Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed - } - else - { - Write-Host "Could not get Provisioned App information. Skipping process..." - } + } + 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) -{ +function Copy-ToUSB([string] $fileToCopy) { foreach ($volume in Get-Volume) { if ($volume -and $volume.FileSystemLabel -ieq "ventoy") { $destinationPath = "$($volume.DriveLetter):\" @@ -214,8 +198,7 @@ function Copy-ToUSB([string] $fileToCopy) Write-Host "Ventoy USB Key is not inserted" } -function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false) -{ +function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false) { if(([string]::IsNullOrEmpty($pathToDelete))) { return } if (-not (Test-Path -Path "$($pathToDelete)")) { return } @@ -240,25 +223,21 @@ function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [sw $itemsToDelete = [System.Collections.ArrayList]::new() - if ($mask -eq "") - { + if ($mask -eq "") { Write-Debug "Adding $($pathToDelete) to array." [void]$itemsToDelete.Add($pathToDelete) } - else - { + 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) - { + foreach($itemToDelete in $itemsToDelete) { $status = "Deleting $($itemToDelete)" Write-Progress -Activity "Removing Items" -Status $status -PercentComplete ($counter++/$itemsToDelete.Count*100) - if (Test-Path -Path "$($itemToDelete)" -PathType Container) - { + if (Test-Path -Path "$($itemToDelete)" -PathType Container) { $status = "Deleting directory: $($itemToDelete)" takeown /r /d $yesNo[0] /a /f "$($itemToDelete)" @@ -267,8 +246,7 @@ function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [sw 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) - { + elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf) { $status = "Deleting file: $($itemToDelete)" takeown /a /f "$($itemToDelete)" @@ -285,42 +263,42 @@ 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 + # 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 + # + # 1 + # net user administrator /active:yes # # this section doesn't work in win10/???? -# -# -# 0 -# -# -# false -# +# +# +# 0 +# +# +# false +# # $unattend = @' @@ -328,7 +306,7 @@ function New-Unattend { - <#REPLACEME#> + <#REPLACEME#> @@ -343,9 +321,9 @@ function New-Unattend { - true - false - false + true + false + false true true true @@ -369,26 +347,24 @@ function New-Unattend { '@ - $specPass = @' + $specPass = @' - - 0 - - - false - - + + 0 + + + false + + '@ - if ((Test-CompatibleImage $imgVersion $([System.Version]::new(10,0,22000,1))) -eq $false) - { - # Replace the placeholder text with an empty string to make it valid for Windows 10 Setup - $unattend = $unattend.Replace("<#REPLACEME#>", "").Trim() - } - else - { - # Replace the placeholder text with the Specialize pass - $unattend = $unattend.Replace("<#REPLACEME#>", $specPass).Trim() - } + if ((Test-CompatibleImage $imgVersion $([System.Version]::new(10,0,22000,1))) -eq $false) { + # Replace the placeholder text with an empty string to make it valid for Windows 10 Setup + $unattend = $unattend.Replace("<#REPLACEME#>", "").Trim() + } + else { + # Replace the placeholder text with the Specialize pass + $unattend = $unattend.Replace("<#REPLACEME#>", $specPass).Trim() + } $unattend | Out-File -FilePath "$env:temp\unattend.xml" -Force -Encoding utf8 } @@ -472,8 +448,7 @@ function New-FirstRun { $firstRun = @' # Set the global error action preference to continue $ErrorActionPreference = "Continue" - function Remove-RegistryValue - { + function Remove-RegistryValue { param ( [Parameter(Mandatory = $true)] [string]$RegistryPath, @@ -483,30 +458,25 @@ function New-FirstRun { ) # Check if the registry path exists - if (Test-Path -Path $RegistryPath) - { + if (Test-Path -Path $RegistryPath) { $registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue # Check if the registry value exists - if ($registryValue) - { + if ($registryValue) { # Remove the registry value Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force Write-Host "Registry value '$ValueName' removed from '$RegistryPath'." } - else - { + else { Write-Host "Registry value '$ValueName' not found in '$RegistryPath'." } } - else - { + else { Write-Host "Registry path '$RegistryPath' not found." } } - function Stop-UnnecessaryServices - { + function Stop-UnnecessaryServices { $servicesToExclude = @( "AudioSrv", "AudioEndpointBuilder", @@ -573,9 +543,8 @@ function New-FirstRun { ) $runningServices = Get-Service | Where-Object { $servicesToExclude -notcontains $_.Name } - foreach($service in $runningServices) - { - Stop-Service -Name $service.Name -PassThru + 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 } @@ -613,10 +582,8 @@ function New-FirstRun { # 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) - { + 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." @@ -639,8 +606,7 @@ function New-FirstRun { # Create a shortcut object $shortcut = $shell.CreateShortcut($shortcutPath) - if (Test-Path -Path "c:\Windows\cttlogo.png") - { + if (Test-Path -Path "c:\Windows\cttlogo.png") { $shortcut.IconLocation = "c:\Windows\cttlogo.png" } @@ -650,11 +616,11 @@ function New-FirstRun { # Save the shortcut $shortcut.Save() - # Make the shortcut have 'Run as administrator' property on - $bytes = [System.IO.File]::ReadAllBytes($shortcutPath) - # Set byte value at position 0x15 in hex, or 21 in decimal, from the value 0x00 to 0x20 in hex - $bytes[0x15] = $bytes[0x15] -bor 0x20 - [System.IO.File]::WriteAllBytes($shortcutPath, $bytes) + # Make the shortcut have 'Run as administrator' property on + $bytes = [System.IO.File]::ReadAllBytes($shortcutPath) + # Set byte value at position 0x15 in hex, or 21 in decimal, from the value 0x00 to 0x20 in hex + $bytes[0x15] = $bytes[0x15] -bor 0x20 + [System.IO.File]::WriteAllBytes($shortcutPath, $bytes) Write-Host "Shortcut created at: $shortcutPath" # diff --git a/functions/private/Set-WinUtilUiTheme.ps1 b/functions/private/Set-WinUtilUiTheme.ps1 index 46d55afa..1338526f 100644 --- a/functions/private/Set-WinUtilUiTheme.ps1 +++ b/functions/private/Set-WinUtilUiTheme.ps1 @@ -1,24 +1,23 @@ function Set-WinUtilUITheme { <# + .SYNOPSIS + Sets the theme of the XAML file - .SYNOPSIS - Sets the theme of the XAML file + .PARAMETER inputXML + A string representing the XAML object to modify - .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 + .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)] + [Parameter(Mandatory, position=0)] [string] $inputXML, - [Parameter(Mandatory=$false, Position=1)] + [Parameter(position=1)] [string] $themeName = 'matrix' )