2009-01-22 71 views
4

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

回答

6

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

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

8
+0

你是不是可能有足夠的權限來殺死服務流程... – Arkadiy 2009-01-22 15:33:24

+0

這似乎並不成爲德爾福的解決方案,我不真的在尋找另一種語言的解決方案,我將不得不接受這個解決方案。 @Arkadiy - 殺死進程並不是一個大問題,目前的系統是這樣做的,但是在運行多個進程的時候並沒有區分 – 2009-01-22 15:39:12

0

Or use DSiWin32 for many useful functions,包括DSiGetProcessID。此代碼是由StackOverflow user (and programmer) 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 } 
相關問題