Browse Source

Update to v0.7.3

master 0.7.3
Styris 5 months ago
parent
commit
ddfdcccc04
34 changed files with 6797 additions and 379 deletions
  1. +26
    -0
      TrustedUninstaller.CLI/CLI.cs
  2. BIN
      TrustedUninstaller.CLI/Properties/resources/CLI-Resources.7z
  3. BIN
      TrustedUninstaller.CLI/Properties/resources/ProcessInformer.7z
  4. +16
    -27
      TrustedUninstaller.CLI/TrustedUninstaller.CLI.csproj
  5. +13
    -4
      TrustedUninstaller.Shared/Actions/AppxAction.cs
  6. +157
    -14
      TrustedUninstaller.Shared/Actions/CmdAction.cs
  7. +92
    -35
      TrustedUninstaller.Shared/Actions/FileAction.cs
  8. +3
    -1
      TrustedUninstaller.Shared/Actions/LanguageAction.cs
  9. +1
    -0
      TrustedUninstaller.Shared/Actions/LineInFileAction.cs
  10. +174
    -12
      TrustedUninstaller.Shared/Actions/PowershellAction.cs
  11. +1
    -0
      TrustedUninstaller.Shared/Actions/RegistryKeyAction.cs
  12. +1
    -0
      TrustedUninstaller.Shared/Actions/RegistryValueAction.cs
  13. +187
    -28
      TrustedUninstaller.Shared/Actions/RunAction.cs
  14. +1
    -0
      TrustedUninstaller.Shared/Actions/ScheduledTaskAction.cs
  15. +80
    -56
      TrustedUninstaller.Shared/Actions/ServiceAction.cs
  16. +1
    -0
      TrustedUninstaller.Shared/Actions/ShortcutAction.cs
  17. +4
    -1
      TrustedUninstaller.Shared/Actions/SystemPackageAction.cs
  18. +178
    -116
      TrustedUninstaller.Shared/Actions/TaskKillAction.cs
  19. +1
    -0
      TrustedUninstaller.Shared/Actions/UpdateAction.cs
  20. +1
    -0
      TrustedUninstaller.Shared/Actions/UserAction.cs
  21. +1
    -0
      TrustedUninstaller.Shared/Actions/WriteStatusAction.cs
  22. +143
    -26
      TrustedUninstaller.Shared/AmeliorationUtil.cs
  23. +3340
    -0
      TrustedUninstaller.Shared/AugmentedProcess.cs
  24. +22
    -0
      TrustedUninstaller.Shared/Debug.cs
  25. +34
    -14
      TrustedUninstaller.Shared/Defender.cs
  26. +21
    -6
      TrustedUninstaller.Shared/Globals.cs
  27. +2
    -1
      TrustedUninstaller.Shared/Playbook.cs
  28. +507
    -0
      TrustedUninstaller.Shared/ProcessPrivilege.cs
  29. +1
    -0
      TrustedUninstaller.Shared/Tasks/ITaskAction.cs
  30. +8
    -0
      TrustedUninstaller.Shared/Tasks/TaskAction.cs
  31. +9
    -0
      TrustedUninstaller.Shared/Tasks/UninstallTask.cs
  32. +21
    -13
      TrustedUninstaller.Shared/TrustedUninstaller.Shared.csproj
  33. +1699
    -0
      TrustedUninstaller.Shared/Win32.cs
  34. +52
    -25
      TrustedUninstaller.Shared/WinUtil.cs

+ 26
- 0
TrustedUninstaller.CLI/CLI.cs View File

