forked from ScoopInstaller/Scoop
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Uninstall.ps1
149 lines (130 loc) · 5.42 KB
/
Uninstall.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@(
@('core', 'Test-ScoopDebugEnabled'),
@('Helpers', 'New-IssuePrompt'),
@('install', 'msi_installed'),
@('manifest', 'Resolve-ManifestInformation'),
@('psmodules', 'install_psmodule'),
@('shortcuts', 'rm_startmenu_shortcuts'),
@('Versions', 'Clear-InstalledVersion')
) | ForEach-Object {
if (!([bool] (Get-Command $_[1] -ErrorAction 'Ignore'))) {
Write-Verbose "Import of lib '$($_[0])' initiated from '$PSCommandPath'"
. (Join-Path $PSScriptRoot "$($_[0]).ps1")
}
}
function Uninstall-ScoopApplication {
<#
.SYNOPSIS
Uninstall application.
.PARAMETER App
Application name to be uninstalled.
.PARAMETER Global
Globally installed application.
.PARAMETER Purge
Remove persisted data.
.PARAMETER Older
Remove older versions. Older versions are removed only on uninstallation, not on update.
#>
[CmdletBinding()]
[OutputType([Bool])]
param(
[String] $App,
[Switch] $Global,
[Switch] $Purge,
[Switch] $Older
# TODO: Force
)
# Do not uninstall when there is any process opened from application directory
$processdir = appdir $App $Global | Resolve-Path | Select-Object -ExpandProperty 'Path'
$processes = Get-Process | Where-Object { $_.Path -like "$processdir\*" }
if ($processes) {
$plPr = pluralize $processes.Count 'Process' 'Processes'
$plId = pluralize $processes.Count 'ID' 'IDs'
$plIs = pluralize $processes.Count 'is' 'are'
Write-UserMessage -Err -Message @(
'Application is still running!'
"$plPr with following $plId $plIs blocking uninstallation:"
($processes.Id -join ', ')
)
return $false
}
$version = Select-CurrentVersion -AppName $App -Global:$Global
$dir = versiondir $App $version $Global
$current_dir = current_dir $dir
$persist_dir = persistdir $App $Global
Write-UserMessage -Message "Uninstalling '$App' ($version)" -Output:$false
try {
Test-Path $dir -ErrorAction 'Stop' | Out-Null
} catch [UnauthorizedAccessException] {
Write-UserMessage -Message "Access denied: $dir. You might need to restart." -Err
return $false
}
$manifest = installed_manifest $App $version $Global
$install = install_info $App $version $Global
$architecture = $install.architecture
if ($install.dependency_for -and (installed $install.dependency_for)) {
Write-UserMessage -Message "Uninstalling dependency required for installed application '$($install.dependency_for)'. This operation could negatively influence the said application." -Warning
}
Invoke-ManifestScript -Manifest $manifest -ScriptName 'pre_uninstall' -Architecture $architecture
run_uninstaller $manifest $architecture $dir
Invoke-ManifestScript -Manifest $manifest -ScriptName 'post_uninstall' -Architecture $architecture
rm_shims $manifest $Global $architecture
rm_startmenu_shortcuts $manifest $Global $architecture
# If a junction was used during install, that will have been used
# as the reference directory. Otherwise it will just be the version
# directory.
$refdir = unlink_current $dir
uninstall_psmodule $manifest $refdir $Global
env_rm_path $manifest $refdir $Global $architecture
env_rm $manifest $Global $architecture
# Remove older versions
if ($Older) {
try {
# Unlink all potential old link before doing recursive Remove-Item
unlink_persist_data $dir
Remove-Item $dir -ErrorAction 'Stop' -Recurse -Force
} catch {
if (Test-Path $dir) {
Write-UserMessage -Message "Couldn't remove '$(friendly_path $dir)'; it may be in use." -Err
return $false
}
}
# TODO: foreach
Get-InstalledVersion -AppName $App -Global:$Global | ForEach-Object {
Write-UserMessage -Message "Removing older version ($_)." -Output:$false
$dir = versiondir $app $_ $Global
try {
# Unlink all potential old link before doing recursive Remove-Item
unlink_persist_data $dir
Remove-Item $dir -ErrorAction 'Stop' -Recurse -Force
} catch {
Write-UserMessage -Message "Couldn't remove '$(friendly_path $dir)'; it may be in use." -Err
return $false
}
}
if ((Get-InstalledVersion -AppName $App -Global:$Global).Count -eq 0) {
$appdir = appdir $App $Global
try {
# If last install failed, the directory seems to be locked and this
# will throw an error about the directory not existing
Remove-Item $appdir -ErrorAction 'Stop' -Recurse -Force
} catch {
if ((Test-Path $appdir)) { return $false } # only throw if the dir still exists
}
}
}
if ($Purge) {
Write-UserMessage -Message 'Removing persisted data.' -Output:$false
$persist_dir = persistdir $App $Global
if (Test-Path $persist_dir) {
try {
Remove-Item $persist_dir -ErrorAction 'Stop' -Recurse -Force
} catch {
Write-UserMessage -Message "Couldn't remove '$(friendly_path $persist_dir)'" -Err
return $false
}
}
# TODO: System wide purge uninstallation
}
return $true
}