有两种方法。
第一种:(此方法需要提升权限)
type
TGetProcessHandleCount = function (hProcess: THandle; var pdwHandleCount: DWORD): LongBool; stdcall;
var
_GetProcessHandleCount: TGetProcessHandleCount;
// 获取API地址, 建议放在 initialization 段中
_GetProcessHandleCount := GetProcAddress(GetModuleHandle(kernel32), 'GetProcessHandleCount');
// 使用API获取句柄数
function GetProcessHandleCount(PID: Cardinal): Cardinal;
var
hProcess: THandle;
begin
Result := 0;
if Assigned(_GetProcessHandleCount) then begin
hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
if hProcess <> 0 then begin
_GetProcessHandleCount(hProcess, Result);
CloseHandle(hProcess);
end;
end;
end;
提升权限的代码:
function EnablePrivilege(PrivName: string; bEnable: Boolean): Boolean;
var
TP: PTokenPrivileges;
Dummy: Cardinal;
hToken: THandle;
begin
Result := False;
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
begin
GetMem(TP, SizeOf(DWORD) + SizeOf(TLUIDAndAttributes));
try
TP.PrivilegeCount := 1;
if LookupPrivilegeValue(nil, PChar(PrivName), TP.Privileges[0].Luid) then begin
if bEnable then
TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
TP.Privileges[0].Attributes := 0;
Result := AdjustTokenPrivileges(hToken, False, TP^, SizeOf(TP), nil, Dummy);
end else
Result := False;
finally
FreeMem(TP);
CloseHandle(hToken);
end;
end;
end;
EnablePrivilege('SeDebugPrivilege', True); // 提升权限
Minimum supported client
Windows Vista, Windows XP with SP1 [desktop apps only]
Minimum supported server
Windows Server 2003 [desktop apps only]
第二种: (直接查询信息,不需要提升权限)
type
TSystemHandleInformationsBuffer = packed record
NumberOfHandles: LongWord;
SystemHandleInformations: array[0..MAX_LENGTH-1] of TSystemHandleInformation;
end;
var
FLocker: TCriticalSection;
HandleInfoBuffer: Pointer;
function GetProcessHandleCount(PID: Cardinal): Cardinal;
var
returnSize: Cardinal;
p, p1: PAnsiChar;
begin
P := HandleInfoBuffer;
FLocker.Enter;
Result := NtQuerySystemInformation(Cardinal(SystemHandleInformation),
P, SizeOf(TSystemHandleInformationsBuffer), returnSize);
if Result = 0 then begin
returnSize := PLongWord(P)^;
Inc(P, 4);
p1 := p + returnSize * SizeOf(TSystemHandleInformation);
while(p < p1) do begin
if (PSystemHandleInformation(P)^.ProcessId = PID) then
Inc(Result);
Inc(P, SizeOf(TSystemHandleInformation));
end;
end else
Result := 0;
FLocker.Leave;
end;
相关声明
type
TNtQuerySystemInformation = function(infoClass: DWORD; buffer: Pointer; bufSize: DWORD;
var returnSize: Dword): DWORD; stdcall;
TNtQueryInformationProcess = function (ProcessHandle: Cardinal;
ProcessInformationClass: PROCESSINFOCLASS; ProcessInformation: Pointer;
ProcessInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall;
var
_NtQuerySystemInformation: TNtQuerySystemInformation;
_NtQueryInformationProcess: TNtQueryInformationProcess;
function NtQuerySystemInformation(infoClass: DWORD; buffer: Pointer; bufSize: DWORD;
var returnSize: Dword): DWORD;
begin
if not Assigned(_NtQuerySystemInformation) then
Result := 0
else
Result := _NtQuerySystemInformation(infoClass, buffer, bufSize, returnSize);
end;
function NtQueryInformationProcess(ProcessHandle: Cardinal;
ProcessInformationClass: PROCESSINFOCLASS; ProcessInformation: Pointer;
ProcessInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS;
begin
if not Assigned(_NtQueryInformationProcess) then
Result := 0
else
Result := _NtQueryInformationProcess(ProcessHandle, ProcessInformationClass,
ProcessInformation, ProcessInformationLength, ReturnLength);
end;
initialization
FLocker := TCriticalSection.Create;
HandleInfoBuffer := GetMemory(SizeOf(TSystemHandleInformationsBuffer));
_NtQuerySystemInformation := GetProcAddress(GetModuleHandle('ntdll.dll'), 'NtQuerySystemInformation');
_NtQueryInformationProcess := GetProcAddress(GetModuleHandle('ntdll.dll'), 'NtQueryInformationProcess');
finalization
FLocker.Free;
FreeMemory(HandleInfoBuffer);