本文告诉大家如何在 dotnet 获取指定的进程的命令行参数
很多的程序在启动的时候都需要传入参数,那么如何拿到这些程序传入的参数?
我找到两个方法,一个需要引用 C++ 库支持 x86 和 x64 程序,另一个都是C#代码,但是只支持 x86 程序
本文提供一个由 StackOverflow 大神开发的库拿到进程的命令行
在使用下面的代码需要引用两个 C++ 的库,可以从 csdn 下载
使用下面的代码就可以拿到传入进程的参数,在使用之前,需要在输出的文件夹里面包含 ProcCmdLine32.dll 和 ProcCmdLine64.dll 可以从csdn 下载
public static string GetCommandLineOfProcess(Process process) { // max size of a command line is USHORT/sizeof(WCHAR), so we are going // just allocate max USHORT for sanity sake. var stringBuilder = new StringBuilder(0xFFFF); if (Environment.Is64BitProcess) { GetProcCmdLine64((uint) process.Id, stringBuilder, (uint) stringBuilder.Capacity); } else { GetProcCmdLine32((uint) process.Id, stringBuilder, (uint) stringBuilder.Capacity); }
return stringBuilder.ToString(); }
[DllImport("ProcCmdLine32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetProcCmdLine")] private static extern bool GetProcCmdLine32(uint nProcId, StringBuilder stringBuilder, uint dwSizeBuf);
[DllImport("ProcCmdLine64.dll", CharSet = CharSet.Unicode, EntryPoint = "GetProcCmdLine")] private static extern bool GetProcCmdLine64(uint nProcId, StringBuilder stringBuilder, uint dwSizeBuf);
获取所有的进程的命令行可以使用这个代码
foreach (var process in Process.GetProcesses()) { Console.WriteLine($"{process.ProcessName} {GetCommandLineOfProcess(process)}"); }
上面的代码需要引用一个 C++ 的库,看起来不清真,下面通过全部 C# 的代码
public static string GetCommandLineOfProcess(int processId) { var pid = processId;
var pbi = new NativeMethods.PROCESS_BASIC_INFORMATION();
IntPtr proc = NativeMethods.OpenProcess ( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid );
if (proc == IntPtr.Zero) { return ""; }
if (NativeMethods.NtQueryInformationProcess(proc, 0, ref pbi, pbi.Size, IntPtr.Zero) == 0) { var buff = new byte[IntPtr.Size]; if (NativeMethods.ReadProcessMemory ( proc, (IntPtr) (pbi.PebBaseAddress.ToInt32() + 0x10), buff, IntPtr.Size, out _ )) { var buffPtr = BitConverter.ToInt32(buff, 0); var commandLine = new byte[Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING))];
if ( NativeMethods.ReadProcessMemory ( proc, (IntPtr) (buffPtr + 0x40), commandLine, Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING)), out _ ) ) { var ucsData = ByteArrayToStructure<NativeMethods.UNICODE_STRING>(commandLine); var parms = new byte[ucsData.Length]; if ( NativeMethods.ReadProcessMemory ( proc, ucsData.buffer, parms, ucsData.Length, out _ ) ) { return Encoding.Unicode.GetString(parms); } } } }
NativeMethods.CloseHandle(proc);
return ""; }
private const uint PROCESS_QUERY_INFORMATION = 0x400; private const uint PROCESS_VM_READ = 0x010;
private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct { var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); var stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); handle.Free(); return stuff; }
private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr OpenProcess ( uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId );
[DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ReadProcessMemory ( IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesRead );
[DllImport("ntdll.dll")] internal static extern int NtQueryInformationProcess ( IntPtr ProcessHandle, uint ProcessInformationClass, ref PROCESS_BASIC_INFORMATION ProcessInformation, uint ProcessInformationLength, IntPtr ReturnLength );
[StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct PROCESS_BASIC_INFORMATION { internal int ExitProcess; internal IntPtr PebBaseAddress; internal IntPtr AffinityMask; internal int BasePriority; internal IntPtr UniqueProcessId; internal IntPtr InheritedFromUniqueProcessId;
internal uint Size => (uint) Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
[StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct UNICODE_STRING { internal ushort Length; internal ushort MaximumLength; internal IntPtr buffer; } }
获取所有进程的参数
[STAThread] private static void Main(string[] args) { if (Environment.Is64BitProcess) { throw new InvalidOperationException("暂时只支持x86程序"); }
foreach (var process in Process.GetProcesses()) { Console.WriteLine($"{process.ProcessName} {GetCommandLineOfProcess(process.Id)}"); } }

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。