@ -142,6 +142,30 @@ namespace TrustedUninstaller.CLI
AmeliorationUtil.Playbook.Options = defaultOptions;
}
if (!AmeliorationUtil.Playbook.UseKernelDriver.HasValue)
{
if (new RegistryValueAction()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity",
Value = "Enabled",
Data = 1,
}.GetStatus()
!= UninstallTaskStatus.Completed
&&
new RegistryValueAction()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config",
Value = "VulnerableDriverBlocklistEnable",
Data = 0,
}.GetStatus()
== UninstallTaskStatus.Completed && (await GetDefenderToggles()).All(toggleOn => !toggleOn))
{
AmeliorationUtil.UseKernelDriver = true;
}
}
else
AmeliorationUtil.UseKernelDriver = AmeliorationUtil.Playbook.UseKernelDriver.Value;
try
{
if (!Directory.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ame-assassin")))
@ -150,9 +174,11 @@ namespace TrustedUninstaller.CLI
ExtractResourceFolder("resources", Directory.GetCurrentDirectory());
ExtractArchive(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CLI-Resources.7z"), AppDomain.CurrentDomain.BaseDirectory);
if (AmeliorationUtil.UseKernelDriver) ExtractArchive(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ProcessInformer.7z"), AppDomain.CurrentDomain.BaseDirectory);
try
{
File.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CLI-Resources.7z"));
File.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ProcessInformer.7z"));
} catch (Exception e)
{
}


BIN
TrustedUninstaller.CLI/Properties/resources/CLI-Resources.7z View File


BIN
TrustedUninstaller.CLI/Properties/resources/ProcessInformer.7z View File


+ 16
- 27
TrustedUninstaller.CLI/TrustedUninstaller.CLI.csproj View File

@ -70,6 +70,13 @@
<DebugType>embedded</DebugType>
<DefineConstants>SINGLE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<Optimize>true</Optimize>
<DebugType>embedded</DebugType>
<DefineConstants>SINGLE;DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>B8F0A67800B779C5CEF49BEAB6E5247E373F9452</ManifestCertificateThumbprint>
</PropertyGroup>
@ -91,21 +98,19 @@
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' Or '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")
cmd /c "echo Compiled&gt; "$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\Compiled.txt""</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PreBuildEvent>PowerShell -NoP -C "Get-Process 'ame-builder' -EA SilentlyContinue | Wait-Process -EA SilentlyContinue; EXIT 0"
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'CLI' -WindowStyle Hidden"
</PreBuildEvent>
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'CLI','""""x64\$(Configuration)""""' -NoNewWindow -Wait"
</PostBuildEvent>
<AllowedReferenceRelatedFileExtensions>
<!-- Prevent default XML files copied to output.-->
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' And '$(Configuration)|$(Platform)' != 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")</PostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
@ -113,16 +118,6 @@
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CLI.cs" />
@ -150,18 +145,12 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.0.0" />
<PackageReference Include="Microsoft.PowerShell.5.ReferenceAssemblies" Version="1.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="SQLitePCLRaw.core" Version="2.0.7" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.CodeDom" Version="6.0.0" />
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
<PackageReference Include="System.Management" Version="6.0.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
@ -171,7 +160,7 @@
<EmbeddedResource Include="Properties\resources\CLI-Resources.7z" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\resources\NSudoLC.exe" />
<EmbeddedResource Include="Properties\resources\ProcessInformer.7z" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

+ 13
- 4
TrustedUninstaller.Shared/Actions/AppxAction.cs View File

@ -16,6 +16,8 @@ namespace TrustedUninstaller.Shared.Actions
// Integrate ame-assassin later
internal class AppxAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
public enum AppxOperation
{
Remove = 0,
@ -39,6 +41,9 @@ namespace TrustedUninstaller.Shared.Actions
[YamlMember(typeof(bool), Alias = "verboseOutput")]
public bool Verbose { get; set; } = false;
[YamlMember(typeof(bool), Alias = "unregister")]
public bool Unregister { get; set; } = false;
[YamlMember(typeof(string), Alias = "weight")]
public int ProgressWeight { get; set; } = 30;
public int GetProgressWeight() => ProgressWeight;
@ -69,14 +74,18 @@ namespace TrustedUninstaller.Shared.Actions
InProgress = true;
Console.WriteLine($"Removing APPX {Type.ToString().ToLower()} '{Name}'...");
WinUtil.CheckKph();
string verboseArg = Verbose ? " -Verbose" : "";
string unregisterArg = Unregister ? " -Verbose" : "";
string kernelDriverArg = AmeliorationUtil.UseKernelDriver ? " -UseKernelDriver" : "";
var psi = new ProcessStartInfo()
{
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $@"-{Type.ToString()} ""{Name}""" + verboseArg,
Arguments = $@"-{Type.ToString()} ""{Name}""" + verboseArg + unregisterArg + kernelDriverArg,
FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
RedirectStandardOutput = true,
RedirectStandardError = true
@ -98,7 +107,7 @@ namespace TrustedUninstaller.Shared.Actions
bool exited = proc.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(proc))
while (!exited && ExeRunning("ame-assassin", proc.Id))
{
exited = proc.WaitForExit(30000);
}
@ -121,11 +130,11 @@ namespace TrustedUninstaller.Shared.Actions
if (!write.Equals("Complete!")) Console.WriteLine(write);
}
private static bool ExeRunning(Process process)
private static bool ExeRunning(string name, int id)
{
try
{
return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
return Process.GetProcessesByName(name).Any(x => x.Id == id);
}
catch (Exception)
{


+ 157
- 14
TrustedUninstaller.Shared/Actions/CmdAction.cs View File

@ -1,7 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TrustedUninstaller.Shared.Exceptions;
using TrustedUninstaller.Shared.Tasks;
@ -11,6 +13,25 @@ namespace TrustedUninstaller.Shared.Actions
{
public class CmdAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (InProgress) throw new TaskInProgressException("Another Cmd action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running cmd command '{Command}'...");
ExitCode = null;
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess();
else
RunAsPrivilegedProcess();
InProgress = false;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "command")]
public string Command { get; set; }
@ -48,21 +69,20 @@ namespace TrustedUninstaller.Shared.Actions
return ExitCode == null ? UninstallTaskStatus.ToDo: UninstallTaskStatus.Completed;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (InProgress) throw new TaskInProgressException("Another Cmd action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running cmd command '{Command}'...");
ExitCode = null;
return null;
}
private void RunAsProcess()
{
var process = new Process();
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + $"\"{Environment.ExpandEnvironmentVariables(this.Command)}\"",
Arguments = "/C " + $"\"{this.Command}\"",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
@ -83,7 +103,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
process.Dispose();
return true;
return;
}
var error = new StringBuilder();
@ -97,6 +117,114 @@ namespace TrustedUninstaller.Shared.Actions
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
if (!exited)
{
process.Kill();
throw new TimeoutException($"Command '{Command}' timeout exceeded.");
}
}
else
{
bool exited = process.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && CmdRunning(process.Id))
{
exited = process.WaitForExit(30000);
}
}
int exitCode = 0;
try
{
exitCode = process.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "CmdAction Error", Command);
}
if (exitCode != 0)
{
StandardError = error.ToString();
Console.WriteLine($"cmd instance exited with error code: {exitCode}");
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error message: {StandardError}");
ErrorLogger.WriteToErrorLog("Cmd exited with a non-zero exit code: " + exitCode, null, "CmdAction Error", Command);
this.ExitCode = exitCode;
}
else
{
ExitCode = 0;
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
}
private static bool CmdRunning(int id)
{
try
{
return Process.GetProcessesByName("cmd").Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private void RunAsPrivilegedProcess()
{
var process = new AugmentedProcess.Process();
var startInfo = new AugmentedProcess.ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + $"\"{Environment.ExpandEnvironmentVariables(this.Command)}\"",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
process.StartInfo = startInfo;
ProcessPrivilege.StartPrivilegedTask(process, RunAs);
if (!Wait)
{
process.Dispose();
return;
}
var error = new StringBuilder();
process.OutputDataReceived += PrivilegedProcOutputHandler;
process.ErrorDataReceived += delegate(object sender, AugmentedProcess.DataReceivedEventArgs args)
{
if (!String.IsNullOrEmpty(args.Data))
error.AppendLine(args.Data);
else
error.AppendLine();
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
@ -127,14 +255,29 @@ namespace TrustedUninstaller.Shared.Actions
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
InProgress = false;
return true;
}
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
private static void ProcOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;


+ 92
- 35
TrustedUninstaller.Shared/Actions/FileAction.cs View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -9,6 +10,7 @@ using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using TrustedUninstaller.Shared.Exceptions;
@ -19,6 +21,7 @@ namespace TrustedUninstaller.Shared.Actions
{
public class FileAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string RawPath { get; set; }
@ -81,13 +84,14 @@ namespace TrustedUninstaller.Shared.Actions
{
if (!TrustedInstaller)
{
try {await Task.Run(() => File.Delete(file));} catch {}
try { File.Delete(file);} catch (Exception e) { }
if (File.Exists(file))
{
try
{
EzUnlockFileW(file);
var result = EzUnlockFileW(file);
Testing.WriteLine($"ExUnlock on ({file}) result: " + result);
}
catch (Exception e)
{
@ -95,20 +99,21 @@ namespace TrustedUninstaller.Shared.Actions
$"FileAction Error", file);
}
try {await Task.Run(() => File.Delete(file));} catch {}
try {await Task.Run(() => File.Delete(file));} catch (Exception e) {Testing.WriteLine(e, "DeleteFile > File.Delete(File)");}
CmdAction delAction = new CmdAction()
{
Command = $"del /q /f \"{file}\""
};
await delAction.RunTask();
delAction.RunTaskOnMainThread();
}
}
else if (File.Exists("NSudoLC.exe"))
{
try
{
EzUnlockFileW(file);
var result = EzUnlockFileW(file);
Testing.WriteLine($"ExUnlock on ({file}) result: " + result);
}
catch (Exception e)
{
@ -123,7 +128,7 @@ namespace TrustedUninstaller.Shared.Actions
CreateWindow = false
};
await tiDelAction.RunTask();
tiDelAction.RunTaskOnMainThread();
if (tiDelAction.Output != null)
{
if (log) ErrorLogger.WriteToErrorLog(tiDelAction.Output, Environment.StackTrace,
@ -149,7 +154,7 @@ namespace TrustedUninstaller.Shared.Actions
{
Command = $"rmdir /Q /S \"{dir}\""
};
await deleteDirCmd.RunTask();
deleteDirCmd.RunTaskOnMainThread();
if (deleteDirCmd.StandardError != null)
{
@ -171,7 +176,7 @@ namespace TrustedUninstaller.Shared.Actions
CreateWindow = false
};
await tiDelAction.RunTask();
tiDelAction.RunTaskOnMainThread();
if (tiDelAction.Output != null)
{
@ -216,15 +221,28 @@ namespace TrustedUninstaller.Shared.Actions
var cmdAction = new CmdAction();
Console.WriteLine($"Removing driver service {driverService}...");
// TODO: Replace with win32
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = driverService;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "FileAction Warning", RawPath);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
catch (Exception servException)
{
@ -270,16 +288,19 @@ namespace TrustedUninstaller.Shared.Actions
{
try
{
using var search = new ManagementObjectSearcher($"select * from Win32_Service where ProcessId = '{svchost.Id}'");
foreach (ManagementObject queryObj in search.Get())
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(svchost.Id))
{
var serviceName = (string)queryObj["Name"]; // Access service name
var serv = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serv == null) svcCount++;
else svcCount += serv.DependentServices.Length + 1;
svcCount++;
try
{
var serviceController = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serviceController != null)
svcCount += serviceController.DependentServices.Length;
}
catch (Exception e)
{
Console.WriteLine($"\r\nError: Could not get amount of dependent services for {serviceName}.\r\nException: " + e.Message);
}
}
} catch (Exception e)
{
@ -328,7 +349,15 @@ namespace TrustedUninstaller.Shared.Actions
continue;
}
await taskKillAction.RunTask();
try
{
await taskKillAction.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
$"FileAction Error: Could not kill process {taskKillAction.ProcessName}.");
}
}
// This gives any obstinant processes some time to unlock the file on their own.
@ -352,6 +381,11 @@ namespace TrustedUninstaller.Shared.Actions
if (delay >= 800)
ErrorLogger.WriteToErrorLog($"Could not kill locking processes for file '{file}'. Process termination loop exceeded max cycles (8).",
Environment.StackTrace, "FileAction Error");
if (Path.GetExtension(file).Equals(".exe", StringComparison.OrdinalIgnoreCase))
{
await new TaskKillAction() { ProcessName = Path.GetFileNameWithoutExtension(file) }.RunTask();
}
await DeleteFile(file, true);
@ -419,7 +453,7 @@ namespace TrustedUninstaller.Shared.Actions
};
try
{
await permAction.RunTask();
permAction.RunTaskOnMainThread();
}
catch (Exception e)
{
@ -466,7 +500,7 @@ namespace TrustedUninstaller.Shared.Actions
}
}
}
else if (isFile)
if (isFile)
{
try
{
@ -486,7 +520,7 @@ namespace TrustedUninstaller.Shared.Actions
};
try
{
await permAction.RunTask();
permAction.RunTaskOnMainThread();
}
catch (Exception e)
{
@ -504,15 +538,30 @@ namespace TrustedUninstaller.Shared.Actions
var cmdAction = new CmdAction();
Console.WriteLine($"Removing driver service {driverService}...");
// TODO: Replace with win32
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = driverService;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "FileAction Warning", RawPath);
}
WinUtil.CheckKph();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
catch (Exception servException)
{
@ -558,16 +607,19 @@ namespace TrustedUninstaller.Shared.Actions
{
try
{
using var search = new ManagementObjectSearcher($"select * from Win32_Service where ProcessId = '{svchost.Id}'");
foreach (ManagementObject queryObj in search.Get())
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(svchost.Id))
{
var serviceName = (string)queryObj["Name"]; // Access service name
var serv = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serv == null) svcCount++;
else svcCount += serv.DependentServices.Length + 1;
svcCount++;
try
{
var serviceController = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serviceController != null)
svcCount += serviceController.DependentServices.Length;
}
catch (Exception e)
{
Console.WriteLine($"\r\nError: Could not get amount of dependent services for {serviceName}.\r\nException: " + e.Message);
}
}
} catch (Exception e)
{
@ -645,6 +697,11 @@ namespace TrustedUninstaller.Shared.Actions
ErrorLogger.WriteToErrorLog($"Could not kill locking processes for file '{realPath}'. Process termination loop exceeded max cycles (8).",
Environment.StackTrace, "FileAction Error");
if (Path.GetExtension(realPath).Equals(".exe", StringComparison.OrdinalIgnoreCase))
{
await new TaskKillAction() { ProcessName = Path.GetFileNameWithoutExtension(realPath) }.RunTask();
}
await DeleteFile(realPath, true);
}
}


