Как я могу найти идентификатор процесса из названия / дескриптора службы в Delphi? - PullRequest
4 голосов
/ 22 января 2009

У меня есть имя службы для службы Windows в Delphi, и я знаю, как получить ручку от этого. Что мне нужно сделать, это остановить службу, и если по какой-то причине остановка не удалась, мне нужно завершить процесс, связанный с этой службой. Проблема в том, что у меня несколько служб, запущенных из одного исполняемого файла, поэтому я не могу использовать имя исполняемого файла, чтобы завершить процесс. Это означает, что мне нужен идентификатор процесса, чтобы убить соответствующий связанный процесс. Как я могу получить этот идентификатор или каким-либо способом убить правильный процесс из имени службы или дескриптора?

Ответы [ 3 ]

8 голосов
/ 22 января 2009
6 голосов
/ 22 января 2009

Обратите внимание, что я принял это решение только для того, чтобы было принято решение с полным кодом Delphi, все благодаря Jk, хотя и указал мне правильный путь.

-

Хорошо, я смог понять, как использовать ответ от Jk, и придумал это решение в Delphi.

Для справки, это ссылка, предоставленная Jk:

QueryServiceStatusEx

Мое решение:

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.

Обратите внимание, что не все внешние наименования и другие предметы первой необходимости включены.

1 голос
/ 23 января 2009

Или используйте DSiWin32 для многих полезных функций , включая DSiGetProcessID. Этот код был написан пользователем StackOverflow (и программистом) Gabr.

Вот эта функция, для вашей справки. Это даст вам то, что вы ищете:

//Retrieves ID of the specified process. Requires Toolhelp API.
//  @returns False if ID cannot be retrieved. Check GetLastError - if it is 0, process
//       doesn't exist; otherwise it contains the Win32 error code.
//  @author  gabr
//  @since   2004-02-12
//
  function DSiGetProcessID(const processName: string; var processID: DWORD): boolean;
  var
    hSnapshot: THandle;
    procEntry: TProcessEntry32;
  begin
    Result := false;
    hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if hSnapshot = 0 then
      Exit;
    try
      procEntry.dwSize := Sizeof(procEntry);
      if not Process32First(hSnapshot, procEntry) then
        Exit;
      repeat
        if AnsiSameText(procEntry.szExeFile, processName) then begin
          processID := procEntry.th32ProcessID;
          Result := true;
          break; // repeat
        end;
      until not Process32Next(hSnapshot, procEntry);
    finally DSiCloseHandleAndNull(hSnapshot); end;
  end; { DSiGetProcessID }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...