Delphi 获取进程命令行参数方法
适合D2007 x86版本
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit2: TEdit; Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; type USHORT = Word; UNICODE_STRING = packed record Length: USHORT; MaximumLength: USHORT; Buffer: PWideString; end; RTL_USER_PROCESS_PARAMETERS = packed record Reserved1: array[0..15] of Byte; Reserved2: array[0..9] of Pointer; ImagePathName: UNICODE_STRING; CommandLine: UNICODE_STRING; end; PRTL_USER_PROCESS_PARAMETERS = ^RTL_USER_PROCESS_PARAMETERS; PEB = packed record Reserved1: array[0..1] of Byte; BeingDebugged: ByteBool; Reserved2: Byte; Reserved3: array[0..1] of Pointer; Ldr: Pointer; ProcessParameters: PRTL_USER_PROCESS_PARAMETERS; Reserved4: array[0..103] of Byte; Reserved5: array[0..51] of Pointer; end; PPEB = ^PEB; PROCESS_BASIC_INFORMATION = packed record ExitStatus: DWORD; PebBaseAddress: PPEB; AffinityMask: DWORD; BasePriority: DWORD; uUniqueProcessId: ULong; uInheritedFromUniqueProcessId: ULong; end; TProcessBasicInformation = PROCESS_BASIC_INFORMATION; function NtQueryInformationProcess(ProcessHandle: THandle;ProcessInformationClass: Byte;ProcessInformation: Pointer; ProcessInformationLength: ULONG;ReturnLength: PULONG): DWORD; stdcall; external 'ntdll.dll'; var Form1: TForm1; implementation {$R *.dfm} //only match x86 not support x64 bit application function GetProcessCmdLine(PID: Cardinal): string; const ProcessBasicInformation = 0; var h: THandle; pbi: TProcessBasicInformation; ret: Cardinal; r: Cardinal; ws: WideString; aPEB: PEB; ProcPar: RTL_USER_PROCESS_PARAMETERS; begin Result := ''; if PID = 0 then PID := GetCurrentProcessID; try h := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID); if h = 0 then Exit; try ret := NtQueryInformationProcess(h, ProcessBasicInformation, @pbi, SizeOf(pbi), @r); if ret = 0 then repeat if (not ReadProcessMemory(h, pbi.PebBaseAddress, @aPEB, SizeOf(aPEB), r)) or (r <> SizeOf(aPEB)) then break; if (not ReadProcessMemory(h, aPEB.ProcessParameters, @ProcPar, SizeOf(ProcPar), r)) or (r <> SizeOf(ProcPar)) then break; SetLength(ws, ProcPar.CommandLine.Length div 2); if (not ReadProcessMemory(h, ProcPar.CommandLine.Buffer, PWideChar(ws), ProcPar.CommandLine.Length, r)) or (r <> ProcPar.CommandLine.Length) then break; Result := ws; until True; finally CloseHandle(h); end; finally end; end; function EnableDebugPriv: Boolean; //提升进程权限为DEBUG权限 var hToken: THandle; tp: TTokenPrivileges; rl: Cardinal; begin Result := false; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken); if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then begin tp.PrivilegeCount:=1; tp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED; Result := AdjustTokenPrivileges(hToken, false, tp, SizeOf(tp), nil, rl); end; end; procedure TForm1.Button1Click(Sender: TObject); begin EnableDebugPriv; Memo1.Text:=GetProcessCmdLine(StrToInt(Edit2.Text)); end; end.
效果如下图:
以下代码适合X64位进程(32位兼容)编译环境XE2
function GetProcessCmdLine64(PID: Cardinal): string; var pbi : PROCESS_BASIC_INFORMATION64; pfnNtQueryInformationProcess : TNtQueryInformationProcess; pfnNtReadVirtualMemory : TNtReadVirtualMemory64; dwSize:DWORD; size:UINT64; iReturn:Integer; pAddrPEB:PVOID64; PEB:__PEB64; stBlock:_RTL_USER_PROCESS_PARAMETERS64; PathBuffer : PByte; hProcess:Cardinal; CmdLine:string; begin Result := ''; @pfnNtQueryInformationProcess := GetProcAddress(GetModuleHandle('ntdll.dll'),'NtWow64QueryInformationProcess64'); @pfnNtReadVirtualMemory := GetProcAddress(GetModuleHandle('ntdll.dll'),'NtWow64ReadVirtualMemory64'); hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID); if ( Assigned(pfnNtQueryInformationProcess) ) then begin pAddrPEB := 0; iReturn := pfnNtQueryInformationProcess(hProcess,0,@pbi,sizeof(pbi),PULONG(@dwSize)); pAddrPEB := pbi.PebBaseAddress; // NtQueryInformationProcess returns a negative value if it fails if (iReturn >= 0) then begin // 1. Find the Process Environment Block size := dwSize; if ( ERROR_SUCCESS <> pfnNtReadVirtualMemory(hProcess, pAddrPEB, @PEB, sizeof(PEB), PUINT64(@size)) ) then begin // Call GetLastError() if you need to know why Exit; end; // 2. From this PEB, get the address of the block containing // a pointer to the CmdLine if ( ERROR_SUCCESS <> pfnNtReadVirtualMemory(hProcess, PEB.ProcessParameters, @stBlock, sizeof(stBlock), PUINT64(@size))) then begin // Call GetLastError() if you need to know why Exit; end; { // 3. Get the ImagePathName PathBuffer := GetMemory(stBlock.ImagePathName.MaximumLength); FillChar(PathBuffer^,stBlock.ImagePathName.MaximumLength,0); if ( ERROR_SUCCESS = pfnNtReadVirtualMemory(hProcess, stBlock.ImagePathName.Buffer, PVOID(PathBuffer), stBlock.ImagePathName.Length*sizeof(Char), PUINT64(@size))) then begin // Call GetLastError() if you need to know why SetString(ImagePath,PChar(PathBuffer),stBlock.ImagePathName.Length div 2); Result := True; } end; // 4. Get the CmdLine // FreeMemory(PathBuffer); PathBuffer := GetMemory(stBlock.CmdLine.MaximumLength); FillChar(PathBuffer^,stBlock.CmdLine.MaximumLength,0); if ( ERROR_SUCCESS = pfnNtReadVirtualMemory(hProcess, stBlock.CmdLine.Buffer, PVOID(PathBuffer), stBlock.CmdLine.Length*sizeof(Char), PUINT64(@size))) then begin // Call GetLastError() if you need to know why SetString(CmdLine,PChar(PathBuffer),stBlock.CmdLine.Length div 2); Result := CmdLine; end; FreeMemory(PathBuffer); end; end;
效果:
本文来自博客园,作者:IT情深,转载请注明原文链接:https://www.cnblogs.com/wh445306/p/16751809.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?