+ 3
- 1
TrustedUninstaller.Shared/Actions/LanguageAction.cs View File

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -8,6 +9,7 @@ namespace TrustedUninstaller.Shared.Actions
{
class LanguageAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
public int ProgressWeight { get; set; } = 1;
public int GetProgressWeight() => ProgressWeight;


+ 1
- 0
TrustedUninstaller.Shared/Actions/LineInFileAction.cs View File

@ -16,6 +16,7 @@ namespace TrustedUninstaller.Shared.Actions
}
internal class LineInFileAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(Alias = "path")]
public string RawPath { get; set; }


+ 174
- 12
TrustedUninstaller.Shared/Actions/PowershellAction.cs View File

@ -14,6 +14,26 @@ namespace TrustedUninstaller.Shared.Actions
{
public class PowerShellAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (InProgress) throw new TaskInProgressException("Another Powershell action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running PowerShell command '{Command}'...");
WinUtil.CheckKph();
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess();
else
RunAsPrivilegedProcess();
InProgress = false;
return;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "command")]
public string Command { get; set; }
@ -50,13 +70,13 @@ namespace TrustedUninstaller.Shared.Actions
return ExitCode == null ? UninstallTaskStatus.ToDo: UninstallTaskStatus.Completed;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (InProgress) throw new TaskInProgressException("Another Powershell action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running PowerShell command '{Command}'...");
return null;
}
private void RunAsProcess()
{
var process = new Process();
var startInfo = new ProcessStartInfo
{
@ -83,7 +103,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
process.Dispose();
return true;
return;
}
var error = new StringBuilder();
@ -98,6 +118,114 @@ namespace TrustedUninstaller.Shared.Actions
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
if (!exited)
{
process.Kill();
throw new TimeoutException($"Command '{Command}' timeout exceeded.");
}
}
else
{
bool exited = process.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && PowerShellRunning(process.Id))
{
exited = process.WaitForExit(30000);
}
}
StandardError = error.ToString();
int exitCode = 0;
try
{
exitCode = process.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "PowerShellAction Error", Command);
}
if (exitCode != 0)
{
Console.WriteLine($"PowerShell instance exited with error code: {exitCode}");
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error message: {StandardError}");
ErrorLogger.WriteToErrorLog("PowerShell exited with a non-zero exit code: " + exitCode, null, "PowerShellAction Error", Command);
this.ExitCode = exitCode;
}
else
{
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error output: {StandardError}");
ExitCode = 0;
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
}
private static bool PowerShellRunning(int id)
{
try
{
return Process.GetProcessesByName("powershell").Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private void RunAsPrivilegedProcess()
{
var process = new AugmentedProcess.Process();
var startInfo = new AugmentedProcess.ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "PowerShell.exe",
Arguments = $@"-NoP -ExecutionPolicy Bypass -NonInteractive -C ""{Command}""",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
process.StartInfo = startInfo;
ProcessPrivilege.StartPrivilegedTask(process, RunAs);
if (!Wait)
{
process.Dispose();
return;
}
var error = new StringBuilder();
process.OutputDataReceived += PrivilegedProcOutputHandler;
process.ErrorDataReceived += delegate(object sender, AugmentedProcess.DataReceivedEventArgs args)
{
if (!String.IsNullOrEmpty(args.Data))
error.AppendLine(args.Data);
else
error.AppendLine();
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
@ -129,16 +257,50 @@ namespace TrustedUninstaller.Shared.Actions
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
InProgress = false;
return true;
}
private static bool ExeRunning(string exe, int id)
{
try
{
return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(exe)).Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private static void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
Console.WriteLine(outLine.Data);
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{


+ 1
- 0
TrustedUninstaller.Shared/Actions/RegistryKeyAction.cs View File

@ -23,6 +23,7 @@ namespace TrustedUninstaller.Shared.Actions
}
public class RegistryKeyAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string KeyName { get; set; }


+ 1
- 0
TrustedUninstaller.Shared/Actions/RegistryValueAction.cs View File

@ -38,6 +38,7 @@ namespace TrustedUninstaller.Shared.Actions
public class RegistryValueAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string KeyName { get; set; }


+ 187
- 28
TrustedUninstaller.Shared/Actions/RunAction.cs View File

@ -2,14 +2,59 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Documents;
using TrustedUninstaller.Shared.Tasks;
using YamlDotNet.Serialization;
namespace TrustedUninstaller.Shared.Actions
{
public enum Privilege
{
TrustedInstaller,
System,
CurrentUserElevated,
CurrentUser,
}
public class RunAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (RawPath != null) RawPath = Environment.ExpandEnvironmentVariables(RawPath);
InProgress = true;
if (Arguments == null) Console.WriteLine($"Running '{Exe}'...");
else Console.WriteLine($"Running '{Exe}' with arguments '{Arguments}'...");
WinUtil.CheckKph();
var currentDir = Directory.GetCurrentDirectory();
if (ExeDir) RawPath = AmeliorationUtil.Playbook.Path + "\\Executables";
if (BaseDir) RawPath = currentDir;
string file = null;
if (RawPath != null && File.Exists(Path.Combine(Environment.ExpandEnvironmentVariables(RawPath), Exe)))
file = Path.Combine(Environment.ExpandEnvironmentVariables(RawPath), Exe);
else if (ExistsInPath(Exe) || File.Exists(Environment.ExpandEnvironmentVariables(Exe)))
file = Environment.ExpandEnvironmentVariables(Exe);
if (file == null)
throw new FileNotFoundException($"Executable not found.");
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess(file);
else
RunAsPrivilegedProcess(file);
InProgress = false;
return;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "path")]
public string RawPath { get; set; } = null;
@ -80,28 +125,13 @@ namespace TrustedUninstaller.Shared.Actions
return HasExited || !Wait ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (RawPath != null) RawPath = Environment.ExpandEnvironmentVariables(RawPath);
InProgress = true;
if (Arguments == null) Console.WriteLine($"Running '{Exe}'...");
else Console.WriteLine($"Running '{Exe}' with arguments '{Arguments}'...");
var currentDir = Directory.GetCurrentDirectory();
if (ExeDir) RawPath = AmeliorationUtil.Playbook.Path + "\\Executables";
if (BaseDir) RawPath = currentDir;
string file = null;
if (RawPath != null && File.Exists(Path.Combine(RawPath, Exe)))
file = Path.Combine(RawPath, Exe);
else if (ExistsInPath(Exe) || File.Exists(Environment.ExpandEnvironmentVariables(Exe)))
file = Exe;
if (file == null)
throw new FileNotFoundException($"Executable not found.");
return null;
}
private void RunAsProcess(string file)
{
var startInfo = new ProcessStartInfo
{
CreateNoWindow = !this.CreateWindow,
@ -138,7 +168,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
exeProcess.Dispose();
return true;
return;
}
if (ShowOutput)
@ -165,15 +195,24 @@ namespace TrustedUninstaller.Shared.Actions
bool exited = exeProcess.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(exeProcess))
while (!exited && ExeRunning(exeProcess.ProcessName, exeProcess.Id))
{
exited = exeProcess.WaitForExit(30000);
}
}
if (exeProcess.ExitCode != 0)
int exitCode = 0;
try
{
exitCode = exeProcess.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "RunAction Error", Exe + " " + Arguments);
}
if (exitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exitCode, null, "RunAction Error", Exe + " " + Arguments);
}
HasExited = true;
@ -182,15 +221,116 @@ namespace TrustedUninstaller.Shared.Actions
exeProcess.CancelOutputRead();
if (ShowError)
exeProcess.CancelErrorRead();
}
private void RunAsPrivilegedProcess(string file)
{
var startInfo = new AugmentedProcess.ProcessStartInfo
{
CreateNoWindow = !this.CreateWindow,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Normal,
RedirectStandardError = true,
RedirectStandardOutput = true,
FileName = file,
};
if (Arguments != null) startInfo.Arguments = Arguments;
InProgress = false;
return true;
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
if (!ShowOutput)
startInfo.RedirectStandardOutput = false;
if (!ShowError)
startInfo.RedirectStandardError = false;
var exeProcess = new AugmentedProcess.Process
{
StartInfo = startInfo,
EnableRaisingEvents = true
};
ProcessPrivilege.StartPrivilegedTask(exeProcess, RunAs);
if (!Wait)
{
exeProcess.Dispose();
return;
}
if (ShowOutput)
exeProcess.OutputDataReceived += PrivilegedProcOutputHandler;
if (ShowError)
exeProcess.ErrorDataReceived += PrivilegedProcOutputHandler;
if (ShowOutput)
exeProcess.BeginOutputReadLine();
if (ShowError)
exeProcess.BeginErrorReadLine();
if (Timeout.HasValue)
{
var exited = exeProcess.WaitForExit(Timeout.Value);
if (!exited)
{
exeProcess.Kill();
throw new TimeoutException($"Executable run timeout exceeded.");
}
}
else
{
bool exited = exeProcess.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(exeProcess.ProcessName, exeProcess.Id))
{
exited = exeProcess.WaitForExit(30000);
}
}
try
{
if (exeProcess.ExitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
}
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "RunAction Error", Exe + " " + Arguments);
Thread.Sleep(500);
try
{
if (exeProcess.ExitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
}
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (2)", null, "RunAction Error", Exe + " " + Arguments);
}
}
HasExited = true;
if (ShowOutput)
exeProcess.CancelOutputRead();
if (ShowError)
exeProcess.CancelErrorRead();
}
private static bool ExeRunning(Process process)
private static bool ExeRunning(string name, int id)
{
try
{
return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
return Process.GetProcessesByName(name).Any(x => x.Id == id);
}
catch (Exception)
{
@ -198,6 +338,25 @@ namespace TrustedUninstaller.Shared.Actions
}
}
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
var outputString = outLine.Data;
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
Output += outputString + Environment.NewLine;
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
// Collect the sort command output.


