【问题标题】:Get service name from the path of its executable从其可执行文件的路径获取服务名称
【发布时间】:2016-12-21 14:03:45
【问题描述】:

我有一个可执行文件的路径,它是一个正在运行的服务应用程序。

例如:C:\Program Files (x86)\Someapp\somesvc.exe

我想停止并启动它,为此我想我需要获取[this] 答案中概述的服务名称。

我可以通过遍历HKLM\System\CurrentControlSet\Services 处所有服务的所有注册表项并检查ImagePath 注册表项是否与我的可执行路径匹配来获得此信息。

这个解决方案应该可行,但对我来说似乎是错误的。有没有更好的方法来做到这一点?

【问题讨论】:

  • 为什么不用服务控制管理器API?
  • @DavidHeffernan 正如我在我的问题中所链接的那样,我将使用它,但它期望作为服务名称作为输入,而不是服务的路径,这是这里的主要问题.
  • 服务控制管理器了解所有服务及其所有详细信息。使用它来提取您需要的信息。我只是建议您使用官方 API 而不是破解注册表。当然,可以很容易地以相同的名称注册多个服务。
  • 并非所有服务都具有可执行文件。从 Vista 开始,它被认为是系统资源紧张,因此努力将这些可执行文件转换为共享服务
  • 让我们后退一步:您是如何在不知道其名称的情况下不得不重新启动服务的?也许你可以解决这个问题,让剩下的问题变得更容易。

标签: windows delphi


【解决方案1】:

使用EnumServicesStatus()EnumServicesStatusEx() 枚举已安装的服务。这将为您提供每个服务的名称,而不是其ImagePath。要检索它,您可以使用OpenService(SERVICE_QUERY_CONFIG) 打开每个服务,然后使用QueryServiceConfig() 获取其ImagePath

【讨论】:

  • 这是正确的解决方案,谢谢。不过,我需要进行大量研究,大多数关于这些功能的在线教程都不适用于新的 delphi 版本。
【解决方案2】:

您可以向 WMI 查询 PathName 类似于您的路径的服务。

注意:某些路径包含参数。你不能使用 equal(使用 Like)。

您可以使用类似这样的代码来查询 WMI:

//-----------------------------------------------------------------------------------------------------
//     This code was generated by the Wmi Delphi Code Creator (WDCC) Version 1.9.9.350
//     http://code.google.com/p/wmi-delphi-code-creator/
//     Blog http://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/
//     Author Rodrigo Ruz V. (RRUZ) Copyright (C) 2011-2015 
//----------------------------------------------------------------------------------------------------- 
//
//     LIABILITY DISCLAIMER
//     THIS GENERATED CODE IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.
//     YOU USE IT AT YOUR OWN RISK. THE AUTHOR NOT WILL BE LIABLE FOR DATA LOSS,
//     DAMAGES AND LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS CODE.
//
//----------------------------------------------------------------------------------------------------
program GetWMI_Info;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;



// La clase Win32_Service representa un servicio en un sistema Win32. Un 
// aplicación de servicio cumple las reglas de la interfaz del Administrador de 
// control de servicios (SCM, Service Control Manager) y un usuario la puede 
// iniciar automáticamente al arrancar el sistema a través del programa Servicios 
// del Panel de control o mediante una aplicación que utilice las funciones de 
// servicio de la API de Win32. Los servicios se pueden ejecutar aunque ningún 
// usuario haya iniciado sesión en el sistema.

procedure  GetWin32_ServiceInfo(sPath:String);
const
  WbemUser            ='';
  WbemPassword        ='';
  WbemComputer        ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_Service WHERE PathName like "%' + sPath + '%"','WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('Caption        %s',[String(FWbemObject.Caption)]));// String
    Writeln(Format('DisplayName    %s',[String(FWbemObject.DisplayName)]));// String
    Writeln(Format('Name           %s',[String(FWbemObject.Name)]));// String
    Writeln(Format('PathName       %s',[String(FWbemObject.PathName)]));// String

    Writeln('');
    FWbemObject:=Unassigned;
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_ServiceInfo(ExtractFileName('c:\windows\system\locator.exe'));
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode])); 
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;      
end.

如果您需要更多属性,请添加到 precedure。

查询:'c:\windows\system\locator.exe',获取:

查询:'C:\Program Files (x86)\Skype\Updater\Updater.exe',你得到:

对于启动停止服务,您需要property Name

【讨论】:

  • 我对此投了反对票,因为 WMI 是“邪恶的”IMO,它很慢并且有很多开销。 SCM API 可用于迭代服务和比较路径...msdn.microsoft.com/en-us/library/windows/desktop/…
  • @Remko。这是个人意见。对于一个问题,可能有几个有效的解决方案。对你来说是坏的,对另一个人来说可能是好的。我不理解反对票,因为解决方案不是您提出的解决方案或您喜欢的解决方案。
  • 这是一个非常糟糕的解决方案。 WMI 是不适合这项工作的工具。我也投反对票。
  • 因为 WMI 是一种真正适用于脚本的解决方案,而且速度非常慢,因此会给应用程序增加不必要的延迟。如果 WMI 是唯一的方法,那很好,但是从早期开始,Windows 中就有一个有据可查的 api,并且可以在 Delphi 中轻松访问。
  • 即使这是一个理想的解决方案,这段代码也没有错误检查。如果 WMI 没有运行(我以前见过)怎么办?如果用户没有足够的权限怎么办?如果请求的服务不存在怎么办?更进一步——如果同一个可执行文件产生了多个服务怎么办?是的,这是可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 2011-01-25
相关资源
最近更新 更多