starting external process when one process is done - c#

Stupid question, but I am starting a couple external applications (all .exe). After the process is started, how can I make my program wait until that process ends to start another process?
Example'
'Start application
Process.Start(My.Computer.FileSystem.CurrentDirectory & "SomeEXE1.exe")
**' A if statement or something to state that SomeEXE2.exe will NOT start until SomeEXE1.exe finish.**
Process.Start(My.Computer.FileSystem.CurrentDirectory & "SomeEXE2.exe")

Just call:
Process.WaitForExit
on that instance of Process.

How about using Shell?
Dim pID As Integer = Shell(thePathOfEXE, AppWinStyle.NormalFocus, True, 30000)
Will launch the exe passing the processID back to pID, normal focus and wait until completed execution or until 30 seconds have passed. The 30000 could be -1 if you're not interested in a timeout.
http://msdn.microsoft.com/en-us/library/xe736fyk(v=vs.71).aspx

Related

Interrupt a running process with IPC

I have two processes in a Win Form application. In the first process I have a methode "checkIfTrue" which has a return value of boolean. The methode in the first process will get some information from the second process by IPC (I use WCF with named pipes) and will return, depand on the information from the second process true or false.
My problem how can I interrupt the first process? The method in the first process ask the second process for information, when the second process got the information and will send back the result to the first process. In the first process the result will not be process before the methode "checkIfTrue" are finished.
The second process will call a method "synchronizeResults" via IPC and transfer the results. The methode "synchronizeResults" store the result in a ConcurrentDictionary. My plan was to stop the methode "checkIfTrue" in first process until the Dictionary is filled. But the methode "synchronizeResults" is not calling by IPC until methode "checkIfTrue" is finished.
Normally i would fire a event when the result are send back from process 2, but in this case I need the result before the methode is finished.
The main reason while it doesnt work was my CallbackService-Class. I had forgot to mark the class with
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)].
When a callback is made from the service to client, only one thread is spawned because by default the concurrency mode is set to “single”.
Here's [a link] (https://blogs.msdn.microsoft.com/dsnotes/2013/09/18/wcf-callback-operations-are-invoked-sequentially/)

Start more processes and get window handle for each right after start and without sleep? [duplicate]

This question already has answers here:
How to open an application on active display while using Process.Start()?
(1 answer)
Programmatically, how does this application detect that a program is ready for input
(3 answers)
Determining when a process has finalized initialization
(2 answers)
Check if Windows Application is running (not process)
(4 answers)
Closed 5 years ago.
I'm working on an application that starts other processes (some console applications, etc.). Each process has a user interface. When each process is started (via process.Start()), I want to move the process UI to some other location on the screen (also on the second monitor). I know how to do this later after a "sleep" or button click action. The problem is that I want the window to move right after the process starts. The window handle is still not "available" (value is 0).
I searched for a solution and came across the process.WaitForExit(100) method and the process.Exited event handler. After investigating these, I discovered that:
the process.Exited event is called when the process ends and not when the process "loads," and
process.WaitForExit(100) causes the program to "sleep" when it is invoked.
So, I need some architecture guidance. How can I solve my problem without "sleeping" (for example, via process.WaitForExit(100))? Should I consider an approach that involves one of the following techniques:
Mutex,
Multithreading, or
Async process start?
Or, is process.WaitForExit(100) really OK (not "dangerous") for a stable application (if I will run up to 15 processes)? Here is my code example:
private void startApplication(
int aApplicationId,
string aBrowserPath,
string aAppPath,
int aMid,
int aAppLeft,
int aAppTop,
int aAppWidth,
int aAppHeight) // Try to start application process
{
Process process = new Process();
try
{
process.StartInfo.FileName = aAppPath;
//process.EnableRaisingEvents = true;
//process.Exited += new EventHandler(myProcess_Exited);
//process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit(100);
mProcessMap.Add(aApplicationId, process); // Add to process map
// Move process window to right position
IntPtr windowHandle = process.MainWindowHandle;
this.moveAppToRightPosition(windowHandle, aMid, aAppLeft, aAppTop,
aAppWidth, aAppHeight);
}
catch (Exception exc)
{
Console.WriteLine("ERROR! Process start exception!");
}
}
You can't retrieve the MainWindowHandle immediately after the process is created because the creation of a process and of a window are two completely independent things (not to mention that a process may not even have a window). So there is nothing wrong with sleeping and waiting for the MainWindowHandle to appear. MSDN says you need to call Refresh to update it.
If you don't want to sleep you have two options:
Set a hook that will notify you when the process created a window. More details in this answer.
If you also created the process you are launching then you can insert the logic that will notify the master process via a socket or named pipe once the window is created.
Sleeping might not be the right way, because the process might need more time to start.
It may be possible to start a thread (if you want to asynchronously run the function startApplication) and in that thread check for the state of the process and when available set the position of window (looping with sleep at the end of loop).
I would use SendMessageTimeout to send WM_NULL messages in a loop, with a small timeout of say 50-100ms. If the function succeeds, that means that the new process is alive and going strong. In this way, you will block only for the timeout interval.

