簡體   English   中英

如何從Delphi中的服務名稱/句柄中找到進程ID?

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

我在delphi中有一個Windows服務的服務名稱,我也知道如何從中獲取句柄。 我需要做的是停止服務,如果由於某種原因停止失敗,我需要終止與服務相關的進程。 問題是我有多個服務從同一個可執行文件運行,所以我不能使用可執行文件名來終止進程。 這意味着我需要進程ID來終止正確的關聯進程。 如何從服務名稱或句柄中獲取此id或某種方式來終止正確的進程?

請注意我只接受了這個解決方案,以便接受完整的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.

請注意,並非包括所有外部命名和其他必需品。

或者將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 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM