@ -17,7 +17,7 @@ using YamlDotNet.Serialization;
namespace TrustedUninstaller.Shared.Actions
{
internal enum ServiceOperation
public enum ServiceOperation
{
Stop ,
Continue ,
@ -26,7 +26,7 @@ namespace TrustedUninstaller.Shared.Actions
Delete ,
Change
}
internal class ServiceAction : TaskAction , ITaskAction
public class ServiceAction : TaskAction , ITaskAction
{
public void RunTaskOnMainThread ( ) { throw new NotImplementedException ( ) ; }
[YamlMember(typeof(ServiceOperation), Alias = "operation")]
@ -175,6 +175,9 @@ namespace TrustedUninstaller.Shared.Actions
{
Console . WriteLine ( $"No services found matching '{ServiceName}'." ) ;
//ErrorLogger.WriteToErrorLog($"The service matching '{ServiceName}' does not exist.", Environment.StackTrace, "ServiceAction Error");
if ( Operation = = ServiceOperation . Start )
throw new ArgumentException ( "Service " + ServiceName + " not found." ) ;
return false ;
}
@ -182,98 +185,207 @@ namespace TrustedUninstaller.Shared.Actions
var cmdAction = new CmdAction ( ) ;
if ( Operation = = ServiceOperation . Delete | | Operation = = ServiceOperation . Stop )
if ( ( Operation = = ServiceOperation . Delete & & DeleteStop ) | | Operation = = ServiceOperation . Stop )
{
if ( RegexNoKill . Any ( regex = > Regex . Match ( ServiceName , regex , RegexOptions . IgnoreCase ) . Success ) )
{
Console . WriteLine ( $"Skipping {ServiceName}..." ) ;
return false ;
}
foreach ( ServiceController dependentService in service . DependentServices )
try
{
foreach ( ServiceController dependentService in service . DependentServices . Where ( x = > x . Status ! = ServiceControllerStatus . Stopped ) )
{
Console . WriteLine ( $"Killing dependent service {dependentService.ServiceName}..." ) ;
if ( dependentService . Status ! = ServiceControllerStatus . StopPending & & dependentService . Status ! = ServiceControllerStatus . Stopped )
{
try
{
dependentService . Stop ( ) ;
}
catch ( Exception e )
{
dependentService . Refresh ( ) ;
if ( dependentService . Status ! = ServiceControllerStatus . Stopped & & dependentService . Status ! = ServiceControllerStatus . StopPending )
ErrorLogger . WriteToErrorLog ( "Dependent service stop failed: " + e . Message , e . StackTrace , "ServiceAction Warning" , dependentService . ServiceName ) ;
}
cmdAction . Command = Environment . Is64BitOperatingSystem ?
$"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" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
}
Console . WriteLine ( "Waiting for the dependent service to stop..." ) ;
try
{
dependentService . WaitForStatus ( ServiceControllerStatus . Stopped , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
catch ( Exception e )
{
dependentService . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( "Dependent service stop timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
try
{
var killServ = new TaskKillAction ( )
{
ProcessID = Win32 . ServiceEx . GetServiceProcessId ( dependentService . ServiceName )
} ;
await killServ . RunTask ( ) ;
}
catch ( Exception e )
{
dependentService . Refresh ( ) ;
if ( dependentService . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( $"Could not kill dependent service {dependentService.ServiceName}." ,
e . StackTrace , "ServiceAction Error" , ServiceName ) ;
}
}
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( $"Error killing dependent services: " + e . Message ,
e . StackTrace , "ServiceAction Error" , ServiceName ) ;
}
}
if ( Operation = = ServiceOperation . Delete )
{
if ( DeleteStop & & service . Status ! = ServiceControllerStatus . StopPending & & service . Status ! = ServiceControllerStatus . Stopped )
{
Console . WriteLine ( $"Killing dependent service {dependentService.ServiceName}..." ) ;
try
{
dependentService . Stop ( ) ;
s ervice. Stop ( ) ;
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( "Service stop failed: " + e . Message , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped & & service . Status ! = ServiceControllerStatus . StopPending )
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\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop" ;
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {s ervice.ServiceName} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {s ervice.ServiceName} -caction stop" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
Console . WriteLine ( "Waiting for the service to stop..." ) ;
int delay = 1 0 0 ;
while ( dependentService . Status ! = ServiceControllerStatus . Stopped & & delay < = 1 0 0 0 )
try
{
dependentService . Refresh ( ) ;
//Wait for the service to stop
Task . Delay ( delay ) . Wait ( ) ;
delay + = 1 0 0 ;
service . WaitForStatus ( ServiceControllerStatus . Stopped , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
if ( delay > = 1 0 0 0 )
catch ( Exception e )
{
Console . WriteLine ( "\r\nService stop timeout exceeded." ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( "Service stop timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
try
{
var killServ = new TaskKillAction ( )
{
ProcessID = Win32 . ServiceEx . GetServiceProcessId ( dependentService . ServiceName )
ProcessID = Win32 . ServiceEx . GetServiceProcessId ( s ervice. ServiceName )
} ;
await killServ . RunTask ( ) ;
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( $"Could not kill dependent service {dependentService.ServiceName}." ,
e . StackTrace , "ServiceAction Error" ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( $"Could not kill service {service.ServiceName}." , e . StackTrace , "ServiceAction Error" ) ;
}
}
if ( service . ServiceName = = "SgrmAgent" & & ( ( Operation = = ServiceOperation . Delete & & DeleteStop ) | | Operation = = ServiceOperation . Stop ) )
if ( RegistryDelete )
{
await new TaskKillAction ( ) { ProcessName = "SgrmBroker" } . RunTask ( ) ;
var action = new RegistryKeyAction ( )
{
KeyName = $@"HKLM\SYSTEM\CurrentControlSet\Services\{ServiceName}" ,
Operation = RegistryKeyOperation . Delete
} ;
await action . RunTask ( ) ;
}
}
if ( Operation = = ServiceOperation . Delete )
{
if ( DeleteStop & & service . Status ! = ServiceControllerStatus . StopPending & & service . Status ! = ServiceControllerStatus . Stopped )
else
{
try
{
service . Stop ( ) ;
ServiceInstaller ServiceInstallerObj = new ServiceInstaller ( ) ;
ServiceInstallerObj . Context = new InstallContext ( ) ;
ServiceInstallerObj . ServiceName = service . ServiceName ;
ServiceInstallerObj . Uninstall ( null ) ;
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( "Service stop failed: " + e . Message , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
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 stop" :
$"ProcessHacker\\x86\\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 delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction delete " ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
}
Console . WriteLine ( "Waiting for the service to stop..." ) ;
int delay = 1 0 0 ;
while ( DeleteStop & & service . Status ! = ServiceControllerStatus . Stopped & & delay < = 1 5 0 0 )
} else if ( Operation = = ServiceOperation . Start )
{
try
{
service . Start ( ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Running )
ErrorLogger . WriteToErrorLog ( "Service start 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 start" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction start" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
try
{
service . WaitForStatus ( ServiceControllerStatus . Running , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
//Wait for the service to stop
await Task . Delay ( delay ) ;
delay + = 1 0 0 ;
if ( service . Status ! = ServiceControllerStatus . Running )
ErrorLogger . WriteToErrorLog ( "Service start timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
if ( delay > = 1 0 0 0 )
} else if ( Operation = = ServiceOperation . Stop )
{
try
{
Console . WriteLine ( "\r\nService stop timeout exceeded." ) ;
service . Stop ( ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped & & service . Status ! = ServiceControllerStatus . StopPending )
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\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
Console . WriteLine ( "Waiting for the service to stop..." ) ;
try
{
service . WaitForStatus ( ServiceControllerStatus . Stopped , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( "Service stop timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
try
{
@ -285,53 +397,68 @@ namespace TrustedUninstaller.Shared.Actions
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( $"Could not kill service {service.ServiceName}." , e . StackTrace , "ServiceAction Error" ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Stopped )
ErrorLogger . WriteToErrorLog ( $"Could not kill dependent service {service.ServiceName}." ,
e . StackTrace , "ServiceAction Error" ) ;
}
if ( RegistryDelete )
} else if ( Operation = = ServiceOperation . Pause )
{
try
{
var action = new RegistryKeyAction ( )
{
KeyName = $@"HKLM\SYSTEM\CurrentControlSet\Services\{ServiceName}" ,
Operation = RegistryKeyOperation . Delete
} ;
await action . RunTask ( ) ;
service . Pause ( ) ;
}
else
catch ( Exception e )
{
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" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Paused )
ErrorLogger . WriteToErrorLog ( "Service pause 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 pause" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction pause" ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
try
{
service . WaitForStatus ( ServiceControllerStatus . Paused , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Paused )
ErrorLogger . WriteToErrorLog ( "Service pause timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
}
else
else if ( Operation = = ServiceOperation . Continue )
{
try
{
service . Stop ( ) ;
service . Pause ( ) ;
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( "Service stop failed: " + e . Message , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Running )
ErrorLogger . WriteToErrorLog ( "Service continue 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 {Operation.ToString().ToLower()}" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction {Operation.ToString().ToLower()}" ;
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction continue " :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction continue " ;
if ( AmeliorationUtil . UseKernelDriver ) cmdAction . RunTaskOnMainThread ( ) ;
try
{
service . WaitForStatus ( ServiceControllerStatus . Running , TimeSpan . FromMilliseconds ( 5 0 0 0 ) ) ;
}
catch ( Exception e )
{
service . Refresh ( ) ;
if ( service . Status ! = ServiceControllerStatus . Running )
ErrorLogger . WriteToErrorLog ( "Service continue timeout exceeded." , e . StackTrace , "ServiceAction Warning" , ServiceName ) ;
}
}
service ? . Dispose ( ) ;