How to stop a process after you run it?

This is the code I used to run the following exe program. How can I end this 3 process after I had run it?
Process.Start(#"C:\Bot-shortcut\DIE1.exe");
Process.Start(#"C:\Bot-shortcut\DIE2.exe");
Process.Start(#"C:\Bot-shortcut\DIE3.exe");
First, store the process object returned when you start the process.
If you want it to close normally, as though someone had clicked the close icon, then use CloseMainWindow. This simulates clicking the close icon so that the process can shut down normally. This is always preferable to killing the process, which can corrupt data.
If you want it to die instantly then use Kill. Note that this can corrupt data; the process might have been writing to a file when you killed it.
You have to get the process by Name and then stop it.
Here is the code snippet from MSDN:
Process[] myProcesses;
// Returns array containing all instances of Notepad.
myProcesses = Process.GetProcessesByName("Notepad");
foreach (Process myProcess in myProcesses)
{
myProcess.CloseMainWindow();
}
The Process.kill() will also stop the process but without any prompt.
Find the details in This article.
You can end your process using Kill
Process myProcess = new Process(#"C:\Bot-shortcut\DIE1.exe");
myProcess.Start();
//After Some Codes
myProcess.Kill();
Process.Start returns the process instance which you have started.
Store that in variable and use Process.Kill method to kill that process once you are done with it.
Process process = Process.Start(#"C:\Bot-shortcut\DIE1.exe");
process.Kill();
Store the process objects as variables:
var proc1 =Process.Start(#"C:\Bot-shortcut\DIE1.exe");
var proc2 = Process.Start(#"C:\Bot-shortcut\DIE2.exe");
var proc3 = Process.Start(#"C:\Bot-shortcut\DIE3.exe");
And wait for them to exit:
proc1.WaitForExit();
proc2.WaitForExit();
proc3.WaitForExit();
Or kill them:
proc1.Kill();
proc2.Kill();
proc3.Kill();

Make program make sure it has 3 instances of itself running at all times?

There's a .NET assembly and it needs to have 3 instances running at the same time all the time how can I monitor this.
I am fairly positive it can be done by monitoring the system processes?
Something like this:
using System.Diagnostics;
// ...
string proc = Process.GetCurrentProcess().ProcessName;
Process[] processes = Process.GetProcessesByName(proc);
if (processes.Length != 3)
{
// ...
}
Step 1: Start the initial process and let it know that it's the master "ID1"
To start the initial process, use a command line argument. MyProcess.exe -ID1
This instance of your process knows that it is the "master" or ID1 vs. ID2, ID3
Step 2: Run this code periodically when the application's ProcessID is #1
Note: You can use a timer and fire an event and handle it with the code below:
Imports System.Diagnostics
'Check to see if we need to spawn one or more processes
Dim ProcessCounter as integer = 0
For Each p as Process In Process.GetProcesses
if p.NameProperty??.ToString() = "MyProcessName" then ProcessCounter += 1
Next
'Use this code to spawn new instances of the process, and assign process ID's accordingly
while processcounter < 3
Use Process.Start() and run a new instance of your process, but pass it a command line argument -ID# where # is the # of that process (also = to ProcessCounter)
ProcessCounter += 1
end while
Notes:
You may want to run a "watcher" process that periodically runs the above code... you can have a windows task that runs a simple exe every minute or so that contains only the above code. You must use a "watcher" process if the master process (or the one with ID = 1 above) may terminate
If a process has an internal ID variable that is not 1 (indicating that it is the master process that is in charge of monitoring for the existing of 3 instances), then the above code will not be run. Only one of the processes needs to do this monitoring

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");
}
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.
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.
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.
First off, are you sure testprogram does not spawn a process of its own and exit without waiting for that process to finish? We're dealing with some kind of race condition here, and testprogram can be significant.
Second point I'd like to make is about this - "I need to be absolutely sure that this logfile exists". Well, there is no such thing. You can make your check, and then the file is gone. The common way to address this is not to check, but rather to do what you want to do with the file. Go ahead, read it, catch exceptions, retry if the thing seems unstable and you don't want to change anything. The functional check-and-do does not work well if you have more than one actor (thread or whatever) in the system.
A bunch of random ideas follows.
Have you tried using FileSystemWatcher and not depending on process completion?
Does it get any better if you try reading the file (not checking if it exists, but acting instead) in the process.Exited event? [it shouldn't]
Is the system healthy? Anything suspicious in the Event Log?
Can some really aggressive antivirus policy be involved?
(Can't tell much without seeing all the code and looking into testprogram.)
So just for a further investigation into the root cause of the problem you should maybe check out what's really happening by using Process Monitor. Simply start it and include the external program and your own tool and let it record what happens.
Within the log you should see how the external tool writes to the output file and how you open that file. But within this log you should see in which order all these accesses happen.
The first thing that came to my mind is that the Process class doesn't lie and the process is really gone when it tells so. So problem is that at this point in time it seems that the file is still not fully available. I think this is a problem of the OS, cause it holds some parts of the file still within a cache that is not fully written onto the disk and the tool has simply exited itself without flushing its file handles.
With this in mind you should see within the log that the external tool created the file, exited and AFTER that the file will be flushed/closed (by the OS [maybe remove any filters when you found this point within the log]).
So if my assumptions are correct the root cause would be the bad behavior of your external tool which you can't change thus leading to simply wait a little bit after the process has exited and hope that the timeout is long enough to get the file flushed/closed by the OS (maybe try to open the file in a loop with a timeout till it succeeded).
There's two possibilities, the process object continues to hold a reference to the process, so it has exited, but it hasn't yet been deleted. Or you have a second instance of the process running. You should also compare the process Id to make sure. Try this.
....
// Start the program
process.Start();
while (!process.HasExited)
Thread.Sleep( 500 );
Process[] p = Process.GetProcessesByName( "testprogram" );
if ( p.Length != 0 && p[0].Id == process.id && ! p[0].HasExited)
throw new Exception("Oh oh");
For a start, is there an issue with using Process.WaitForExit rather than polling it?
Anyway, it is technically possible for the process to exit from a usable point of view but the process still be around briefly while it does stuff like flush disk cache. Is the log file especially large (or any operation it is performing heavy on disk writes)?
As per MSDN documentation for HasExited.
If a handle is open to the process,
the operating system releases the
process memory when the process has
exited, but retains administrative
information about the process, such as
the handle, exit code, and exit time.
Probably not related, but it's worth noting.
If it's only a problem 1/10 of the time, and the process disappears after a second anyway, depending on your usage of HasExited, try just adding another delay after the HasExited check works, like
while (!process.HasExited)
DoStuff();
Thread.Sleep(500);
Cleanup();
and see if the problem persists.
Personally, I've always just used the Exited event handler instead of any kind of polling, and a simplistic custom wrapper around System.Diagnostics.Process to handle things like thread safety, wrapping a call to CloseMainWindow() followed by WaitForExit(timeout) and finally Kill(), logging, et cetera, and never encountered a problem.
Maybe the problem is in the testprogram? Does this code nicely flush/close etc.? It seems to me if testprogram writes a file to disk, the file should at least be available (empty or not)
If you have web application, and your external program/process is generating files (write to disk) check if your IIS have rights to write to that folder if not on properties security add permission for your IIS user, that was the reason in my case, i was receiving process.HasExited =true, but produced files from the process was not completed, after struggling for a while i add full permissions to the folder where process was writhing and process.Refresh() as Zarathos described from above and everything was working as expected.
Use process_name.Refresh() before checking whether process has exited or not. Refresh() will clear all the cached information related to the process.

Categories