|
5 | 5 | using Microsoft.Win32; |
6 | 6 | using System; |
7 | 7 | using System.Collections.Generic; |
| 8 | +using System.Diagnostics; |
| 9 | +using System.Management.Automation; |
8 | 10 |
|
9 | 11 | namespace AnyPackage.Provider.Programs |
10 | 12 | { |
11 | 13 | [PackageProvider("Programs")] |
12 | | - public sealed class ProgramsProvider : PackageProvider, IGetPackage |
| 14 | + public sealed class ProgramsProvider : PackageProvider, IGetPackage, IUninstallPackage |
13 | 15 | { |
14 | 16 | private const string _uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; |
| 17 | + private const string _uninstallString = "UninstallString"; |
| 18 | + private const string _quietUninstallString = "QuietUninstallString"; |
15 | 19 |
|
16 | 20 | protected override object? GetDynamicParameters(string commandName) |
17 | 21 | { |
@@ -40,6 +44,29 @@ public void GetPackage(PackageRequest request) |
40 | 44 | GetPackage(hkcu, request); |
41 | 45 | } |
42 | 46 |
|
| 47 | + public void UninstallPackage(PackageRequest request) |
| 48 | + { |
| 49 | + if (request.Package is not null) |
| 50 | + { |
| 51 | + UninstallPackage(request.Package, request); |
| 52 | + } |
| 53 | + else |
| 54 | + { |
| 55 | + using var powershell = PowerShell.Create(); |
| 56 | + powershell.AddCommand("Get-Package").AddParameter("Name", request.Name); |
| 57 | + |
| 58 | + if (request.Version is not null) |
| 59 | + { |
| 60 | + powershell.AddParameter("Version", request.Version); |
| 61 | + } |
| 62 | + |
| 63 | + foreach (var package in powershell.Invoke<PackageInfo>()) |
| 64 | + { |
| 65 | + UninstallPackage(package, request); |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + |
43 | 70 | private void GetPackage(RegistryKey key, PackageRequest request) |
44 | 71 | { |
45 | 72 | var dynamicParameters = request.DynamicParameters as GetPackageDynamicParameters; |
@@ -104,5 +131,80 @@ private void GetPackage(RegistryKey key, PackageRequest request) |
104 | 131 | } |
105 | 132 | } |
106 | 133 | } |
| 134 | + |
| 135 | + private void UninstallPackage(PackageInfo package, PackageRequest request) |
| 136 | + { |
| 137 | + string uninstallString; |
| 138 | + |
| 139 | + if (package.Metadata.ContainsKey(_quietUninstallString)) |
| 140 | + { |
| 141 | + request.WriteVerbose("Quiet uninstall string found."); |
| 142 | + uninstallString = package.Metadata[_quietUninstallString].ToString(); |
| 143 | + } |
| 144 | + else if (package.Metadata.ContainsKey(_uninstallString)) |
| 145 | + { |
| 146 | + request.WriteVerbose("Uninstall string found."); |
| 147 | + uninstallString = package.Metadata[_uninstallString].ToString(); |
| 148 | + } |
| 149 | + else |
| 150 | + { |
| 151 | + throw new InvalidOperationException($"Package '{package.Name}' with version '{package.Version} cannot find uninstall program."); |
| 152 | + } |
| 153 | + |
| 154 | + using var process = GetProcess(uninstallString); |
| 155 | + process.Start(); |
| 156 | + process.WaitForExit(); |
| 157 | + |
| 158 | + request.WritePackage(package); |
| 159 | + } |
| 160 | + |
| 161 | + private Process GetProcess(string text) |
| 162 | + { |
| 163 | + bool quoted, found; |
| 164 | + int i, position; |
| 165 | + |
| 166 | + quoted = found = false; |
| 167 | + i = position = 0; |
| 168 | + |
| 169 | + if (text[0] == '"') |
| 170 | + { |
| 171 | + quoted = true; |
| 172 | + } |
| 173 | + |
| 174 | + for (i = quoted ? 1 : 0; i < text.Length; i++) |
| 175 | + { |
| 176 | + if (text[i] == ' ' && !quoted) |
| 177 | + { |
| 178 | + position = i; |
| 179 | + found = true; |
| 180 | + break; |
| 181 | + } |
| 182 | + else if (text[i] == '"' && quoted) |
| 183 | + { |
| 184 | + position = i; |
| 185 | + found = true; |
| 186 | + break; |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + var process = new Process(); |
| 191 | + |
| 192 | + if (found && quoted) |
| 193 | + { |
| 194 | + process.StartInfo.FileName = text.Substring(0, position + 1).Replace("\"", ""); |
| 195 | + process.StartInfo.Arguments = text.Substring(position + 1, text.Length - position - 1).Trim(); |
| 196 | + } |
| 197 | + else if (found) |
| 198 | + { |
| 199 | + process.StartInfo.FileName = text.Substring(0, position); |
| 200 | + process.StartInfo.Arguments = text.Substring(position, text.Length - position).Trim(); |
| 201 | + } |
| 202 | + else |
| 203 | + { |
| 204 | + process.StartInfo.FileName = text; |
| 205 | + } |
| 206 | + |
| 207 | + return process; |
| 208 | + } |
107 | 209 | } |
108 | 210 | } |
0 commit comments