How can I find the process id from the service name/handle in Delphi?

后端 未结 3 1314
无人共我
无人共我 2021-02-10 14:24

I have the service name for a windows service in delphi, and I know how to get the handle from that as well. What I need to do is stop a service, and if the stop fails for some

3条回答
  •  耶瑟儿~
    2021-02-10 15:09

    Please note I have only accepted this solution so that a full delphi code solution is accepted, all due thanks to Jk though for pointing me on the correct path.

    --

    Ok, I've been able to figure out how to use the answer by Jk and have come up with this solution in delphi.

    For reference, this is the link provided by Jk:

    QueryServiceStatusEx

    My Solution:

    unit Demo;
    
    interface
    
    uses
      Windows, Forms, SysUtils,
      StdCtrls, WinSvc, Controls, Classes;
    
    type
    
      //Form for basic demo usage
      TForm6 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
      end;
    
      //Record defined for use as return buffer
      _SERVICE_STATUS_PROCESS = record
        dwServiceType: DWORD;
        dwCurrentState: DWORD;
        dwControlsAccepted: DWORD;
        dwWin32ExitCode: DWORD;
        dwServiceSpecificExitCode: DWORD;
        dwCheckPoint: DWORD;
        dwWaitHint: DWORD;
        dwProcessId: DWORD;
        dwServiceFlags: DWORD;
      end;
      //Function Prototype
      function QueryServiceStatusEx(
      SC_HANDLE: SC_Handle;
      SC_STATUS_TYPE: Cardinal;
      out lpBuffer: _SERVICE_STATUS_PROCESS;
      cbBufSize: DWORD;
      out pcbBytesNeeded: LPDWORD
      ): BOOL; stdcall;
    
    
      //internal setup function
      function GetPid(sService: String; sMachine: String = '') : Cardinal;
    var
      Form6: TForm6;
    
    implementation
    
    {$R *.dfm}
    const
      // windows api library
      advapi32 = 'advapi32.dll';
      //define the api call
      function QueryServiceStatusEx;   external advapi32 name 'QueryServiceStatusEx';
    
    //for demo usage
    procedure TForm6.Button1Click(Sender: TObject);
    begin
      Memo1.Lines.Add(IntToStr(Integer(GetPid('Service'))))
    end;
    
    
    function GetPid(sService: String; sMachine: String = '') : Cardinal;
    var
      schm,
      schs: SC_Handle;
      SC_STATUS_TYPE: Cardinal;
      lpBuffer: _SERVICE_STATUS_PROCESS;
      cbBufSize: DWORD;
      pcbBytesNeeded: LPDWORD;
    begin
      //open the service manager  (defined in WinSvc)
      schm := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_CONNECT);
      //set the status type to SC_STATUS_PROCESS_INFO
      //this is currently the only value supported
      SC_STATUS_TYPE := $00000000;
      //set the buffer size to the size of the record
      cbBufSize := sizeof(_SERVICE_STATUS_PROCESS);
      if (schm>0) then
      begin
        //grab the service handle
        schs := OpenService(schm, PChar(sService), SERVICE_QUERY_STATUS);
        if (schs>0) then
        begin
          //call the function
          QueryServiceStatusEx(
          schs,
          SC_STATUS_TYPE,
          lpBuffer,
          cbBufSize,
          pcbBytesNeeded);
          CloseServiceHandle(schs);
        end;
        CloseServiceHandle(schm);
      end;
      Result := lpBuffer.dwProcessId;
    end;
    
    
    
    end.
    

    Please note that not all external naming and other necessities are included.

提交回复
热议问题