2

For some reporting purposes I'm trying to get the location of a certain binary.

I was doing this, and it was working, but I'm now getting a NullReferenceException when I try to get testProc.MainModule.FileName; and I think it may be that the program is closing before I'm able to grab it. Is there any better way to do this?

ProcessStartInfo testPSI = new ProcessStartInfo(RunOptions.TestBinary);
testPSI.RedirectStandardError = true;
testPSI.RedirectStandardOutput = true;
testPSI.UseShellExecute = false;
Process testProc = new Process();
testProc.StartInfo = testPSI;   
testProc.Start();
ret = testProc.MainModule.FileName;
testProc.Kill();
if (ret != null)
    return ret;
4

1 回答 1

3

选项 1:使用您已有的路径。

除非我遗漏了某些东西,否则您似乎是在自己创建流程(使用RunOptions.TestBinary),因此您应该已经知道路径。您可以使用 获取可执行文件的完整路径Path.GetFullPath(RunOptions.TestBinary),或者如果二进制文件位于 上PATH,您可以手动检查每个目录以确定执行二进制文件的位置。

选项 2:使用 C# 的WMI库:

如果测试主机进程和正在执行的进程之间存在位数(32位/64位)差异,则枚举模块和获取文件名将不起作用。但是,您可以使用 WMI 来解决此限制。

添加对的引用System.Management并尝试以下操作(警告:无错误处理):

static string GetImagePath(int processId)
{
    string query = string.Format("SELECT ExecutablePath FROM Win32_Process WHERE ProcessID='{0}'", processId);
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
    ManagementObjectCollection results = searcher.Get();
    ManagementObject process = results.Cast<ManagementObject>().First();
    return (string)process["ExecutablePath"];
}

选项 3:向目标进程添加同步:

如果这确实是一个时间问题(即受监控的进程在测试进程可以检查它之前就死了),那么您可以在两个进程之间添加一些同步(例如命名互斥锁)。如果你真的想深入挖掘,你可以使用ETW来捕获进程启动事件(见下文)。

选项 4:使用TraceEvent .NET 库来捕获进程启动事件。

Vance Morrison(谁编写了 TraceEvent 库)有一篇关于如何捕获进程启动事件的深入文章。该解决方案确实需要引入一堆依赖项,但由于它使用 ETW,因此不会出现时间问题(即使进程很快终止,进程启动事件仍然会被触发)。这是迄今为止最复杂的解决方案。

于 2013-05-21T02:03:40.397 回答