win: improve system app uninstall cleanup #73
- Add documentation about folders. - Add more user-friendly logging. - Continue uninstallation if single folder fails (remove throw). - Continue uninstallation if renaming single file fails. - Add handling of `Metadata` folder as suggested in #73.
This commit is contained in:
@@ -9797,50 +9797,113 @@ functions:
|
|||||||
name: UninstallSystemApp
|
name: UninstallSystemApp
|
||||||
parameters:
|
parameters:
|
||||||
- name: packageName
|
- name: packageName
|
||||||
# It simply renames files
|
# It simply renames folders
|
||||||
# Because system apps are non removable (check: (Get-AppxPackage -AllUsers 'Windows.CBSPreview').NonRemovable)
|
# Because system apps are non removable (check: (Get-AppxPackage -AllUsers 'Windows.CBSPreview').NonRemovable)
|
||||||
# Otherwise they throw 0x80070032 when trying to uninstall them
|
# Otherwise they throw 0x80070032 when trying to uninstall them
|
||||||
|
# This script all files in three application folders to make them inaccessible for the operating system:
|
||||||
|
# 1. Installation
|
||||||
|
# - Parent : `%WINDIR%\SystemApps\{PackageFamilyName}` or `%WINDIR%\{AppName}`
|
||||||
|
# - Example : `C:\Windows\SystemApps\Windows.CBSPreview_cw5n1h2txyewy` or `C:\Windows\PrintDialog`
|
||||||
|
# - Check : `(Get-AppxPackage -AllUsers 'Windows.CBSPreview').InstallLocation` or `(Get-AppxPackage -AllUsers 'Windows.PrintDialog').InstallLocation`
|
||||||
|
# 2. User-specific data
|
||||||
|
# - Parent : %LOCALAPPDATA%\Packages\
|
||||||
|
# - Example : C:\Users\undergroundwires\AppData\Local\Packages\Windows.CBSPreview_cw5n1h2txyewy
|
||||||
|
# - Check : "$env:LOCALAPPDATA\Packages\$((Get-AppxPackage -AllUsers 'Windows.CBSPreview').PackageFamilyName)"
|
||||||
|
# 3. Metadata
|
||||||
|
# - Parent : `%PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\${PackageFullName}`
|
||||||
|
# - Example : C:\ProgramData\Microsoft\Windows\AppRepository\Packages\Windows.CBSPreview_10.0.19580.1000_neutral_neutral_cw5n1h2txyewy
|
||||||
|
# - Check : "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$((Get-AppxPackage -AllUsers 'Windows.CBSPreview').PackageFullName)"
|
||||||
call:
|
call:
|
||||||
function: RunPowerShell
|
function: RunPowerShell
|
||||||
parameters:
|
parameters:
|
||||||
code: |-
|
code: |-
|
||||||
$package = Get-AppxPackage -AllUsers '{{ $packageName }}'
|
$packageName = '{{ $packageName }}'
|
||||||
if (!$package) {
|
Write-Host "Soft-deleting `"$packageName`" folders."
|
||||||
Write-Host 'Not installed'
|
$package = Get-AppxPackage -AllUsers $packageName
|
||||||
|
if (!$package) {
|
||||||
|
Write-Host "Skipping, package `"$packageName`" is not installed."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
$directories = @($package.InstallLocation, "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)")
|
$directories = @(
|
||||||
foreach($dir in $directories) {
|
@{ Name = 'Installation'; Path = $package.InstallLocation; }
|
||||||
if ( !$dir -Or !(Test-Path "$dir") ) { continue }
|
@{ Name = 'User-specific data'; Path = "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)"; }
|
||||||
cmd /c ('takeown /f "' + $dir + '" /r /d y 1> nul')
|
@{ Name = 'Metadata'; Path = "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$($package.PackageFullName)"; }
|
||||||
if($LASTEXITCODE) { throw 'Failed to take ownership' }
|
)
|
||||||
cmd /c ('icacls "' + $dir + '" /grant administrators:F /t 1> nul')
|
foreach($directory in $directories) {
|
||||||
if($LASTEXITCODE) { throw 'Failed to take ownership' }
|
Write-Host "Processing folder: `"$($directory.Name)`"..."
|
||||||
$files = Get-ChildItem -File -Path $dir -Recurse -Force
|
if (!$directory.Path) {
|
||||||
foreach($file in $files) {
|
Write-Host 'Skipping, path not found.'
|
||||||
if($file.Name.EndsWith('.OLD')) { continue }
|
continue
|
||||||
$newName = $file.FullName + '.OLD'
|
}
|
||||||
Write-Host "Rename '$($file.FullName)' to '$newName'"
|
if (!(Test-Path $directory.Path)) {
|
||||||
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force
|
Write-Host "Skipping, directory `"$($directory.Path)`" does not exist."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd /c ("takeown /f `"$($directory.Path)`" /r /d y 1> nul")
|
||||||
|
if ($LASTEXITCODE) {
|
||||||
|
Write-Error "Failed to obtain ownership for `"$($directory.Path)`"."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd /c ("icacls `"$($directory.Path))`" /grant administrators:F /t 1> nul")
|
||||||
|
if ($LASTEXITCODE) {
|
||||||
|
Write-Error "Failed to assign permissions for `"$($directory.Path)`"."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$files = Get-ChildItem -File -Path $directory.Path -Recurse -Force
|
||||||
|
foreach ($file in $files) {
|
||||||
|
if($file.Name.EndsWith('.OLD')) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$newName = "$($file.FullName).OLD"
|
||||||
|
try {
|
||||||
|
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force -ErrorAction Stop
|
||||||
|
Write-Host "Successfully renamed `"$($file.FullName)`"."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to rename `"$($file.FullName)`" to `"$newName`": $($_.Exception.Message)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
revertCode: |-
|
revertCode: |-
|
||||||
$package = Get-AppxPackage -AllUsers '{{ $packageName }}'
|
$packageName = '{{ $packageName }}'
|
||||||
if (!$package) {
|
$package = Get-AppxPackage -AllUsers $packageName
|
||||||
Write-Error 'App could not be found' -ErrorAction Stop
|
Write-Host "Restoring `"$packageName`" folders."
|
||||||
|
if (!$package) {
|
||||||
|
throw "The package `"$packageName`" could not be found."
|
||||||
}
|
}
|
||||||
$directories = @($package.InstallLocation, "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)")
|
$directories = @(
|
||||||
foreach($dir in $directories) {
|
@{ Name = 'Installation'; Path = $package.InstallLocation; }
|
||||||
if ( !$dir -Or !(Test-Path "$dir") ) { continue; }
|
@{ Name = 'User-specific data'; Path = "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)"; }
|
||||||
cmd /c ('takeown /f "' + $dir + '" /r /d y 1> nul')
|
@{ Name = 'Metadata'; Path = "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$($package.PackageFullName)"; }
|
||||||
if($LASTEXITCODE) { throw 'Failed to take ownership' }
|
)
|
||||||
cmd /c ('icacls "' + $dir + '" /grant administrators:F /t 1> nul')
|
foreach ($directory in $directories) {
|
||||||
if($LASTEXITCODE) { throw 'Failed to take ownership' }
|
Write-Host "Processing folder: `"$($directory.Name)`" directory..."
|
||||||
$files = Get-ChildItem -File -Path "$dir\*.OLD" -Recurse -Force
|
if (!$directory.Path) {
|
||||||
foreach($file in $files) {
|
Write-Host "Skipping `"$($directory.Name)`" directory, path not found."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!(Test-Path $directory.Path)) {
|
||||||
|
Write-Host "Skipping, directory `"$($directory.Path)`" does not exist."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd /c ("takeown /f `"$($directory.Path)`" /r /d y 1> nul")
|
||||||
|
if ($LASTEXITCODE) {
|
||||||
|
Write-Error "Failed to obtain ownership for `"$($directory.Path)`"."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd /c ("icacls `"$($directory.Path)`" /grant administrators:F /t 1> nul")
|
||||||
|
if ($LASTEXITCODE) {
|
||||||
|
Write-Error "Failed to assign permissions for `"$($directory.Path)`"."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$files = Get-ChildItem -File -Path "$($directory.Path)\*.OLD" -Recurse -Force
|
||||||
|
foreach ($file in $files) {
|
||||||
$newName = $file.FullName.Substring(0, $file.FullName.Length - 4)
|
$newName = $file.FullName.Substring(0, $file.FullName.Length - 4)
|
||||||
Write-Host "Rename '$($file.FullName)' to '$newName'"
|
try {
|
||||||
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force
|
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force -ErrorAction Stop
|
||||||
|
Write-Host "Successfully renamed `"$($file.FullName)`" back to original."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to rename `"$($file.FullName)`" back to original `"$newName`": $($_.Exception.Message)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
|
|||||||
Reference in New Issue
Block a user