出于某些报告目的,我正试图获取某个二进制文件的位置。
我这样做了,它正在工作,但是当我尝试获取testProc.MainModule.FileName时,我现在得到一个NullReferenceException;而且我认为可能是程序在我能够抓住之前关闭。有没有更好的方法呢?
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;
答案 0 :(得分: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:使用the TraceEvent .NET library捕获流程启动事件。
Vance Morrison(编写了TraceEvent库)有an in-depth article关于如何捕获进程启动事件的信息。这个解决方案确实需要引入一堆依赖关系,但由于它使用ETW,因此不存在计时问题(即使进程快速死亡,进程启动事件仍然被触发)。这是迄今为止最复杂的解决方案。