我用下面的代码得到了一个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服务的列表放入名为ListBox1
的ListBox中,请执行以下操作:
ServiceGetList( '',
SERVICE_WIN32,
SERVICE_STATE_ALL,
ListBox1.Items );
我尝试在 Delphi 10.4和Delphi 11中使用相同的代码,但是EnumServicesStatus
函数有一个问题:
[dcc32错误]单元1.pas(145):E2010不兼容的类型:'LPENUM服务状态'和'枚举服务状态'
当我尝试使用LPENUM_SERVICE_STATUSW
而不是TEnumServiceStatus
时:
type
TSvcA = array[0..cnMaxServices]
of LPENUM_SERVICE_STATUSW;// instead TEnumServiceStatus;
出现“访问冲突”错误。
也许关键点在Winapi.WinSvc.pas
中的外部函数中:
function EnumServicesStatus; external advapi32 name 'EnumServicesStatusW';
1条答案
按热度按时间ffdz8vbo1#
预先分配这么大的数组并不是一个好主意。你不能假设PC实际上安装了多少服务。让
EnumServicesStatus()
告诉你为数组分配多少服务。此外,您还必须考虑到可能需要多次调用
EnumServicesStatus()
才能获得所有状态。现在,关于编译器问题-实际的
EnumServiceStatus()
API需要指向ENUM_SERVICE_STATUS
记录数组的指针(在WinSvc
单位中别名为TEnumServiceStatus
),而不是LPENUM_SERVICE_STATUS
指针数组。在早期版本的 Delphi 中,Winsvc
单元声明了EnumServiceStatusW()
,以获取对数组中第一个ENUM_SERVICE_STATUS
的var
引用。但显然,它后来被重新声明为获取指向第一个ENUM_SERVICE_STATUS
的指针,以匹配实际API。所以,说了这么多,试着像这样: