我使用下面的代碼來獲取 Windows 服務的串列。它適用于 Delphi 10.2.3 及更早版本:
uses WinSvc;
//-------------------------------------
// Get a list of services
//
// return TRUE if successful
//
// sMachine:
// machine name, ie: \SERVER
// empty = local machine
//
// dwServiceType
// SERVICE_WIN32,
// SERVICE_DRIVER or
// SERVICE_TYPE_ALL
//
// dwServiceState
// SERVICE_ACTIVE,
// SERVICE_INACTIVE or
// SERVICE_STATE_ALL
//
// slServicesList
// TStrings variable to storage
//
function ServiceGetList(
sMachine : string;
dwServiceType,
dwServiceState : DWord;
slServicesList : TStrings )
: boolean;
const
//
// assume that the total number of
// services is less than 4096.
// increase if necessary
cnMaxServices = 4096;
type
TSvcA = array[0..cnMaxServices]
of TEnumServiceStatus;
PSvcA = ^TSvcA;
var
//
// temp. use
j : integer;
//
// service control
// manager handle
schm : SC_Handle;
//
// bytes needed for the
// next buffer, if any
nBytesNeeded,
//
// number of services
nServices,
//
// pointer to the
// next unread service entry
nResumeHandle : DWord;
//
// service status array
ssa : PSvcA;
begin
Result := false;
// connect to the service
// control manager
schm := OpenSCManager(
PChar(sMachine),
Nil,
SC_MANAGER_ALL_ACCESS);
// if successful...
if(schm > 0)then
begin
nResumeHandle := 0;
New(ssa);
EnumServicesStatus(
schm,
dwServiceType,
dwServiceState,
ssa^[0],
SizeOf(ssa^),
nBytesNeeded,
nServices,
nResumeHandle );
//
// assume that our initial array
// was large enough to hold all
// entries. add code to enumerate
// if necessary.
//
for j := 0 to nServices-1 do
begin
slServicesList.
Add( StrPas(
ssa^[j].lpDisplayName ) );
end;
Result := true;
Dispose(ssa);
// close service control
// manager handle
CloseServiceHandle(schm);
end;
end;
要將所有 Windows 服務的串列放入名為的 ListBox 中ListBox1:
ServiceGetList( '',
SERVICE_WIN32,
SERVICE_STATE_ALL,
ListBox1.Items );
我嘗試在Delphi 10.4和Delphi 11中使用相同的代碼,但是EnumServicesStatus函式存在問題:
[dcc32 錯誤] Unit1.pas(145):E2010 不兼容的型別:“LPENUM_SERVICE_STATUSW”和“_ENUM_SERVICE_STATUSW”
當我嘗試LPENUM_SERVICE_STATUSW改為TEnumServiceStatus:
type
TSvcA = array[0..cnMaxServices]
of LPENUM_SERVICE_STATUSW;// instead TEnumServiceStatus;
我收到“訪問沖突”錯誤。
也許重點在于Winapi.WinSvc.pas:
function EnumServicesStatus; external advapi32 name 'EnumServicesStatusW';
uj5u.com熱心網友回復:
預先分配這么大的陣列并不是一個好主意。您無法假設 PC 實際安裝了多少服務。讓我們EnumServicesStatus()告訴您為陣列分配多少。
此外,您必須考慮可能需要EnumServicesStatus()多次呼叫才能獲得所有狀態的可能性。
現在,關于編譯器問題 - 實際的EnumServiceStatus()API 需要一個指向記錄陣列的指標(在單元中ENUM_SERVICE_STATUS別名),而不是指標陣列。在早期版本的 Delphi 中,該單元宣告參考陣列中的第一個。但顯然它已經被重新宣告為取一個指向 1st 的指標,以匹配實際的 API。TEnumServiceStatusWinSvcLPENUM_SERVICE_STATUSWinsvcEnumServiceStatusW()varENUM_SERVICE_STATUSENUM_SERVICE_STATUS
因此,話雖如此,請嘗試更多類似的東西:
uses
WinSvc;
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 34}
{$DEFINE lpServices_Param_Is_Pointer}
{$IFEND}
{$ENDIF}
function ServiceGetList(
const sMachine : string;
dwServiceType,
dwServiceState : DWord;
slServicesList : TStrings )
: Boolean;
var
j : integer;
schm : SC_Handle;
nBytesNeeded,
nServices,
nResumeHandle : DWord;
buffer : array of Byte;
ssa, ss : PEnumServiceStatus;
begin
Result := False;
schm := OpenSCManager(
PChar(sMachine),
nil,
SC_MANAGER_CONNECT or SC_MANAGER_ENUMERATE_SERVICE);
if (schm <> 0) then
try
nResumeHandle := 0;
if not EnumServicesStatus(
schm,
dwServiceType,
dwServiceState,
{$IFDEF lpServices_Param_Is_Pointer}nil{$ELSE}PEnumServiceStatus(nil)^{$ENDIF},
0,
nBytesNeeded,
nServices,
nResumeHandle) then
begin
if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) and (GetLastError() <> ERROR_MORE_DATA) then
begin
Exit;
end;
SetLength(buffer, nBytesNeeded);
ssa := PEnumServiceStatus(buffer);
if not EnumServicesStatus(
schm,
dwServiceType,
dwServiceState,
ssa{$IFNDEF lpServices_Param_Is_Pointer}^{$ENDIF},
Length(buffer),
nBytesNeeded,
nServices,
nResumeHandle) then
begin
Exit;
end;
end;
if (nServices > 0) then
begin
ss := ssa;
for j := 0 to nServices-1 do
begin
slServicesList.Add(ss.lpDisplayName);
Inc(ss);
end;
end;
finally
CloseServiceHandle(schm);
end;
Result := True;
end;
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/495039.html
標籤:德尔福
上一篇:具有自定義樣式的Delphi專案
下一篇:將程序分配給動態創建的物件
