Как получить путь к *.exe службы Windows через ServiceController

308
06 апреля 2019, 09:30

В системе имеется установленная служба. Управление ею из другого приложения осуществляется через ServiceController:

private ServiceController ctrl;
// ...
if (ctrl != null) ctrl.Dispose();
ctrl = new ServiceController(AutoCalcServiceConsts.ServiceName);  // имя сервиса, но не путь к файлу
if (ctrl.Status.In(ServiceControllerStatus.Running, ServiceControllerStatus.StartPending))
    status = Statuses.Running;
else
    if (ctrl.Status.In(ServiceControllerStatus.Stopped, ServiceControllerStatus.StopPending))
        status = Statuses.Stopped;

Каким образом можно получить путь к *.exe-шнику службы (это нужно не для запуска "напрямую", а для получения доступа к его конфигу) ?

Answer 1

Вот тут советуют через WMI:

using System.Management;
string ServiceName = "YourServiceName";
using (ManagementObject wmiService = new ManagementObject("Win32_Service.Name='"+ ServiceName +"'"))
                {
                    wmiService.Get();
                    string currentserviceExePath = wmiService["PathName"].ToString();
                    Console.WriteLine(wmiService["PathName"].ToString());
                }

Еще есть вариант через реестр:

RegistryKey services = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services"); 
if (services != null) 
{ 
object pathtoexecutable = services.OpenSubKey(<<ServiceName>>).GetValue("ImagePath"); 
} 

Вот тут готовая реализация класса наследника, от ServiceController, с реализацией метода через реестр:

public class ServiceController : System.ServiceProcess.ServiceController
{
    private string m_ImagePath;
    private ServiceController[] m_DependentServices;
    private ServiceController[] m_ServicesDependedOn;
    public ServiceController()
        : base()
    {
    }
    public ServiceController( string name )
        : base( name )
    {
    }
    public ServiceController( string name, string machineName )
        : base( name, machineName )
    {
    }
    public string ImagePath
    {
        get
        {
            if( m_ImagePath == null )
            {
                m_ImagePath = GetImagePath();
            }
            return m_ImagePath;
        }
    }
    public new ServiceController[] DependentServices
    {
        get
        {
            if( m_DependentServices == null )
            {
                m_DependentServices = 
                     ServiceController.GetServices( base.DependentServices );
            }
            return m_DependentServices;
        }
    }
    public new ServiceController[] ServicesDependedOn
    {
        get
        {
            if( m_ServicesDependedOn == null )
            {
                m_ServicesDependedOn = 
                      ServiceController.GetServices( base.ServicesDependedOn );
            }
            return m_ServicesDependedOn;
        }
    }
    public static new ServiceController[] GetServices()
    {
        return GetServices( "." );
    }
    public static new ServiceController[] GetServices( string machineName )
    {
        return GetServices( System.ServiceProcess.ServiceController.GetServices
            ( machineName ) );
    }
    private string GetImagePath()
    {
        string registryPath = @"SYSTEM\CurrentControlSet\Services\" + ServiceName;
        RegistryKey keyHKLM = Registry.LocalMachine;
        RegistryKey key;
        if( MachineName != "" )
        {
            key = RegistryKey.OpenRemoteBaseKey
              ( RegistryHive.LocalMachine, this.MachineName ).OpenSubKey( registryPath );
        }
        else
        {
            key = keyHKLM.OpenSubKey( registryPath );
        }
        string value = key.GetValue( "ImagePath" ).ToString();
        key.Close();
        return ExpandEnvironmentVariables( value );
        //return value;
    }
    private string ExpandEnvironmentVariables( string path )
    {
        if( MachineName == "" )
        {
            return Environment.ExpandEnvironmentVariables( path );
        }
        else
        {
            string systemRootKey = @"Software\Microsoft\Windows NT\CurrentVersion\";
            RegistryKey key = RegistryKey.OpenRemoteBaseKey
                 ( RegistryHive.LocalMachine, MachineName ).OpenSubKey( systemRootKey );
            string expandedSystemRoot = key.GetValue( "SystemRoot" ).ToString();
            key.Close();
            path = path.Replace( "%SystemRoot%", expandedSystemRoot );
            return path;
        }
    }
    private static ServiceController[] GetServices
         ( System.ServiceProcess.ServiceController[] systemServices )
    {
        List<ServiceController> services = new List<ServiceController>
            ( systemServices.Length );
        foreach( System.ServiceProcess.ServiceController service in systemServices )
        {
            services.Add( new ServiceController
                ( service.ServiceName, service.MachineName ) );
        }
        return services.ToArray();
    }
}

Как альтернативу наследнику, можно сделать метод расширения.

READ ALSO
прекращение работы Microsoft visual studio 2017

прекращение работы Microsoft visual studio 2017

При попытке обновить таблицу в бд в microsoft visual studio 2017 вылетает из программы, после захода в программу созданная таблица исчезает (скорее всего...

165
Помогите с кодом для DFS с рекурсией

Помогите с кодом для DFS с рекурсией

Помогите с кодом на C# для рекурсивного поиска пути в графе

149
Gif изображение в Android Xamarin

Gif изображение в Android Xamarin

Есть метод для появления Gif

177