mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2025-01-02 02:54:55 -06:00
Add DISM command fallback
This fallback is triggered if an exception occurs while getting information with the cmdlets (I couldn't test this on my host as everything magically works now - sometimes it threw the Class not registered error)
This commit is contained in:
parent
bee4d04a17
commit
9dd508d069
@ -163,12 +163,12 @@ public class PowerManagement {
|
||||
}
|
||||
|
||||
Write-Host "Remove Features from the image"
|
||||
Microwin-RemoveFeatures
|
||||
Microwin-RemoveFeatures -UseCmdlets $true
|
||||
Write-Host "Removing features complete!"
|
||||
Write-Host "Removing OS packages"
|
||||
Microwin-RemovePackages
|
||||
Microwin-RemovePackages -UseCmdlets $true
|
||||
Write-Host "Removing Appx Bloat"
|
||||
Microwin-RemoveProvisionedPackages
|
||||
Microwin-RemoveProvisionedPackages -UseCmdlets $true
|
||||
|
||||
# Detect Windows 11 24H2 and add dependency to FileExp to prevent Explorer look from going back - thanks @WitherOrNot and @thecatontheceiling
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,1))) -eq $true) {
|
||||
|
@ -3,38 +3,80 @@ function Microwin-RemoveFeatures() {
|
||||
.SYNOPSIS
|
||||
Removes certain features from ISO image
|
||||
|
||||
.PARAMETER Name
|
||||
No Params
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- If false, calls to the DISM executable will be made whilst selecting bits and pieces from the output as a string (that was how MicroWin worked before
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemoveFeatures
|
||||
Microwin-RemoveFeatures -UseCmdlets $true
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try {
|
||||
$featlist = (Get-WindowsOptionalFeature -Path $scratchDir)
|
||||
if ($UseCmdlets) {
|
||||
$featlist = (Get-WindowsOptionalFeature -Path "$scratchDir")
|
||||
|
||||
$featlist = $featlist | Where-Object {
|
||||
$_.FeatureName -NotLike "*Defender*" -AND
|
||||
$_.FeatureName -NotLike "*Printing*" -AND
|
||||
$_.FeatureName -NotLike "*TelnetClient*" -AND
|
||||
$_.FeatureName -NotLike "*PowerShell*" -AND
|
||||
$_.FeatureName -NotLike "*NetFx*" -AND
|
||||
$_.FeatureName -NotLike "*Media*" -AND
|
||||
$_.FeatureName -NotLike "*NFS*" -AND
|
||||
$_.FeatureName -NotLike "*SearchEngine*" -AND
|
||||
$_.FeatureName -NotLike "*RemoteDesktop*" -AND
|
||||
$_.State -ne "Disabled"
|
||||
$featlist = $featlist | Where-Object {
|
||||
$_.FeatureName -NotLike "*Defender*" -AND
|
||||
$_.FeatureName -NotLike "*Printing*" -AND
|
||||
$_.FeatureName -NotLike "*TelnetClient*" -AND
|
||||
$_.FeatureName -NotLike "*PowerShell*" -AND
|
||||
$_.FeatureName -NotLike "*NetFx*" -AND
|
||||
$_.FeatureName -NotLike "*Media*" -AND
|
||||
$_.FeatureName -NotLike "*NFS*" -AND
|
||||
$_.FeatureName -NotLike "*SearchEngine*" -AND
|
||||
$_.FeatureName -NotLike "*RemoteDesktop*" -AND
|
||||
$_.State -ne "Disabled"
|
||||
}
|
||||
} else {
|
||||
$featList = dism /english /image="$scratchDir" /get-features | Select-String -Pattern "Feature Name : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$featList = $featList -split "Feature Name : " | Where-Object {$_}
|
||||
# Exclude the same items. Note: for now, this doesn't exclude those features that are disabled.
|
||||
# This will appear in the future
|
||||
$featList = $featList | Where-Object {
|
||||
$_ -NotLike "*Defender*" -AND
|
||||
$_ -NotLike "*Printing*" -AND
|
||||
$_ -NotLike "*TelnetClient*" -AND
|
||||
$_ -NotLike "*PowerShell*" -AND
|
||||
$_ -NotLike "*NetFx*" -AND
|
||||
$_ -NotLike "*Media*" -AND
|
||||
$_ -NotLike "*NFS*" -AND
|
||||
$_ -NotLike "*SearchEngine*" -AND
|
||||
$_ -NotLike "*RemoteDesktop*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Features could not be obtained with DISM. MicroWin processing will continue, but features will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
foreach($feature in $featlist) {
|
||||
$status = "Removing feature $($feature.FeatureName)"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing feature $($feature.FeatureName)"
|
||||
Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $($feature.FeatureName) -Remove -ErrorAction SilentlyContinue -NoRestart
|
||||
if ($UseCmdlets) {
|
||||
foreach ($feature in $featList) {
|
||||
$status = "Removing feature $($feature.FeatureName)"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing feature $($feature.FeatureName)"
|
||||
Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $($feature.FeatureName) -Remove -ErrorAction SilentlyContinue -NoRestart
|
||||
}
|
||||
} else {
|
||||
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"
|
||||
dism /english /image="$scratchDir" /disable-feature /featurename=$feature /remove /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "Feature $feature could not be disabled."
|
||||
}
|
||||
}
|
||||
}
|
||||
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 <installation media>\Sources."
|
||||
} catch {
|
||||
Write-Host "Unable to get information about the features. MicroWin processing will continue, but features will not be processed"
|
||||
Write-Host "Unable to get information about the features. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemoveFeatures -UseCmdlets $false
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,101 @@
|
||||
function Microwin-RemovePackages {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes certain packages from ISO image
|
||||
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- If false, calls to the DISM executable will be made whilst selecting bits and pieces from the output as a string (that was how MicroWin worked before
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemovePackages -UseCmdlets $true
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try {
|
||||
$pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName
|
||||
if ($useCmdlets) {
|
||||
$pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName
|
||||
|
||||
$pkglist = $pkglist | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*DotNet*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*Ethernet*" -AND
|
||||
$_ -NotLike "*Wifi*" -AND
|
||||
$_ -NotLike "*FodMetadata*" -AND
|
||||
$_ -NotLike "*Foundation*" -AND
|
||||
$_ -NotLike "*LanguageFeatures*" -AND
|
||||
$_ -NotLike "*VBSCRIPT*" -AND
|
||||
$_ -NotLike "*License*" -AND
|
||||
$_ -NotLike "*Hello-Face*" -AND
|
||||
$_ -NotLike "*ISE*"
|
||||
$pkglist = $pkglist | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*DotNet*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*Ethernet*" -AND
|
||||
$_ -NotLike "*Wifi*" -AND
|
||||
$_ -NotLike "*FodMetadata*" -AND
|
||||
$_ -NotLike "*Foundation*" -AND
|
||||
$_ -NotLike "*LanguageFeatures*" -AND
|
||||
$_ -NotLike "*VBSCRIPT*" -AND
|
||||
$_ -NotLike "*License*" -AND
|
||||
$_ -NotLike "*Hello-Face*" -AND
|
||||
$_ -NotLike "*ISE*"
|
||||
}
|
||||
} else {
|
||||
$pkgList = dism /english /image="$scratchDir" /get-packages | Select-String -Pattern "Package Identity : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$pkgList = $pkgList -split "Package Identity : " | Where-Object {$_}
|
||||
# Exclude the same items.
|
||||
$pkgList = $pkgList | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*DotNet*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*Ethernet*" -AND
|
||||
$_ -NotLike "*Wifi*" -AND
|
||||
$_ -NotLike "*FodMetadata*" -AND
|
||||
$_ -NotLike "*Foundation*" -AND
|
||||
$_ -NotLike "*LanguageFeatures*" -AND
|
||||
$_ -NotLike "*VBSCRIPT*" -AND
|
||||
$_ -NotLike "*License*" -AND
|
||||
$_ -NotLike "*Hello-Face*" -AND
|
||||
$_ -NotLike "*ISE*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Packages could not be obtained with DISM. MicroWin processing will continue, but packages will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$failedCount = 0
|
||||
if ($UseCmdlets) {
|
||||
$failedCount = 0
|
||||
|
||||
$erroredPackages = [System.Collections.Generic.List[ErroredPackage]]::new()
|
||||
$erroredPackages = [System.Collections.Generic.List[ErroredPackage]]::new()
|
||||
|
||||
foreach ($pkg in $pkglist) {
|
||||
try {
|
||||
$status = "Removing $pkg"
|
||||
Write-Progress -Activity "Removing Packages" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
||||
Remove-WindowsPackage -Path "$scratchDir" -PackageName $pkg -NoRestart -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
# This can happen if the package that is being removed is a permanent one
|
||||
$erroredPackages.Add([ErroredPackage]::new($pkg, $_.Exception.Message))
|
||||
$failedCount += 1
|
||||
continue
|
||||
foreach ($pkg in $pkglist) {
|
||||
try {
|
||||
$status = "Removing $pkg"
|
||||
Write-Progress -Activity "Removing Packages" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
||||
Remove-WindowsPackage -Path "$scratchDir" -PackageName $pkg -NoRestart -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
# This can happen if the package that is being removed is a permanent one
|
||||
$erroredPackages.Add([ErroredPackage]::new($pkg, $_.Exception.Message))
|
||||
$failedCount += 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($package in $pkgList) {
|
||||
$status = "Removing package $package"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing package $package"
|
||||
dism /english /image="$scratchDir" /remove-package /packagename=$package /remove /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "Package $package could not be removed."
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Packages" -Status "Ready" -Completed
|
||||
if ($failedCount -gt 0)
|
||||
if ($UseCmdlets -and $failedCount -gt 0)
|
||||
{
|
||||
Write-Host "$failedCount package(s) could not be removed. Your image will still work fine, however. Below is information on what packages failed to be removed and why."
|
||||
if ($erroredPackages.Count -gt 0)
|
||||
@ -63,7 +120,8 @@ function Microwin-RemovePackages {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed"
|
||||
Write-Host "Unable to get information about the packages. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemovePackages -UseCmdlets $false
|
||||
}
|
||||
}
|
||||
|
@ -3,49 +3,94 @@ function Microwin-RemoveProvisionedPackages() {
|
||||
.SYNOPSIS
|
||||
Removes AppX packages from a Windows image during MicroWin processing
|
||||
|
||||
.PARAMETER Name
|
||||
No Params
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- If false, calls to the DISM executable will be made whilst selecting bits and pieces from the output as a string (that was how MicroWin worked before
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemoveProvisionedPackages
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try
|
||||
{
|
||||
$appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
|
||||
$_.PackageName -NotLike "*AppInstaller*" -AND
|
||||
$_.PackageName -NotLike "*Store*" -and
|
||||
$_.PackageName -NotLike "*Notepad*" -and
|
||||
$_.PackageName -NotLike "*Printing*" -and
|
||||
$_.PackageName -NotLike "*YourPhone*" -and
|
||||
$_.PackageName -NotLike "*Xbox*" -and
|
||||
$_.PackageName -NotLike "*WindowsTerminal*" -and
|
||||
$_.PackageName -NotLike "*Calculator*" -and
|
||||
$_.PackageName -NotLike "*Photos*" -and
|
||||
$_.PackageName -NotLike "*VCLibs*" -and
|
||||
$_.PackageName -NotLike "*Paint*" -and
|
||||
$_.PackageName -NotLike "*Gaming*" -and
|
||||
$_.PackageName -NotLike "*Extension*" -and
|
||||
$_.PackageName -NotLike "*SecHealthUI*" -and
|
||||
$_.PackageName -NotLike "*ScreenSketch*"
|
||||
if ($UseCmdlets) {
|
||||
$appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
|
||||
$_.PackageName -NotLike "*AppInstaller*" -AND
|
||||
$_.PackageName -NotLike "*Store*" -and
|
||||
$_.PackageName -NotLike "*Notepad*" -and
|
||||
$_.PackageName -NotLike "*Printing*" -and
|
||||
$_.PackageName -NotLike "*YourPhone*" -and
|
||||
$_.PackageName -NotLike "*Xbox*" -and
|
||||
$_.PackageName -NotLike "*WindowsTerminal*" -and
|
||||
$_.PackageName -NotLike "*Calculator*" -and
|
||||
$_.PackageName -NotLike "*Photos*" -and
|
||||
$_.PackageName -NotLike "*VCLibs*" -and
|
||||
$_.PackageName -NotLike "*Paint*" -and
|
||||
$_.PackageName -NotLike "*Gaming*" -and
|
||||
$_.PackageName -NotLike "*Extension*" -and
|
||||
$_.PackageName -NotLike "*SecHealthUI*" -and
|
||||
$_.PackageName -NotLike "*ScreenSketch*"
|
||||
}
|
||||
} else {
|
||||
$appxProvisionedPackages = dism /english /image="$scratchDir" /get-provisionedappxpackages | Select-String -Pattern "PackageName : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$appxProvisionedPackages = $appxProvisionedPackages -split "PackageName : " | Where-Object {$_}
|
||||
# Exclude the same items.
|
||||
$appxProvisionedPackages = $appxProvisionedPackages | Where-Object {
|
||||
$_ -NotLike "*AppInstaller*" -AND
|
||||
$_ -NotLike "*Store*" -and
|
||||
$_ -NotLike "*Notepad*" -and
|
||||
$_ -NotLike "*Printing*" -and
|
||||
$_ -NotLike "*YourPhone*" -and
|
||||
$_ -NotLike "*Xbox*" -and
|
||||
$_ -NotLike "*WindowsTerminal*" -and
|
||||
$_ -NotLike "*Calculator*" -and
|
||||
$_ -NotLike "*Photos*" -and
|
||||
$_ -NotLike "*VCLibs*" -and
|
||||
$_ -NotLike "*Paint*" -and
|
||||
$_ -NotLike "*Gaming*" -and
|
||||
$_ -NotLike "*Extension*" -and
|
||||
$_ -NotLike "*SecHealthUI*" -and
|
||||
$_ -NotLike "*ScreenSketch*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "AppX packages could not be obtained with DISM. MicroWin processing will continue, but AppX packages will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$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
|
||||
} catch {
|
||||
Write-Host "Application $($appx.PackageName) could not be removed"
|
||||
continue
|
||||
if ($UseCmdlets) {
|
||||
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
|
||||
} catch {
|
||||
Write-Host "Application $($appx.PackageName) could not be removed"
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($appx in $appxProvisionedPackages) {
|
||||
$status = "Removing Provisioned $appx"
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
|
||||
dism /english /image="$scratchDir" /remove-provisionedappxpackage /packagename=$appx /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "AppX package $appx could not be removed."
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed
|
||||
}
|
||||
catch
|
||||
{
|
||||
# This can happen if getting AppX packages fails
|
||||
Write-Host "Unable to get information about the AppX packages. MicroWin processing will continue, but AppX packages will not be processed"
|
||||
Write-Host "Unable to get information about the AppX packages. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemoveProvisionedPackages -UseCmdlets $false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user