type
// für selbstimportierte Funktion erforderlich
PENUM_SERVICE_STATUS = ^TEnumServiceStatus;
// Funktion selber importieren, da die Borland Version nur den ersten zugreifbar macht
function EnumServicesStatus(
const hSCManager : DWord;
// handle to SCM database
const dwServiceType : DWord;
// service type
const dwServiceState : DWord;
// service state
const lpServices : PENUM_SERVICE_STATUS;
// status buffer
const cbBufSize : DWord;
// size of status buffer
const pcbBytesNeeded : PDWORD;
// buffer size needed
const lpServicesReturned : PDWord;
// number of entries returned
const lpResumeHandle : PDWord
// next entry
) : Boolean;
stdcall;
external '
advapi32.dll'
name '
EnumServicesStatusA';
implementation
{$R *.DFM}
procedure EnumServices(
const AsComputerName :
string);
var
hSCDB : DWORD;
pStatus : PENUM_SERVICE_STATUS;
pWork : PENUM_SERVICE_STATUS;
cbBufSize : DWORD;
pcbBytesNeeded : DWORD;
lpServicesReturned : DWORD;
lpResumeHandle : DWORD;
iCount : integer;
begin
Form1.ListBox1.Items.Clear;
hSCDB := OpenSCManager(
PChar('
\\'+AsComputerName),
// Dienste des angegebenen Rechners auslesen
nil,
// Standarddatenbank nehmen
SC_MANAGER_ENUMERATE_SERVICE
// Dienste aufzählen (alle durchgehen)
or // ausserdem
GENERIC_READ);
// genügt es die Daten nur zu lesen
if hSCDB <> 0
then begin
try
// Erforderlichen Speicherplatz für alle Daten von der Funktion ermitteln lassen
// ==> gezielt mit 0 Byte Buffer fehlschlagen lassen
cbBufSize := 0;
pStatus :=
nil;
lpResumeHandle := 0;
EnumServicesStatus(hSCDB,SERVICE_WIN32,SERVICE_STATE_ALL,pStatus,cbBufSize,@pcbBytesNeeded,@lpServicesReturned,@lpResumeHandle);
lpResumeHandle := 0;
// speicher reservieren
pStatus := AllocMem(pcbBytesNeeded);
try
cbBufSize := pcbBytesNeeded;
EnumServicesStatus(
hSCDB,
// Handle von OpenSCManager
SERVICE_WIN32,
// Nur Dienste, keine Treiber
SERVICE_STATE_ALL,
// Alle installierten Dienste, egal ob sie laufen oder nicht
pStatus,cbBufSize,@pcbBytesNeeded,@lpServicesReturned,@lpResumeHandle);
// Adresse merken, damit der Speicher später wieder freigegeben werden kann, ohne den Pointer
// wieder zurückrechnen zu müssen
pWork := pStatus;
// Alle Dienste in Listbox anzeigen (mit Namen und Anzeigenamen)
for iCount := 1
to lpServicesReturned
do begin
Form1.ListBox1.Items.Add(pWork.lpServiceName+'
/'+pWork.lpDisplayName);
inc(pWork);
end;
finally
if Assigned(pStatus)
then FreeMem(pStatus,pcbBytesNeeded);
end;
finally
CloseServiceHandle(hSCDB);
end;
end;
end;