Leyendo argumentos de línea de comando de otro proceso (código Win32 C)

Necesito poder listar los argumentos de la línea de comandos (si los hay) pasados ​​a otros procesos en ejecución. Ya tengo los PID de los procesos en ejecución en el sistema, así que básicamente necesito determinar los argumentos que se pasan al proceso con el PID XXX dado.

Estoy trabajando en una pieza central de un módulo de Python para administrar procesos . El código se escribe como una extensión de Python en C y se envolverá en una biblioteca de Python de nivel superior. El objective de este proyecto es evitar la dependencia de las librerías de terceros, como las extensiones pywin32, o de los hacks feos, como llamar a ‘ps’ o taskkill en la línea de comandos, por lo que estoy buscando una forma de hacerlo en código C.

Busqué en Google y encontré algunas sugerencias breves sobre el uso de CreateRemoteThread () para insertarme en el otro proceso, luego ejecutar GetCommandLine () pero esperaba que alguien pudiera tener algunos ejemplos de código de trabajo y / o mejores sugerencias.

ACTUALIZACIÓN : Encontré un código de demostración en pleno funcionamiento y una solución que utiliza NtQueryProcessInformation en CodeProject: http://www.codeproject.com/KB/threads/GetNtProcessInfo.aspx : no es ideal, ya que “no es compatible” para recostackr la información directamente desde Las estructuras NTDLL pero viviré con ello. Gracias a todos por las sugerencias.

ACTUALIZACIÓN 2 : Me las arreglé a través de más Google para desenterrar una versión de C que no usa el código C ++, y es un poco más directa / concisa apuntando hacia este problema. Consulte http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/ para obtener más información.

¡Gracias!

Para responder a mi propia pregunta, finalmente encontré una solución de CodeProject que hace exactamente lo que estoy buscando:

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

Como @Reuben ya señaló, puede usar NtQueryProcessInformation para recuperar esta información. Desafortunadamente, no es un enfoque recomendado, pero dado que la única otra solución parece ser incurrir en la sobrecarga de una consulta de WMI, creo que lo haremos por ahora.

Tenga en cuenta que esto parece no funcionar si utiliza el código comstackdo desde Windows de 32 bits en un sistema operativo Windows de 64 bits, pero dado que nuestros módulos se comstackn desde el origen en el destino, eso debería estar bien para nuestros propósitos. Prefiero usar este código existente y si se rompe en Windows 7 o en una fecha posterior, podemos ver nuevamente el uso de WMI. Gracias por las respuestas!

ACTUALIZACIÓN : Aquí se ilustra una versión más concisa y solo C (en oposición a C ++) de la misma técnica:

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

La solución en caché: 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 

También: 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 

Al utilizar psutil ( https://github.com/giampaolo/psutil ):

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

El enfoque WMI mencionado en otra respuesta es probablemente la forma más confiable de hacerlo. Mirando a través de MSDN, descubrí lo que parece otro enfoque posible; está documentado, pero no está claro si es totalmente compatible. En el lenguaje de MSDN,

puede ser alterado o no disponible en futuras versiones de Windows …

En cualquier caso, siempre que su proceso tenga los permisos correctos, debería poder llamar a NtQueryProcessInformation con una ProcessInformationClass de ProcessBasicInformation . En la estructura devuelta de PROCESS_BASIC_INFORMATION , debe regresar un puntero al bloque de ejecución del proceso de destino (como campo PebBaseAddress ). El campo ProcessParameters del PEB le dará un puntero a una estructura RTL_USER_PROCESS_PARAMETERS . El campo de la línea de CommandLine de esa estructura será una estructura UNICODE_STRING . (Tenga cuidado de no hacer demasiadas suposiciones acerca de la cadena; no hay garantías de que terminará en NULL, y no está claro si tendrá que quitar el nombre de la aplicación ejecutada desde el principio de la aplicación). línea de comando.)

No he probado este enfoque, y como mencioné anteriormente, parece un poco … dudoso (lea: no portátil), pero podría valer la pena intentarlo. La mejor de las suertes…

Si no eres el padre de estos procesos, esto no es posible mediante el uso de funciones documentadas 🙁 Ahora, si eres el padre, puedes hacer tu truco CreateRemoteThread, pero de lo contrario casi seguro que obtendrás acceso denegado a menos que tu aplicación tenga derechos de administrador