|
|
- using System;
- using System.Linq;
- using System.Threading.Tasks;
- using TrustedUninstaller.Shared.Exceptions;
- using TrustedUninstaller.Shared.Tasks;
- using YamlDotNet.Serialization;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- using System.Threading;
-
- namespace TrustedUninstaller.Shared.Actions
- {
- internal class SystemPackageAction : ITaskAction
- {
- public enum Architecture
- {
- amd64 = 0,
- wow64 = 1,
- msil = 2,
- x86 = 3,
- All = 4
- }
-
- [YamlMember(typeof(string), Alias = "name")]
- public string Name { get; set; }
-
- [YamlMember(typeof(string), Alias = "arch")]
- public Architecture Arch { get; set; } = Architecture.All;
-
- [YamlMember(typeof(string), Alias = "language")]
- public string Language { get; set; } = "*";
-
- [YamlMember(typeof(string), Alias = "regexExcludeFiles")]
- public string[]? RegexExcludeList { get; set; }
- [YamlMember(typeof(string), Alias = "excludeDependents")]
- public string[]? ExcludeDependentsList { get; set; }
-
- [YamlMember(typeof(string[]), Alias = "weight")]
- public int ProgressWeight { get; set; } = 15;
- public int GetProgressWeight() => ProgressWeight;
-
- private bool InProgress { get; set; }
- public void ResetProgress() => InProgress = false;
-
- public string ErrorString() => $"SystemPackageAction failed to remove '{Name}'.";
-
- public UninstallTaskStatus GetStatus()
- {
- if (InProgress) return UninstallTaskStatus.InProgress;
- return HasFinished ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
- }
- private bool HasFinished = false;
- public async Task<bool> RunTask()
- {
- if (InProgress) throw new TaskInProgressException("Another Appx action was called while one was in progress.");
- InProgress = true;
-
- Console.WriteLine($"Removing system package '{Name}'...");
-
- var excludeArgs = new StringBuilder("");
- if (RegexExcludeList != null)
- {
- foreach (var regex in RegexExcludeList)
- {
- excludeArgs.Append(@$" -xf ""{regex}""");
- }
- }
-
- var excludeDependsArgs = new StringBuilder("");
- if (ExcludeDependentsList != null)
- {
- foreach (var dependent in ExcludeDependentsList)
- {
- excludeDependsArgs.Append(@$" -xdependent ""{dependent}""");
- }
- }
-
- var psi = new ProcessStartInfo()
- {
- UseShellExecute = false,
- CreateNoWindow = true,
- Arguments = $@"-SystemPackage ""{Name}"" -Arch {Arch.ToString()} -Language ""{Language}""" + excludeArgs + excludeDependsArgs,
- FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
- RedirectStandardOutput = true,
- RedirectStandardError = true
- };
-
- var proc = Process.Start(psi);
-
- proc.OutputDataReceived += ProcOutputHandler;
- proc.ErrorDataReceived += ProcOutputHandler;
-
- proc.BeginOutputReadLine();
- proc.BeginErrorReadLine();
-
- bool exited = proc.WaitForExit(30000);
-
- // WaitForExit alone seems to not be entirely reliable
- while (!exited && ExeRunning(proc))
- {
- exited = proc.WaitForExit(30000);
- }
-
- using (var log = new StreamWriter("Logs\\Packages.txt", true))
- log.Write(output.ToString());
-
- HasFinished = true;
-
- InProgress = false;
- return true;
- }
-
- private StringBuilder output = new StringBuilder("");
- private bool PleaseWait = false;
- private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
- {
- var write = outLine == null ? "" : outLine.Data;
- output.Append(write + Environment.NewLine);
-
- if (String.IsNullOrEmpty(write)) return;
-
- if (write.StartsWith("--- Removing"))
- {
- Console.WriteLine(write.Substring(4, write.Length - 4));
- PleaseWait = true;
- }
- if (write.StartsWith("Waiting for the service to stop...") && PleaseWait)
- {
- PleaseWait = false;
- Console.WriteLine("This may take some time...");
- }
- }
-
- private static bool ExeRunning(Process process)
- {
- try
- {
- return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
- }
- catch (Exception)
- {
- return false;
- }
- }
- }
- }
|