即使进程正在运行,Process.HasExited也会返回true?

joh*_*nrl 31 c# process exit terminate

我一直在观察,即使进程仍在运行,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");
Run Code Online (Sandbox Code Playgroud)

更新:我只是尝试等待process.WaitForExit()而不是轮询循环,结果完全相同.

另外:上面的代码只是为了证明一个"更清晰"的问题.说清楚; 我的问题不是我仍然可以Process.GetProcessesByName( "testprogram" );在设置HasExited为true 之后获得该过程.

真正的问题是我在外部运行的程序写入一个文件 - 它在它终止之前(优雅地).我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");
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ave 12

我意识到这是一篇很老的帖子,但是为了找出为什么我的应用程序在应用程序打开之前运行Exited事件,我发现了一些东西,我对将来遇到这个问题的人有用.

进程启动时,会为其分配PID.如果随后通过"用户帐户控制"对话框提示用户并选择"是",则重新启动该过程并分配新的PID.

我坐了几个小时,希望这可以节省一些时间.


Tom*_*zzo 8

我建议你这样试试:

process.Start();

while (!process.HasExited)
{
    // Discard cached information about the process.
    process.Refresh();

    // Just a little check!
    Console.WriteLine("Physical Memory Usage: " + process.WorkingSet64.ToString());

    Thread.Sleep(500);
}

foreach (Process current in Process.GetProcessesByName("testprogram"))
{
    if ((current.Id == process.Id) && !current.HasExited)
        throw new Exception("Oh oh!");
}
Run Code Online (Sandbox Code Playgroud)

无论如何...在HasExited的MSDN页面中我正在阅读以下高亮显示的注释:

当标准输出重定向到异步事件处理程序时,当此属性返回true时,输出处理可能无法完成.要确保已完成异步事件处理,请在检查HasExited之前调用不带参数的WaitForExit()重载.

当您重定向所有内容时,这可能会以某种方式与您的问题相关联.


小智 5

首先,您确定testprogram不会生成自己的进程并在不等待该进程完成的情况下退出吗?我们在这里处理某种竞赛条件,而testprogram可能很重要。

我想说明的第二点是-“我必须绝对确保此日志文件存在”。好吧,没有这样的事情。您可以进行检查,然后文件消失了。解决此问题的常用方法不是检查,而是执行您要对文件执行的操作。继续阅读,阅读异常,如果事情看起来不稳定并且您不想更改任何内容,请重试。如果您在系统中有多个角色(线程或其他功能),则功能检查和操作将无法正常工作。

接下来是一堆随机的想法。

您是否尝试过使用FileSystemWatcher而不依赖于进程完成?

如果您尝试在process.Exited事件中读取文件(不检查文件是否存在,而是采取行动),它会变得更好吗?[不应该]

系统健康吗?事件日志中有任何可疑的内容吗?

可以涉及一些真正激进的防病毒策略吗?

(如果不看所有代码并查看测试程序,就无法说出太多。)


Mic*_*ner 5

我知道,这是旧文章,但也许​​我可以帮助某人。
Process类的行为可能异常!HasExited如果该进程已退出,或者该进程以管理员权限运行并且您的程序仅具有用户特权,则将返回true 。


tyr*_*nid 1

首先,使用 Process.WaitForExit 而不是轮询它是否存在问题?

无论如何,从可用的角度来看,该进程退出在技术上是可能的,但该进程在执行诸如刷新磁盘缓存之类的操作时仍会短暂存在。日志文件是否特别大(或者它正在执行大量磁盘写入操作)?