+ 1
- 0
TrustedUninstaller.Shared/Actions/ScheduledTaskAction.cs View File

@ -21,6 +21,7 @@ namespace TrustedUninstaller.Shared.Actions
internal class ScheduledTaskAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(ScheduledTaskOperation), Alias = "operation")]
public ScheduledTaskOperation Operation { get; set; } = ScheduledTaskOperation.Delete;
[YamlMember(Alias = "data")]


+ 80
- 56
TrustedUninstaller.Shared/Actions/ServiceAction.cs View File

@ -1,5 +1,7 @@
#nullable enable
using System;
using System.Collections.Specialized;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -7,6 +9,7 @@ using System.Management;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Win32;
using TrustedUninstaller.Shared.Exceptions;
using TrustedUninstaller.Shared.Tasks;
@ -25,6 +28,7 @@ namespace TrustedUninstaller.Shared.Actions
}
internal class ServiceAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(ServiceOperation), Alias = "operation")]
public ServiceOperation Operation { get; set; } = ServiceOperation.Delete;
@ -94,7 +98,7 @@ namespace TrustedUninstaller.Shared.Actions
return (int)value == Startup.Value ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
}
ServiceController serviceController;
ServiceController? serviceController;
if (Device) serviceController = GetDevice();
else serviceController = GetService();
@ -129,12 +133,10 @@ namespace TrustedUninstaller.Shared.Actions
|| serviceController?.Status == ServiceControllerStatus.PausePending ?
UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo,
ServiceOperation.Delete =>
serviceController == null ?
serviceController == null || Win32.ServiceEx.IsPendingDeleteOrDeleted(serviceController.ServiceName) ?
UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo,
_ => throw new ArgumentOutOfRangeException("Argument out of Range", new ArgumentOutOfRangeException())
};
}
private readonly string[] RegexNoKill = { "DcomLaunch" };
@ -191,44 +193,46 @@ namespace TrustedUninstaller.Shared.Actions
foreach (ServiceController dependentService in service.DependentServices)
{
Console.WriteLine($"Killing dependent service {dependentService.ServiceName}...");
try
{
dependentService.Stop();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service stop failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop" :
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
Console.WriteLine("Waiting for the service to stop...");
int delay = 100;
while (service.Status != ServiceControllerStatus.Stopped && delay <= 1000)
while (dependentService.Status != ServiceControllerStatus.Stopped && delay <= 1000)
{
service.Refresh();
dependentService.Refresh();
//Wait for the service to stop
Task.Delay(delay).Wait();
delay += 100;
}
if (delay >= 1000)
{
Console.WriteLine("\r\nService stop timeout exceeded. Trying second method...");
try
{
using var search = new ManagementObjectSearcher($"SELECT * FROM Win32_Service WHERE Name='{service.ServiceName}'");
foreach (ManagementObject queryObj in search.Get())
{
var serviceId = (UInt32)queryObj["ProcessId"]; // Access service name
var killServ = new TaskKillAction()
{
ProcessID = (int)serviceId
};
await killServ.RunTask();
}
}
catch (Exception e)
Console.WriteLine("\r\nService stop timeout exceeded.");
}
try
{
var killServ = new TaskKillAction()
{
ErrorLogger.WriteToErrorLog($"Could not kill dependent service {dependentService.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
ProcessID = Win32.ServiceEx.GetServiceProcessId(dependentService.ServiceName)
};
await killServ.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog($"Could not kill dependent service {dependentService.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
}
@ -243,11 +247,19 @@ namespace TrustedUninstaller.Shared.Actions
if (DeleteStop && service.Status != ServiceControllerStatus.StopPending && service.Status != ServiceControllerStatus.Stopped)
{
try
{
service.Stop();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service stop failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop" :
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
Console.WriteLine("Waiting for the service to stop...");
@ -259,30 +271,21 @@ namespace TrustedUninstaller.Shared.Actions
await Task.Delay(delay);
delay += 100;
}
if (delay >= 1500)
if (delay >= 1000)
{
Console.WriteLine("\r\nService stop timeout exceeded. Trying second method...");
try
{
using var search = new ManagementObjectSearcher($"SELECT * FROM Win32_Service WHERE Name='{service.ServiceName}'");
foreach (ManagementObject queryObj in search.Get())
{
var serviceId = (UInt32)queryObj["ProcessId"]; // Access service name
var killServ = new TaskKillAction()
{
ProcessID = (int)serviceId
};
await killServ.RunTask();
}
}
catch (Exception e)
Console.WriteLine("\r\nService stop timeout exceeded.");
}
try
{
var killServ = new TaskKillAction()
{
ErrorLogger.WriteToErrorLog($"Could not kill service {service.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
ProcessID = Win32.ServiceEx.GetServiceProcessId(service.ServiceName)
};
await killServ.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog($"Could not kill service {service.ServiceName}.", e.StackTrace, "ServiceAction Error");
}
if (RegistryDelete)
@ -296,18 +299,39 @@ namespace TrustedUninstaller.Shared.Actions
}
else
{
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = service.ServiceName;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction delete";