Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process.HasExited returns true even though process is running?

I have been observing that Process.HasExited sometimes returns true even though the process is still running.

My code below starts a process with name "testprogram.exe" and then waits for it to exit. The problem is that sometimes I get thrown the exception; it seems that even though HasExited returns true the process itself is still alive in the system - how can this be??

My program writes to a log file just before it terminates and thus I need to be absolutely sure that this log file exists (aka the process has terminated/finished) before reading it. Continuously checking for it's existence is not an option.

// 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");

UPDATE: I just tried waiting with process.WaitForExit() instead of the polling loop and the result is the exact same.

Addition: The above code was only to demonstrate a 'clearer' problem alike. To make it clear; my problem is NOT that I still can get a hold of the process by Process.GetProcessesByName( "testprogram" ); after it set HasExited to true.

The real problem is that the program I am running externally writes a file -just before- it terminates (gracefully). I use HasExited to check when the process has finished and thus I know I can read the file (because the process exited!), but it seems that HasExited returns true even sometimes when the program has NOT written the file to disk yet. Here's example code that illustrates the exact problem:

// 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");
}
like image 201
johnrl Avatar asked Mar 25 '10 21:03

johnrl


3 Answers

I realize this is an old post, but in my quest to find out why my app running the Exited event before the app had even opened I found out something that I though might be useful to people experiencing this problem in the future.

When a process is started, it is assigned a PID. If the User is then prompted with the User Account Control dialog and selects 'Yes', the process is re-started and assigned a new PID.

I sat with this for a few hours, hopefully this can save someone time.

like image 159
Dave Avatar answered Oct 18 '22 10:10

Dave


I would suggest you to try this way:

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!");
}

Anyway... in MSDN page of HasExited I'm reading the following hightlighted note:

When standard output has been redirected to asynchronous event handlers, it is possible that output processing will not have completed when this property returns true. To ensure that asynchronous event handling has been completed, call the WaitForExit() overload that takes no parameter before checking HasExited.

That could be somehow linked to your problem as you are redirecting everything.

like image 9
Tommaso Belluzzo Avatar answered Oct 18 '22 10:10

Tommaso Belluzzo


I know, this is an old post but maybe I can help someone.
The Process class may behave unexpectedly. HasExited will return true if the process has exited or if the process runs with administrator privileges and your program only has user privileges.

I have posted a question regarding this a while back here, but did not receive a satisfiable answer.

like image 9
plainerman Avatar answered Oct 18 '22 11:10

plainerman