-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUndoScript.ps1
170 lines (142 loc) · 5.81 KB
/
UndoScript.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# UndoFilteredFromSunshineConfig.ps1
param(
# Used by Helpers.ps1 (and for filtering undo commands)
[Parameter(Mandatory = $true)]
[Alias("n")]
[string]$ScriptName,
# When this switch is not present, the script will relaunch itself detached via WMI.
[Switch]$Detached
)
# If not already running detached, re-launch self via WMI and exit.
if (-not $Detached) {
# Get the full path of this script.
$scriptPath = $MyInvocation.MyCommand.Definition
# Build the command line; note that we add the -Detached switch.
$command = "powershell.exe -ExecutionPolicy Bypass -File `"$scriptPath`" -ScriptName `"$ScriptName`" -Detached"
Write-Host "Launching detached instance via WMI: $command"
# Launch using WMI Create process.
([wmiclass]"\\.\root\cimv2:Win32_Process").Create($command) | Out-Null
exit
}
# Now we are running in detached mode.
# Set the working directory to this script's folder.
$path = (Split-Path $MyInvocation.MyCommand.Path -Parent)
Set-Location $path
# Load helper functions (assumes Helpers.ps1 exists in the same folder)
. .\Helpers.ps1 -n $ScriptName
# Load settings (this function should be defined in Helpers.ps1)
$settings = Get-Settings
# Define a unique, system-wide mutex name.
$mutexName = "Global\SunshineUndoMutex"
$createdNew = $false
$mutex = New-Object System.Threading.Mutex($true, $mutexName, [ref] $createdNew)
if (-not $createdNew) {
Write-Host "Undo process already in progress or executed. Exiting..."
exit
}
try {
Write-Host "Acquired mutex. Running undo process..."
# Retrieve the list of script names from settings.
$desiredNames = $settings.installationOrderPreferences.scriptNames
if (-not $desiredNames) {
Write-Error "No script names defined in settings.installationOrderPreferences.scriptNames."
exit 1
}
### 1. Read the Sunshine config file and extract the global_prep_cmd JSON array.
try {
$configContent = Get-Content -Path $settings.sunshineConfigPath -Raw
}
catch {
Write-Error "Unable to read Sunshine config file at '$($settings.sunshineConfigPath)'. Error: $_"
exit 1
}
if ($configContent -match 'global_prep_cmd\s*=\s*(\[[^\]]+\])') {
$jsonText = $matches[1]
}
else {
Write-Error "Could not find a valid 'global_prep_cmd' entry in the config file."
exit 1
}
try {
$prepCommands = $jsonText | ConvertFrom-Json
}
catch {
Write-Error "Failed to parse global_prep_cmd JSON: $_"
exit 1
}
if (-not ($prepCommands -is [System.Collections.IEnumerable])) {
$prepCommands = @($prepCommands)
}
### 2. Filter the commands so that only those whose undo command matches one of the desired script names are processed.
$filteredCommands = @()
foreach ($name in $desiredNames) {
# Escape the script name for regex matching.
$regexName = [regex]::Escape($name)
$matchesForName = $prepCommands | Where-Object { $_.undo -match $regexName }
if ($matchesForName) {
$filteredCommands += $matchesForName
}
}
if (-not $filteredCommands) {
Write-Host "No matching undo commands found for the desired script names. Exiting."
exit 0
}
### 3. Order the commands in reverse of the installation order.
$desiredNamesReversed = $desiredNames.Clone()
[Array]::Reverse($desiredNamesReversed)
$finalCommands = @()
foreach ($name in $desiredNamesReversed) {
$cmdForName = $filteredCommands | Where-Object { $_.undo -match [regex]::Escape($name) }
if ($cmdForName) {
# Add all matching commands (if more than one per script)
$finalCommands += $cmdForName
}
}
### 4. Execute the filtered undo commands synchronously.
Write-Host "Starting undo for filtered installed scripts (in reverse order):"
foreach ($cmd in $finalCommands) {
if ($cmd.undo -and $cmd.undo.Trim() -ne "") {
# Save the original undo command text.
$undoCommand = $cmd.undo
if ($undoCommand -contains "PlayniteWatcher" -or $undoCommand -contains "RTSSLimiter") {
continue
}
# Look for the -file parameter and extract its value.
if ($undoCommand -match '-file\s+"([^"]+)"') {
$origFilePath = $matches[1]
$origFileName = Split-Path $origFilePath -Leaf
# If the file isn't already Helpers.ps1, replace it.
if ($origFileName -ne "Helpers.ps1") {
$folder = Split-Path $origFilePath -Parent
$newFilePath = Join-Path $folder "Helpers.ps1"
# Replace the original file path with the new Helpers.ps1 path.
$undoCommand = $undoCommand -replace [regex]::Escape($origFilePath), $newFilePath
if ($undoCommand -notcontains "-t 1") {
$undoCommand = $undoCommand + " -t 1"
}
Write-Host "Modified undo command to: $undoCommand"
}
}
Write-Host "Running undo command:"
Write-Host " $undoCommand"
try {
# Execute the modified undo command synchronously.
Invoke-Expression $undoCommand
Write-Host "Undo command completed."
}
catch {
Write-Warning "Failed to run undo command for one of the scripts: $_"
}
}
else {
Write-Host "No undo command for this entry. Skipping."
}
Start-Sleep -Seconds 1 # Optional pause between commands.
}
Write-Host "All undo operations have been processed."
}
finally {
# Always release and dispose of the mutex.
$mutex.ReleaseMutex()
$mutex.Dispose()
}