读取另一个进程的命令行参数(Win32 C代码)

我需要能够列出传递给其他正在运行的进程的命令行参数(如果有的话)。 我已经在系统上运行进程的PID了,所以基本上我需要确定传递给给定PID XXX的进程的参数。

我正在研究用于管理流程的Python模块的核心部分。 代码在C中编写为Python扩展,并将由更高级别的Python库包装。 这个项目的目标是避免依赖于第三方库,例如pywin32扩展,或者在命令行上调用’ps’或taskkill等丑陋的黑客,所以我正在寻找一种在C代码中执行此操作的方法。

我用Google搜索了一下,发现了一些简短的建议,使用CreateRemoteThread()将自己注入其他进程,然后运行GetCommandLine(),但我希望有人可能有一些工作代码示例和/或更好的建议。

更新 :我在CodeProject上找到了使用NtQueryProcessInformation的完整工作演示代码和解决方案: http : //www.codeproject.com/KB/threads/GetNtProcessInfo.aspx – 这是不理想的,因为“不支持”直接从剔除信息NTDLL结构,但我会忍受它。 感谢大家的建议。

更新2 :我通过更多谷歌搜索来挖掘不使用C ++代码的C版本,并且更直接/更简洁地指出了这个问题。 有关详细信息,请参见http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/ 。

谢谢!

为了回答我自己的问题,我终于找到了一个完全符合我要求的CodeProject解决方案:

http://www.codeproject.com/KB/threads/GetNtProcessInfo.aspx

正如@Reuben已经指出的那样,您可以使用NtQueryProcessInformation来检索此信息。 不幸的是,这不是推荐的方法,但鉴于唯一的其他解决方案似乎是招致WMI查询的开销,我想我们现在就采用这种方法。

请注意,如果在64位Windows操作系统上使用从32位Windows编译的代码,这似乎不起作用,但由于我们的模块是从目标上的源编译的,应该可以用于我们的目的。 我宁愿使用现有的代码,如果它在Windows 7或更晚的日期中断,我们可以再次使用WMI。 谢谢你的回复!

更新 :此处说明了相同技术的更简洁和仅C(与C ++相对)版本:

http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/

缓存的解决方案:http: //74.125.45.132/search?q= cache: -wPkE2PbsGwJ : windowsxp.mvps.org/listproc.htm+running+process+command+line&hl=es&ct=clnk&cd=1&gl=ar&client=firefox-a

in CMD WMIC /OUTPUT:C:\ProcessList.txt PROCESS get Caption,Commandline,Processid or WMIC /OUTPUT:C:\ProcessList.txt path win32_process get Caption,Processid,Commandline 

另外: http : //mail.python.org/pipermail/python-win32/2007-December/006498.html

 http://tgolden.sc.sabren.com/python/wmi_cookbook.html#running_processes seems to do the trick: import wmi c = wmi.WMI () for process in c.Win32_Process (): print process.CommandLine 

通过使用psutil( https://github.com/giampaolo/psutil ):

 >>> import psutil, os >>> psutil.Process(os.getpid()).cmdline() ['C:\\Python26\\python.exe', '-O'] >>> 

另一个响应中提到的WMI方法可能是最可靠的方法。 通过MSDN,我发现了另一种可能的方法; 它已被记录,但尚不清楚它是否得到完全支持。 在MSDN的语言中,它 –

在将来的Windows版本中可能会被更改或不可用…

在任何情况下,只要您的进程具有正确的权限,您就应该能够使用ProcessBasicInformationProcessInformationClass调用NtQueryProcessInformation 。 在返回的PROCESS_BASIC_INFORMATION结构中,您应该返回指向目标进程的进程执行块的指针(作为字段PebBaseAddress )。 PEB的ProcessParameters字段将为您提供指向RTL_USER_PROCESS_PARAMETERS结构的指针。 该结构的CommandLine字段将是UNICODE_STRING结构。 (注意不要对字符串做太多假设;不能保证它会以NULL结尾,并且不清楚你是否需要从一开始就删除已执行应用程序的名称命令行。)

我没有尝试过这种方法 – 正如我上面提到的,它似乎有点…… iffy(阅读:非便携式) – 但它可能值得一试。 祝你好运……

如果你不是这些进程的父级,那么使用记录的函数就不可能了:(现在,如果你是父级,你可以做你的CreateRemoteThread技巧,但除非你的应用程序有,否则你几乎肯定会获得Access Denied管理员权限。