【发布时间】:2011-01-31 22:59:00
【问题描述】:
我一直观察到Process.HasExited 有时会返回true,即使进程仍在运行。
我下面的代码启动了一个名为“testprogram.exe”的进程,然后等待它退出。问题是有时我会抛出异常;似乎即使HasExited 返回true 进程本身在系统中仍然存在 - 这怎么可能??
我的程序在它终止之前写入一个日志文件,因此我需要在读取它之前绝对确定这个日志文件存在(也就是进程已经终止/完成)。不断检查它的存在不是一种选择。
// Create new process object
process = new Process();
// Setup event handlers
process.EnableRaisingEvents = true;
process.OutputDataReceived += OutputDataReceivedEvent;
process.ErrorDataReceived += ErrorDataReceivedEvent;
process.Exited += ProgramExitedEvent;
// Setup start info
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = ExePath,
// Must be false to redirect IO
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments = arguments
};
process.StartInfo = psi;
// Start the program
process.Start();
while (!process.HasExited)
Thread.Sleep( 500 );
Process[] p = Process.GetProcessesByName( "testprogram" );
if ( p.Length != 0 )
throw new Exception("Oh oh");
更新:我只是尝试使用 process.WaitForExit() 而不是轮询循环等待,结果完全相同。
补充:上面的代码只是为了演示一个“更清晰”的问题。说清楚;我的问题不在于在将HasExited 设置为true 之后,我仍然可以通过Process.GetProcessesByName( "testprogram" ); 来控制该过程。
真正的问题是我在外部运行的程序在它终止之前写入了一个文件(优雅地)。我使用HasExited 检查进程何时完成,因此我知道我可以读取文件(因为进程已退出!),但似乎HasExited 返回true,即使有时程序没有写入文件到磁盘呢。这是说明确切问题的示例代码:
// Start the program
process.Start();
while (!process.HasExited)
Thread.Sleep( 500 );
// Could also be process.WaitForExit(), makes no difference to the result
// Now the process has quit, I can read the file it has exported
if ( !File.Exists( xmlFile ) )
{
// But this exception is thrown occasionally, why?
throw new Exception("xml file not found");
}
【问题讨论】:
-
testprogram.exe 是如何退出的?您是在上面调用 Kill(),还是过早地结束它?完成所有写入后是否正常退出?
-
我不知道。这是我正在运行的外部程序,我没有它的源代码。我所知道的是它在关闭之前正在拧文件(导出其结果),因为这就是我从中观察到的行为。返回值为 0 所以我猜它正常退出。没有其他任何显示。
-
@johnrl 你有没有解决过这个问题,你能分享你的代码吗
-
如果您最终想要的是输出的 xml 文件,您是否考虑过 FileSystemWatcher? msdn.microsoft.com/en-us/library/…
-
@johnrl 我想知道是否一切都如您所愿......我从来没有遇到过管理这样的流程的问题。也许它启动了一个子进程并退出了主进程,或者由于某种原因 pid 发生了变化,或者在 Windows 错误报告中工作时在另一个进程中完成了转储,或者......变量太多了。您可以使用 procmon (sysinternals) 来获取有关什么进程做什么的更多信息,并检查 pid 是否在进程资源管理器中(来自 sysinternals 的 procexp)吗?