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

9
我需要能够列出其他正在运行的进程传递的命令行参数(如果有)。我已经获取了系统上正在运行的进程的PID,所以基本上我需要确定给定PID的进程传递的参数。
我正在开发一个用于管理进程的Python模块的核心部分。该代码是用C编写的Python扩展,并将由更高级别的Python库包装。这个项目的目标是避免依赖第三方库,如pywin32扩展,或像在命令行上调用“ps”或taskkill这样的丑陋的hack,因此我正在寻找一种在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个回答

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/


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

Also: 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

谢谢您的建议,但我真的不想调用外部进程。所引用的wmi模块还需要在pywin32扩展之上安装另一个第三方模块,而我们也不希望要求用户安装它。 - Jay
你可以通过WMI的COM接口从C语言中调用它,尽管这可能不是最优雅的代码。 - Rob Walker
@Rob - 这是真的...这似乎是一个简单的任务,但这将会产生一些严重的开销,但现在看来我没有太多选择。 - Jay

3

2
另一篇回答中提到的 WMI 方法可能是最可靠的方法。在 MSDN 上查看时,我发现了另一种可能的方法;它有文档记录,但不清楚是否完全支持。根据 MSDN 的说法,它可能会在未来的 Windows 版本中被更改或不再支持。
无论如何,只要您的进程具有正确的权限,您应该能够调用 NtQueryProcessInformation 并将 ProcessInformationClass 设置为 ProcessBasicInformation。在返回的 PROCESS_BASIC_INFORMATION 结构中,您应该会得到一个指向目标进程的进程执行块的指针(作为字段 PebBaseAddress)。PEB 的 ProcessParameters 字段将为您提供指向 RTL_USER_PROCESS_PARAMETERS 结构的指针。该结构的 CommandLine 字段将是一个 UNICODE_STRING 结构。(请注意不要对字符串进行过多的假设;不能保证它将以 NULL 结尾,也不清楚您是否需要从命令行开头剥离执行应用程序的名称。)
我没有尝试过这种方法——正如我上面提到的,它似乎有点不可靠(即:不可移植)——但是也许值得一试。祝你好运...

我看到了这个,感觉和你一样 - 它似乎不太稳定,但是我找到的CodeProject演示在Vista上运行得非常好,所以我还是会选择它。请查看CodeProject链接以获取可工作的代码。 - Jay

0

如果您不是这些进程的父进程,则使用文档记录的函数不可能实现:( 现在,如果您是父进程,则可以使用CreateRemoteThread技巧,但否则,除非您的应用程序具有管理员权限,否则几乎肯定会收到访问被拒绝的错误。


我现在在模块中有一些代码,如果可能的话,将获取SeDebug权限,因此,如果他们是管理员用户,我们应该拥有所需的特权,对吧? - Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接