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

时间:2009-01-13 21:46:40

标签: python c winapi

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

我正在研究Python module for managing processes的核心部分。代码在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/

谢谢!

5 个答案:

答案 0 :(得分:6)

为了回答我自己的问题,我终于找到了一个完全符合我要求的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/

答案 1 :(得分:5)

缓存解决方案: 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

答案 2 :(得分:3)

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

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

答案 3 :(得分:2)

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

  

可能会被更改或不可用   未来版本的Windows ...

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

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

答案 4 :(得分:0)

如果您不是这些进程的父级,那么使用记录的函数就不可能:(现在,如果您是父级,则可以执行CreateRemoteThread技巧,但除此之外您几乎肯定会获得拒绝访问权限,除非您的应用拥有管理员权限。