52 lines
3.2 KiB
PowerShell
52 lines
3.2 KiB
PowerShell
#Requires -Version 5.1
|
|
[CmdletBinding(SupportsShouldProcess)]
|
|
param(
|
|
[ValidateSet('List','Plan','Apply')][string]$Mode = 'Plan',
|
|
[ValidateSet('Zen','Helium','Tor')][string[]]$Browser = @('Zen'),
|
|
[string[]]$ExtraId = @(), [string[]]$ExcludeId = @(),
|
|
[switch]$SkipBundled, [switch]$KeepOneDrive, [switch]$KeepEdge, [switch]$Json
|
|
)
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
Import-Module (Join-Path $PSScriptRoot 'src/Wind.Core.psm1') -Force
|
|
Import-Module (Join-Path $PSScriptRoot 'src/Wind.Apps.psm1') -Force
|
|
if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) { throw 'Windows is required.' }
|
|
if ($Json -and $Mode -eq 'Apply') { throw '-Json is for List/Plan. Apply displays installer output.' }
|
|
$inventory = @(Get-WindAppInventory)
|
|
$selection = @{ ExtraId=$ExtraId; ExcludeId=$ExcludeId; SkipBundled=$SkipBundled; KeepOneDrive=$KeepOneDrive; KeepEdge=$KeepEdge }
|
|
$plan = @(Get-WindAppPlan -Inventory $inventory @selection)
|
|
if ($Mode -eq 'List') {
|
|
if ($Json) { ConvertTo-Json -InputObject @($plan) -Depth 5 }
|
|
else { $plan | Select-Object Name,Status,Scope,Id,Reason | Format-Table -Wrap }
|
|
return
|
|
}
|
|
if ($Json) {
|
|
[pscustomobject]@{ Browsers=@($Browser); Apps=@($plan | Where-Object Status -ne 'Keep'); Scope='Appx: current user. Desktop: displayed registration scope.' } | ConvertTo-Json -Depth 6
|
|
return
|
|
}
|
|
Write-Output ('Browsers: ' + ($Browser -join ', '))
|
|
$plan | Where-Object Status -ne 'Keep' | Select-Object Name,Status,Scope,Reason | Format-Table -Wrap
|
|
Write-Output 'Removal can delete app settings/data. Export mail, browser data and unsynced work first. OneDrive cloud-only files remain online; folders are not manually deleted.'
|
|
Write-Output 'Store, WebView2, runtimes, security tools and drivers are protected. Appx removal affects this user; provisioning and other users are unchanged.'
|
|
if ($Mode -eq 'Plan') { return }
|
|
if (-not $PSCmdlet.ShouldProcess('Displayed app plan', 'Install selected browsers and remove selected apps')) { return }
|
|
Assert-WindMutationAllowed
|
|
$context = Get-WindContext
|
|
if ($context.Build -notin @(19045,22631,26100,26200)) { throw 'App changes are gated to Windows builds 19045, 22631, 26100 and 26200. Use Windows Installed apps on other builds.' }
|
|
$mutex = [Threading.Mutex]::new($false,'Global\WindPrivacyPolicyTransaction')
|
|
$locked = $false
|
|
try {
|
|
try { $locked = $mutex.WaitOne(0) } catch [Threading.AbandonedMutexException] { $locked = $true }
|
|
if (-not $locked) { throw 'Another Wind transaction is running.' }
|
|
$reportRoot = Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'WindPrivacy\apps'
|
|
[IO.Directory]::CreateDirectory($reportRoot) | Out-Null
|
|
$reportPath = Join-Path $reportRoot ((Get-Date -Format 'yyyyMMdd-HHmmss') + '-' + [guid]::NewGuid().ToString('N') + '.json')
|
|
$save = { param($data) Save-WindJournal -Journal $data -Path $reportPath }.GetNewClosure()
|
|
Write-Output "Operation report: $reportPath"
|
|
$result = Invoke-WindAppChanges -Plan $plan -Browser $Browser -Backend (New-WindAppBackend) -Save $save -Confirm:$false
|
|
Write-Output "App operation: $($result.Status). Set your default browser in Windows Settings and verify it opens links."
|
|
} finally {
|
|
if ($locked) { $mutex.ReleaseMutex() }
|
|
$mutex.Dispose()
|
|
}
|