add restore and backup fix #14
This commit is contained in:
@@ -13,7 +13,8 @@ param(
|
||||
'RemoveRecallTasks')]
|
||||
[array]$Options,
|
||||
[switch]$AllOptions,
|
||||
[switch]$revertMode
|
||||
[switch]$revertMode,
|
||||
[switch]$backupMode
|
||||
)
|
||||
|
||||
if ($nonInteractive) {
|
||||
@@ -39,6 +40,10 @@ If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]:
|
||||
$arglist = $arglist + ' -revertMode'
|
||||
}
|
||||
|
||||
if ($backupMode) {
|
||||
$arglist = $arglist + '-backupMode'
|
||||
}
|
||||
|
||||
|
||||
if ($Options -and $Options.count -ne 0) {
|
||||
#if options and alloptions is supplied just do all options
|
||||
@@ -106,6 +111,215 @@ function Run-Trusted([String]$command, $psversion) {
|
||||
|
||||
}
|
||||
|
||||
# function from: https://github.com/the-loan-wolf/Appx-Backup/blob/master/Appx-Backup.ps1
|
||||
function Backup-Appx {
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string] $WSAppPath,
|
||||
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string] $WSAppOutputPath
|
||||
)
|
||||
|
||||
function Get-FileFromWeb {
|
||||
param (
|
||||
# Parameter help description
|
||||
[Parameter(Mandatory)]
|
||||
[string]$URL,
|
||||
|
||||
# Parameter help description
|
||||
[Parameter(Mandatory)]
|
||||
[string]$File
|
||||
)
|
||||
Begin {
|
||||
|
||||
}
|
||||
Process {
|
||||
try {
|
||||
$storeEAP = $ErrorActionPreference
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# invoke request
|
||||
$request = [System.Net.HttpWebRequest]::Create($URL)
|
||||
$response = $request.GetResponse()
|
||||
|
||||
if ($response.StatusCode -eq 401 -or $response.StatusCode -eq 403 -or $response.StatusCode -eq 404) {
|
||||
throw "Remote file either doesn't exist, is unauthorized, or is forbidden for '$URL'."
|
||||
}
|
||||
|
||||
if ($File -match '^\.\\') {
|
||||
$File = Join-Path (Get-Location -PSProvider 'FileSystem') ($File -Split '^\.')[1]
|
||||
}
|
||||
|
||||
if ($File -and !(Split-Path $File)) {
|
||||
$File = Join-Path (Get-Location -PSProvider 'FileSystem') $File
|
||||
}
|
||||
|
||||
if ($File) {
|
||||
$fileDirectory = $([System.IO.Path]::GetDirectoryName($File))
|
||||
if (!(Test-Path($fileDirectory))) {
|
||||
[System.IO.Directory]::CreateDirectory($fileDirectory) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
[long]$fullSize = $response.ContentLength
|
||||
$fullSizeMB = $fullSize / 1024 / 1024
|
||||
|
||||
# define buffer
|
||||
[byte[]]$buffer = new-object byte[] 1048576
|
||||
[long]$total = [long]$count = 0
|
||||
|
||||
# create reader / writer
|
||||
$reader = $response.GetResponseStream()
|
||||
$writer = new-object System.IO.FileStream $File, 'Create'
|
||||
|
||||
# start download
|
||||
$finalBarCount = 0 #show final bar only one time
|
||||
do {
|
||||
|
||||
$count = $reader.Read($buffer, 0, $buffer.Length)
|
||||
|
||||
$writer.Write($buffer, 0, $count)
|
||||
|
||||
$total += $count
|
||||
$totalMB = $total / 1024 / 1024
|
||||
|
||||
if ($fullSize -gt 0) {
|
||||
#Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix 'MB'
|
||||
}
|
||||
|
||||
if ($total -eq $fullSize -and $count -eq 0 -and $finalBarCount -eq 0) {
|
||||
#Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix 'MB' -Complete
|
||||
$finalBarCount++
|
||||
}
|
||||
|
||||
} while ($count -gt 0)
|
||||
}
|
||||
|
||||
catch {
|
||||
|
||||
$ExeptionMsg = $_.Exception.Message
|
||||
Write-Host "Download breaks with error : $ExeptionMsg"
|
||||
}
|
||||
|
||||
finally {
|
||||
# cleanup
|
||||
if ($reader) { $reader.Close() }
|
||||
if ($writer) { $writer.Flush(); $writer.Close() }
|
||||
|
||||
$ErrorActionPreference = $storeEAP
|
||||
[GC]::Collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Run-Process {
|
||||
Param ($p, $a)
|
||||
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$pinfo.FileName = $p
|
||||
$pinfo.Arguments = $a
|
||||
$pinfo.RedirectStandardError = $true
|
||||
$pinfo.RedirectStandardOutput = $true
|
||||
$pinfo.UseShellExecute = $false
|
||||
$p = New-Object System.Diagnostics.Process
|
||||
$p.StartInfo = $pinfo
|
||||
$p.Start() | Out-Null
|
||||
$output = $p.StandardOutput.ReadToEnd()
|
||||
$output += $p.StandardError.ReadToEnd()
|
||||
$p.WaitForExit()
|
||||
return $output
|
||||
}
|
||||
|
||||
#tools path
|
||||
$WSTools = "$env:TEMP\AppxBackupTools-master\tool\x64"
|
||||
if (!(Test-Path $WSTools)) {
|
||||
Get-FileFromWeb -URL 'https://github.com/zoicware/AppxBackupTools/archive/refs/heads/master.zip' -File "$env:TEMP\BackupTools.zip"
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
Expand-Archive "$env:TEMP\BackupTools.zip" -DestinationPath $env:TEMP
|
||||
}
|
||||
|
||||
$WSAppXmlFile = 'AppxManifest.xml'
|
||||
|
||||
# read manifest
|
||||
$FileExists = Test-Path "$WSAppPath\$WSAppXmlFile"
|
||||
if ($FileExists -eq $False) {
|
||||
#temp: debug
|
||||
Write-Status -msg 'ERROR: Windows Store manifest not found.'
|
||||
}
|
||||
[xml]$manifest = Get-Content "$WSAppPath\$WSAppXmlFile"
|
||||
$WSAppName = $manifest.Package.Identity.Name
|
||||
$WSAppPublisher = $manifest.Package.Identity.Publisher
|
||||
|
||||
# prepare
|
||||
$WSAppFileName = Get-Item $WSAppPath | Select-Object basename
|
||||
$WSAppFileName = $WSAppFileName.BaseName
|
||||
|
||||
if (Test-Path "$WSAppOutputPath\$WSAppFileName.appx") {
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.appx"
|
||||
}
|
||||
$proc = "$WSTools\MakeAppx.exe"
|
||||
$args = "pack /d ""$WSAppPath"" /p ""$WSAppOutputPath\$WSAppFileName.appx"" /l"
|
||||
$output = Run-Process $proc $args
|
||||
if ($output -inotlike '*succeeded*') {
|
||||
Write-host ' ERROR: Appx creation failed!'
|
||||
Write-host " proc = $proc"
|
||||
Write-host " args = $args"
|
||||
Write-host (' ' + $output)
|
||||
# Exit
|
||||
}
|
||||
|
||||
|
||||
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pvk") {
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
|
||||
}
|
||||
if (Test-Path "$WSAppOutputPath\$WSAppFileName.cer") {
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.cer"
|
||||
}
|
||||
$proc = "$WSTools\MakeCert.exe"
|
||||
$args = "-n ""$WSAppPublisher"" -r -a sha256 -len 2048 -cy end -h 0 -eku 1.3.6.1.5.5.7.3.3 -b 01/01/2000 -pe -sv ""$WSAppOutputPath\$WSAppFileName.pvk"" ""$WSAppOutputPath\$WSAppFileName.cer"""
|
||||
$output = Run-Process $proc $args
|
||||
if ($output -inotlike '*succeeded*') {
|
||||
Write-host 'ERROR: Certificate creation failed!'
|
||||
Write-host "proc = $proc"
|
||||
Write-host "args = $args"
|
||||
Write-host (' ' + $output)
|
||||
# Exit
|
||||
}
|
||||
|
||||
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pfx") {
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"
|
||||
}
|
||||
$proc = "$WSTools\Pvk2Pfx.exe"
|
||||
$args = "-pvk ""$WSAppOutputPath\$WSAppFileName.pvk"" -spc ""$WSAppOutputPath\$WSAppFileName.cer"" -pfx ""$WSAppOutputPath\$WSAppFileName.pfx"""
|
||||
$output = Run-Process $proc $args
|
||||
if ($output.Length -gt 0) {
|
||||
Write-host ' ERROR: Certificate conversion to pfx failed!'
|
||||
Write-host " proc = $proc"
|
||||
Write-host " args = $args"
|
||||
Write-host (' ' + $output)
|
||||
# Exit
|
||||
}
|
||||
|
||||
$proc = "$WSTools\SignTool.exe"
|
||||
$args = "sign -fd SHA256 -a -f ""$WSAppOutputPath\$WSAppFileName.pfx"" ""$WSAppOutputPath\$WSAppFileName.appx"""
|
||||
$output = Run-Process $proc $args
|
||||
if ($output -inotlike '*successfully signed*') {
|
||||
Write-host 'ERROR: Package signing failed!'
|
||||
Write-host $output.Length
|
||||
Write-host "proc = $proc"
|
||||
Write-host "args = $args"
|
||||
Write-host (' ' + $output)
|
||||
# Exit
|
||||
}
|
||||
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
|
||||
Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Write-Status {
|
||||
param(
|
||||
[string]$msg,
|
||||
@@ -158,6 +372,13 @@ else {
|
||||
$Global:revert = 0
|
||||
}
|
||||
|
||||
if ($backupMode) {
|
||||
$Global:backup = 1
|
||||
}
|
||||
else {
|
||||
$Global:backup = 0
|
||||
}
|
||||
|
||||
#=====================================================================================
|
||||
|
||||
function Add-LogInfo {
|
||||
@@ -213,6 +434,7 @@ function Disable-Registry-Keys {
|
||||
#disable additional keys
|
||||
Reg.exe add 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings' /v 'AutoOpenCopilotLargeScreens' /t REG_DWORD /d @('0', '1')[$revert] /f *>$null
|
||||
Reg.exe add 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\generativeAI' /v 'Value' /t REG_SZ /d @('Deny', 'Allow')[$revert] /f *>$null
|
||||
Reg.exe add 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\systemAIModels' /v 'Value' /t REG_SZ /d @('Deny', 'Allow')[$revert] /f *>$null
|
||||
Reg.exe add 'HKLM\SOFTWARE\Policies\Microsoft\Windows\AppPrivacy' /v 'LetAppsAccessGenerativeAI' /t REG_DWORD /d @('2', '1')[$revert] /f *>$null
|
||||
Reg.exe add 'HKLM\SOFTWARE\Policies\Microsoft\Windows\AppPrivacy' /v 'LetAppsAccessSystemAIModels' /t REG_DWORD /d @('2', '1')[$revert] /f *>$null
|
||||
Reg.exe add 'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsCopilot' /v 'AllowCopilotRuntime' /t REG_DWORD /d @('0', '1')[$revert] /f *>$null
|
||||
@@ -228,15 +450,25 @@ function Disable-Registry-Keys {
|
||||
$backupPath = "$env:USERPROFILE\RemoveWindowsAI\Backup"
|
||||
$backupFile = 'WSAIFabricSvc.reg'
|
||||
if ($revert) {
|
||||
Reg.exe import "$backupPath\$backupFile" >$null
|
||||
sc.exe create WSAIFabricSvc binPath= "$env:windir\System32\svchost.exe -k WSAIFabricSvcGroup -p" >$null
|
||||
if (Test-Path "$backupPath\$backupFile") {
|
||||
Reg.exe import "$backupPath\$backupFile" *>$null
|
||||
sc.exe create WSAIFabricSvc binPath= "$env:windir\System32\svchost.exe -k WSAIFabricSvcGroup -p" *>$null
|
||||
}
|
||||
else {
|
||||
Write-Status -msg "Path Not Found: $backupPath\$backupFile" -errorOutput $true
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if ($backup) {
|
||||
Write-Status -msg 'Backing up WSAIFabricSvc...'
|
||||
#export the service to a reg file before removing it
|
||||
if (!(Test-Path $backupPath)) {
|
||||
New-Item $backupPath -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
Reg.exe export 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WSAIFabricSvc' "$backupPath\$backupFile" >$null
|
||||
}
|
||||
Write-Status -msg 'Removing up WSAIFabricSvc...'
|
||||
#delete the service
|
||||
sc.exe delete WSAIFabricSvc *>$null
|
||||
}
|
||||
@@ -251,6 +483,7 @@ function Disable-Registry-Keys {
|
||||
# prob not worth trying to restore shouldnt break any functionality if the rest is restored
|
||||
# =========================
|
||||
function Remove-Copilot-Nudges-Keys {
|
||||
if (!$revert) {
|
||||
#prefire copilot nudges package by deleting the registry keys
|
||||
Write-Status -msg 'Removing Copilot Nudges Registry Keys...'
|
||||
$keys = @(
|
||||
@@ -292,6 +525,7 @@ function Remove-Copilot-Nudges-Keys {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -328,6 +562,32 @@ function Disable-Copilot-Policies {
|
||||
|
||||
|
||||
function Remove-AI-Appx-Packages {
|
||||
if ($revert) {
|
||||
#install backedup appx packages
|
||||
$appxBackup = "$env:USERPROFILE\RemoveWindowsAI\Backup\AppxBackup"
|
||||
if (Test-Path $appxBackup) {
|
||||
$files = Get-ChildItem $appxBackup
|
||||
Write-Status -msg 'Installing Appx Packages...'
|
||||
foreach ($file in $files) {
|
||||
if ($file.FullName -like '*.cer') {
|
||||
#install certs
|
||||
Import-Certificate -FilePath $file.FullName -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
|
||||
}
|
||||
}
|
||||
#install the packages
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
foreach ($file in $files) {
|
||||
if ($file.FullName -like '*.appx') {
|
||||
Add-AppPackage -Path $file.FullName
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Status -msg 'Unable to Find AppxBackup in User Directory!' -errorOutput $true
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
#to make this part faster make a txt file in temp with chunck of removal
|
||||
#code and then just run that from run
|
||||
#trusted function due to the design of having it hidden from the user
|
||||
@@ -374,6 +634,26 @@ function Remove-AI-Appx-Packages {
|
||||
'WindowsWorkload.ImageTextSearch.Stx.3'
|
||||
)
|
||||
|
||||
if ($backup) {
|
||||
#backup appx packages before removing them
|
||||
$appxBackup = "$env:USERPROFILE\RemoveWindowsAI\Backup\AppxBackup"
|
||||
if (!(Test-Path $appxBackup)) {
|
||||
New-Item $appxBackup -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
Write-Status -msg 'Backing Up AI Appx Packages...'
|
||||
#aix and core ai can not be backed up
|
||||
$packagesToBackup = get-appxpackage -AllUsers | Where-Object { $aipackages -contains $_.Name } | Where-Object { $_.Name -ne 'MicrosoftWindows.Client.AIX' -and $_.Name -ne 'MicrosoftWindows.Client.CoreAI' }
|
||||
[System.Windows.MessageBox]::Show('Please Select [NONE] On The Following Windows' , 'INFO', [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information) *>$null
|
||||
foreach ($package in $packagesToBackup) {
|
||||
Backup-Appx -WSAppPath $package.InstallLocation -WSAppOutputPath $appxBackup
|
||||
}
|
||||
|
||||
#cleanup tools
|
||||
Remove-Item "$env:TEMP\AppxBackupTools-master\tool\x64" -Force -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item "$env:TEMP\BackupTools.zip" -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$code = @'
|
||||
$aipackages = @(
|
||||
'MicrosoftWindows.Client.AIX'
|
||||
@@ -526,7 +806,10 @@ foreach ($choice in $aipackages) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Remove-Recall-Optional-Feature {
|
||||
if (!$revert) {
|
||||
#doesnt seem to work just gets stuck (does anyone really want this shit lol)
|
||||
#Enable-WindowsOptionalFeature -Online -FeatureName 'Recall' -All -NoRestart
|
||||
#remove recall optional feature
|
||||
@@ -543,9 +826,11 @@ function Remove-Recall-Optional-Feature {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# not restoring for now shouldnt cause any issues (also may not even be possible to restore)
|
||||
function Remove-AI-CBS-Packages {
|
||||
if (!$revert) {
|
||||
#additional hidden packages
|
||||
Write-Status -msg 'Removing Additional Hidden AI Packages...'
|
||||
#unhide the packages from dism, remove owners subkey for removal
|
||||
@@ -567,11 +852,87 @@ function Remove-AI-CBS-Packages {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Remove-AI-Files {
|
||||
#prob add params here for each file removal
|
||||
|
||||
|
||||
if ($revert) {
|
||||
if (Test-Path "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles") {
|
||||
Write-Status -msg 'Restoring Appx Package Files...'
|
||||
$paths = Get-Content "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\backupPaths.txt"
|
||||
foreach ($path in $paths) {
|
||||
$fileName = Split-Path $path -Leaf
|
||||
$dest = Split-Path $path -Parent
|
||||
try {
|
||||
Move-Item -Path "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\$fileName" -Destination $dest -Force -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
$command = "Move-Item -Path `"$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\$fileName`" -Destination `"$dest`" -Force"
|
||||
Run-Trusted -command $command -psversion $psversion
|
||||
Start-Sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\OfficeAI") {
|
||||
Write-Status -msg 'Restoring Office AI Files...'
|
||||
Move-Item "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\OfficeAI\x64\AI" -Destination "$env:ProgramFiles\Microsoft Office\root\vfs\ProgramFilesCommonX64\Microsoft Shared\Office16" -Force
|
||||
Move-Item "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\OfficeAI\x86\AI" -Destination "$env:ProgramFiles\Microsoft Office\root\vfs\ProgramFilesCommonX64\Microsoft Shared\Office16" -Force
|
||||
}
|
||||
|
||||
Write-Status -msg 'Restoring AI URIs...'
|
||||
$regs = Get-ChildItem "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\URIHandlers"
|
||||
foreach ($reg in $regs) {
|
||||
Reg.exe import $reg.FullName *>$null
|
||||
}
|
||||
|
||||
Write-Status -msg 'Files Restored... You May Need to Repair the Apps Using the Microsoft Store'
|
||||
}
|
||||
else {
|
||||
Write-Status -msg 'Unable to Find Backup Files!' -errorOutput $true
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$aipackages = @(
|
||||
# 'MicrosoftWindows.Client.Photon'
|
||||
'MicrosoftWindows.Client.AIX'
|
||||
'MicrosoftWindows.Client.CoPilot'
|
||||
'Microsoft.Windows.Ai.Copilot.Provider'
|
||||
'Microsoft.Copilot'
|
||||
'Microsoft.MicrosoftOfficeHub'
|
||||
'MicrosoftWindows.Client.CoreAI'
|
||||
#ai component packages installed on copilot+ pcs
|
||||
'WindowsWorkload.Data.Analysis.Stx.1'
|
||||
'WindowsWorkload.Manager.1'
|
||||
'WindowsWorkload.PSOnnxRuntime.Stx.2.7'
|
||||
'WindowsWorkload.PSTokenizer.Stx.2.7'
|
||||
'WindowsWorkload.QueryBlockList.1'
|
||||
'WindowsWorkload.QueryProcessor.Data.1'
|
||||
'WindowsWorkload.QueryProcessor.Stx.1'
|
||||
'WindowsWorkload.SemanticText.Data.1'
|
||||
'WindowsWorkload.SemanticText.Stx.1'
|
||||
'WindowsWorkload.Data.ContentExtraction.Stx.1'
|
||||
'WindowsWorkload.ScrRegDetection.Data.1'
|
||||
'WindowsWorkload.ScrRegDetection.Stx.1'
|
||||
'WindowsWorkload.TextRecognition.Stx.1'
|
||||
'WindowsWorkload.Data.ImageSearch.Stx.1'
|
||||
'WindowsWorkload.ImageContentModeration.1'
|
||||
'WindowsWorkload.ImageContentModeration.Data.1'
|
||||
'WindowsWorkload.ImageSearch.Data.3'
|
||||
'WindowsWorkload.ImageSearch.Stx.2'
|
||||
'WindowsWorkload.ImageSearch.Stx.3'
|
||||
'WindowsWorkload.ImageTextSearch.Data.3'
|
||||
'WindowsWorkload.PSOnnxRuntime.Stx.3.2'
|
||||
'WindowsWorkload.PSTokenizerShared.Data.3.2'
|
||||
'WindowsWorkload.PSTokenizerShared.Stx.3.2'
|
||||
'WindowsWorkload.ImageTextSearch.Stx.2'
|
||||
'WindowsWorkload.ImageTextSearch.Stx.3'
|
||||
)
|
||||
|
||||
Write-Status -msg 'Removing Appx Package Files...'
|
||||
#-----------------------------------------------------------------------remove files
|
||||
$appsPath = "$env:SystemRoot\SystemApps"
|
||||
@@ -634,6 +995,13 @@ function Remove-AI-Files {
|
||||
}
|
||||
}
|
||||
|
||||
if ($backup) {
|
||||
Write-Status -msg 'Backing Up AI Files...'
|
||||
$backupDir = "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles"
|
||||
if (!(Test-Path $backupDir)) {
|
||||
New-Item $backupDir -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($Path in $packagesPath) {
|
||||
#only remove dlls from photon to prevent startmenu from breaking
|
||||
@@ -643,10 +1011,25 @@ function Remove-AI-Files {
|
||||
# Start-Sleep 1
|
||||
# }
|
||||
# else {
|
||||
|
||||
if ($backup) {
|
||||
$backupFiles = "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\backupPaths.txt"
|
||||
if (!(Test-Path $backupFiles -PathType Leaf)) {
|
||||
New-Item $backupFiles -Force -ItemType File | Out-Null
|
||||
}
|
||||
try {
|
||||
Copy-Item -Path $Path -Destination $backupDir -Force -Recurse -ErrorAction Stop
|
||||
Add-Content -Path $backupFiles -Value $Path
|
||||
}
|
||||
catch {
|
||||
#ignore any errors
|
||||
}
|
||||
}
|
||||
|
||||
$command = "Remove-item ""$Path"" -force -recurse"
|
||||
Run-Trusted -command $command -psversion $psversion
|
||||
Start-Sleep 1
|
||||
# }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -719,6 +1102,22 @@ function Remove-AI-Files {
|
||||
|
||||
foreach ($path in $aiPaths) {
|
||||
if (Test-Path $path -PathType Container -ErrorAction SilentlyContinue) {
|
||||
if ($backup) {
|
||||
Write-Status -msg 'Backing Up Office AI Files...'
|
||||
$backupDir = "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\OfficeAI"
|
||||
if (!(Test-Path $backupDir)) {
|
||||
New-Item $backupDir -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
if ($path -like '*ProgramFilesCommonX64*') {
|
||||
$backupDir = "$backupDir\x64"
|
||||
New-Item $backupDir -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
else {
|
||||
$backupDir = "$backupDir\x86"
|
||||
New-Item $backupDir -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
Copy-Item -Path $path -Destination $backupDir -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
Remove-Item $path -Recurse -Force
|
||||
}
|
||||
}
|
||||
@@ -736,10 +1135,22 @@ function Remove-AI-Files {
|
||||
)
|
||||
|
||||
foreach ($uri in $uris) {
|
||||
if ($backup) {
|
||||
if (Test-Path $uri) {
|
||||
$backupDir = "$env:USERPROFILE\RemoveWindowsAI\Backup\AIFiles\URIHandlers"
|
||||
if (!(Test-Path $backupDir)) {
|
||||
New-Item $backupDir -Force -ItemType Directory | Out-Null
|
||||
}
|
||||
$regExportPath = "$backupDir\$($uri -replace 'registry::HKEY_CLASSES_ROOT\\', '').reg"
|
||||
Reg.exe export ($uri -replace 'registry::', '') $regExportPath /y *>$null
|
||||
}
|
||||
}
|
||||
Remove-Item $uri -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function Hide-AI-Components {
|
||||
#hide ai components in immersive settings
|
||||
@@ -873,10 +1284,16 @@ else {
|
||||
$contentRow.Height = [System.Windows.GridLength]::new(1, [System.Windows.GridUnitType]::Star)
|
||||
$mainGrid.RowDefinitions.Add($contentRow) | Out-Null
|
||||
|
||||
# Add this BEFORE your bottom row definition:
|
||||
$toggleRow = New-Object System.Windows.Controls.RowDefinition
|
||||
$toggleRow.Height = [System.Windows.GridLength]::new(130) # Fixed height for toggle
|
||||
$mainGrid.RowDefinitions.Add($toggleRow) | Out-Null
|
||||
|
||||
$bottomRow = New-Object System.Windows.Controls.RowDefinition
|
||||
$bottomRow.Height = [System.Windows.GridLength]::new(60)
|
||||
$bottomRow.Height = [System.Windows.GridLength]::new(80)
|
||||
$mainGrid.RowDefinitions.Add($bottomRow) | Out-Null
|
||||
|
||||
|
||||
$title = New-Object System.Windows.Controls.TextBlock
|
||||
$title.Text = 'Remove Windows AI'
|
||||
$title.FontSize = 18
|
||||
@@ -980,9 +1397,189 @@ else {
|
||||
$stackPanel.Children.Add($optionContainer) | Out-Null
|
||||
}
|
||||
|
||||
#add switches for backup and revert modes
|
||||
function Add-iOSToggleToUI {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[System.Windows.Controls.Panel]$ParentControl,
|
||||
[bool]$IsChecked = $false,
|
||||
[string]$Name = 'iOSToggle'
|
||||
)
|
||||
|
||||
$styleXaml = @'
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Style x:Key="CleanToggleStyle" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Width" Value="40"/>
|
||||
<Setter Property="Height" Value="24"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Focusable" Value="False"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Grid>
|
||||
<!-- Switch Track -->
|
||||
<Border x:Name="SwitchTrack"
|
||||
Width="40" Height="24"
|
||||
Background="#E5E5E7"
|
||||
CornerRadius="12"
|
||||
BorderThickness="0">
|
||||
|
||||
<!-- Switch Thumb -->
|
||||
<Border x:Name="SwitchThumb"
|
||||
Width="20" Height="20"
|
||||
Background="White"
|
||||
CornerRadius="10"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Margin="2,0,0,0">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect Color="#00000040"
|
||||
Direction="270"
|
||||
ShadowDepth="1"
|
||||
BlurRadius="3"
|
||||
Opacity="0.4"/>
|
||||
</Border.Effect>
|
||||
<Border.RenderTransform>
|
||||
<TranslateTransform x:Name="ThumbTransform" X="0"/>
|
||||
</Border.RenderTransform>
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<!-- Checked State (ON) -->
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Trigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<!-- Slide thumb to right -->
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ThumbTransform"
|
||||
Storyboard.TargetProperty="X"
|
||||
To="16"
|
||||
Duration="0:0:0.2"/>
|
||||
<!-- Change track color to green -->
|
||||
<ColorAnimation
|
||||
Storyboard.TargetName="SwitchTrack"
|
||||
Storyboard.TargetProperty="Background.Color"
|
||||
To="#34C759"
|
||||
Duration="0:0:0.2"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</Trigger.EnterActions>
|
||||
<Trigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<!-- Slide thumb to left -->
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ThumbTransform"
|
||||
Storyboard.TargetProperty="X"
|
||||
To="0"
|
||||
Duration="0:0:0.2"/>
|
||||
<!-- Change track color to gray -->
|
||||
<ColorAnimation
|
||||
Storyboard.TargetName="SwitchTrack"
|
||||
Storyboard.TargetProperty="Background.Color"
|
||||
To="#E5E5E7"
|
||||
Duration="0:0:0.2"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</Trigger.ExitActions>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
'@
|
||||
|
||||
$reader = New-Object System.Xml.XmlNodeReader([xml]$styleXaml)
|
||||
$resourceDict = [Windows.Markup.XamlReader]::Load($reader)
|
||||
|
||||
$toggleButton = New-Object System.Windows.Controls.Primitives.ToggleButton
|
||||
$toggleButton.Name = $Name
|
||||
$toggleButton.IsChecked = $IsChecked
|
||||
$toggleButton.Style = $resourceDict['CleanToggleStyle']
|
||||
$ParentControl.Children.Add($toggleButton) | Out-Null
|
||||
|
||||
return $toggleButton
|
||||
}
|
||||
|
||||
|
||||
|
||||
$toggleGrid = New-Object System.Windows.Controls.Grid
|
||||
[System.Windows.Controls.Grid]::SetRow($toggleGrid, 2)
|
||||
$toggleGrid.Margin = '20,10,55,15'
|
||||
|
||||
$row1 = New-Object System.Windows.Controls.RowDefinition
|
||||
$row1.Height = [System.Windows.GridLength]::Auto
|
||||
$row2 = New-Object System.Windows.Controls.RowDefinition
|
||||
$row2.Height = [System.Windows.GridLength]::Auto
|
||||
$toggleGrid.RowDefinitions.Add($row1) | Out-Null
|
||||
$toggleGrid.RowDefinitions.Add($row2) | Out-Null
|
||||
|
||||
$mainGrid.Children.Add($toggleGrid) | Out-Null
|
||||
|
||||
$togglePanel1 = New-Object System.Windows.Controls.StackPanel
|
||||
$togglePanel1.Orientation = [System.Windows.Controls.Orientation]::Horizontal
|
||||
$togglePanel1.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Left
|
||||
$togglePanel1.VerticalAlignment = [System.Windows.VerticalAlignment]::Center
|
||||
$togglePanel1.Margin = New-Object System.Windows.Thickness(0, 0, 0, 10)
|
||||
[System.Windows.Controls.Grid]::SetRow($togglePanel1, 0)
|
||||
|
||||
$toggleLabel1 = New-Object System.Windows.Controls.TextBlock
|
||||
$toggleLabel1.Text = 'Revert Mode:'
|
||||
$toggleLabel1.Foreground = [System.Windows.Media.Brushes]::White
|
||||
$toggleLabel1.VerticalAlignment = [System.Windows.VerticalAlignment]::Center
|
||||
$toggleLabel1.Margin = New-Object System.Windows.Thickness(0, 0, 10, 0)
|
||||
$togglePanel1.Children.Add($toggleLabel1) | Out-Null
|
||||
|
||||
$revertModeToggle = Add-iOSToggleToUI -ParentControl $togglePanel1 -IsChecked $revert
|
||||
$toggleGrid.Children.Add($togglePanel1) | Out-Null
|
||||
|
||||
$togglePanel2 = New-Object System.Windows.Controls.StackPanel
|
||||
$togglePanel2.Orientation = [System.Windows.Controls.Orientation]::Horizontal
|
||||
$togglePanel2.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Left
|
||||
$togglePanel2.VerticalAlignment = [System.Windows.VerticalAlignment]::Center
|
||||
[System.Windows.Controls.Grid]::SetRow($togglePanel2, 1)
|
||||
|
||||
$toggleLabel2 = New-Object System.Windows.Controls.TextBlock
|
||||
$toggleLabel2.Text = 'Backup Mode:'
|
||||
$toggleLabel2.Foreground = [System.Windows.Media.Brushes]::White
|
||||
$toggleLabel2.VerticalAlignment = [System.Windows.VerticalAlignment]::Center
|
||||
$toggleLabel2.Margin = New-Object System.Windows.Thickness(0, 0, 10, 0)
|
||||
$togglePanel2.Children.Add($toggleLabel2) | Out-Null
|
||||
|
||||
$backupModeToggle = Add-iOSToggleToUI -ParentControl $togglePanel2 -IsChecked $backup
|
||||
$toggleGrid.Children.Add($togglePanel2) | Out-Null
|
||||
|
||||
$backupModeToggle.Add_Checked({
|
||||
$Global:backup = 1
|
||||
}) | Out-Null
|
||||
|
||||
$backupModeToggle.Add_Unchecked({
|
||||
$Global:backup = 0
|
||||
}) | Out-Null
|
||||
|
||||
$revertModeToggle.Add_Checked({
|
||||
$Global:revert = 1
|
||||
}) | Out-Null
|
||||
$revertModeToggle.Add_Unchecked({
|
||||
$Global:revert = 0
|
||||
}) | Out-Null
|
||||
|
||||
|
||||
$bottomGrid = New-Object System.Windows.Controls.Grid
|
||||
[System.Windows.Controls.Grid]::SetRow($bottomGrid, 2)
|
||||
$bottomGrid.Margin = '20,10,20,10'
|
||||
[System.Windows.Controls.Grid]::SetRow($bottomGrid, 3)
|
||||
$bottomGrid.Margin = '25,15,25,15'
|
||||
|
||||
$leftColumn = New-Object System.Windows.Controls.ColumnDefinition
|
||||
$leftColumn.Width = [System.Windows.GridLength]::new(1, [System.Windows.GridUnitType]::Star)
|
||||
@@ -1260,6 +1857,7 @@ else {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
$actionPanel.Children.Add($cancelButton) | Out-Null
|
||||
$actionPanel.Children.Add($applyButton) | Out-Null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user