I want to constantly check if a background process is running or not, I only have one label (to display the result)
My code that shows whether it's running or not is:
Process[] plist = Process.GetProcessesByName("chrome");
if (plist.Length > 0)
{
label1.ForeColor = Color.Green;
label1.Text = "FOUND";
}
else
{
label1.ForeColor = Color.Red;
label1.Text = "NOT FOUND";
}
And when run it, it works, but when I close the process it still shows "FOUND", how can I make it always check if plist.Lenght is 0 or >0?
p.s: I tried some duplicate questions etc and I didn't get it to work.
using System;
using System.Diagnostics;
namespace Program
{
class Program
{
static void Main(string[] args)
{
Process[] plist = Process.GetProcessesByName("msedge");
if (plist.Length > 0)
{
Console.WriteLine(plist[0].ProcessName);
}
else
{
Console.WriteLine("NotFound");
}
}
}
}
The code above seems to be working just fine. Two things I would check are:
open up task manager
ensure all chrome processes are closed, even if your chrome web browser is closed, there might be some open here. I used msedge, and it seemed to work just fine.
You may have hard looped your UI thread. This means it is so busy checking processes, that it has no time to update your label. normally you do not do tasks like this on the UI thread, but instead break them off on side threads. Alternatively you can use a timer on the main thread, check every couple of miliseconds. The last but Bad way to do this is to call:
label1.Invalidate();
Application.DoEvents();
These lines will force the UI to update and pause your process check, but is really only good for testing / development. As this will cause all of your processes to lag, not a good thing for production enviroments.
Developing a C# .NET 2.0 WinForm Application. Need the application to close and restart itself.
Application.Restart();
The above method has proven to be unreliable.
What is a better way to restart the application?
A much simpler approach that worked for me is:
Application.Restart();
Environment.Exit(0);
This preserves the command-line arguments and works despite event handlers that would normally prevent the application from closing.
The Restart() call tries to exit, starts a new instance anyway and returns. The Exit() call then terminates the process without giving any event handlers a chance to run. There is a very brief period in which both processes are running, which is not a problem in my case, but maybe in other cases.
The exit code 0 in Environment.Exit(0); specifies a clean shutdown. You can also exit with 1 to specify an error occurred.
If you are in main app form try to use
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
Unfortunately you can't use Process.Start() to start an instance of the currently running process. According to the Process.Start() docs:
"If the process is already running, no additional process resource is started..."
This technique will work fine under the VS debugger (because VS does some kind of magic that causes Process.Start to think the process is not already running), but will fail when not run under the debugger. (Note that this may be OS-specific - I seem to remember that in some of my testing, it worked on either XP or Vista, but I may just be remembering running it under the debugger.)
This technique is exactly the one used by the last programmer on the project on which I'm currently working, and I've been trying to find a workaround for this for quite some time. So far, I've only found one solution, and it just feels dirty and kludgy to me: start a 2nd application, that waits in the background for the first application to terminate, then re-launches the 1st application. I'm sure it would work, but, yuck.
Edit: Using a 2nd application works. All I did in the second app was:
static void RestartApp(int pid, string applicationName )
{
// Wait for the process to terminate
Process process = null;
try
{
process = Process.GetProcessById(pid);
process.WaitForExit(1000);
}
catch (ArgumentException ex)
{
// ArgumentException to indicate that the
// process doesn't exist? LAME!!
}
Process.Start(applicationName, "");
}
(This is a very simplified example. The real code has lots of sanity checking, error handling, etc)
I might be late to the party but here is my simple solution and it works like a charm with every application I have:
try
{
//run the program again and close this one
Process.Start(Application.StartupPath + "\\blabla.exe");
//or you can use Application.ExecutablePath
//close this one
Process.GetCurrentProcess().Kill();
}
catch
{ }
I had the same exact problem and I too had a requirement to prevent duplicate instances - I propose an alternative solution to the one HiredMind is proposing (which will work fine).
What I am doing is starting the new process with the processId of the old process (the one that triggers the restart) as a cmd line argument:
// Shut down the current app instance.
Application.Exit();
// Restart the app passing "/restart [processId]" as cmd line args
Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
Then when the new app starts I first parse the cm line args and check if the restart flag is there with a processId, then wait for that process to Exit:
if (_isRestart)
{
try
{
// get old process and wait UP TO 5 secs then give up!
Process oldProcess = Process.GetProcessById(_restartProcessId);
oldProcess.WaitForExit(5000);
}
catch (Exception ex)
{
// the process did not exist - probably already closed!
//TODO: --> LOG
}
}
I am obviously not showing all the safety checks that I have in place etc.
Even if not ideal - I find this a valid alternative so that you don't have to have in place a separate app just to handle restart.
Start/Exit Method
// Get the parameters/arguments passed to program if any
string arguments = string.Empty;
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename
arguments += args[i] + " ";
// Restart current application, with same arguments/parameters
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);
This seems to work better than Application.Restart();
Not sure how this handles if your program protects against multiple instance. My guess is you would be better off launching a second .exe which pauses and then starts your main application for you.
It's simple, you just need to call the Application.Restart() method, this will invoke your application to be restarted. You must also exit from the local environment with an error code:
Application.Restart();
Environment.Exit(int errorcode);
You can create an enumeration of error codes so that you application will exit efficeintly.
Another method is to just exit from the application and start the process using the executable path:
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
Try this code:
bool appNotRestarted = true;
This code must also be in the function:
if (appNotRestarted == true) {
appNotRestarted = false;
Application.Restart();
Application.ExitThread();
}
I figured an another solution out, perhaps anyone can use it, too.
string batchContent = "/c \"#ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();
Code is simplified so take care of Exceptions and stuff ;)
I fear that restarting the entire application using Process is approaching your problem in the wrong way.
An easier way is to modify the Program.cs file to restart:
static bool restart = true; // A variable that is accessible from program
static int restartCount = 0; // Count the number of restarts
static int maxRestarts = 3; // Maximum restarts before quitting the program
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while (restart && restartCount < maxRestarts)
{
restart = false; // if you like.. the program can set it to true again
restartCount++; // mark another restart,
// if you want to limit the number of restarts
// this is useful if your program is crashing on
// startup and cannot close normally as it will avoid
// a potential infinite loop
try {
Application.Run(new YourMainForm());
}
catch { // Application has crashed
restart = true;
}
}
}
You are forgetting the command-line options/parameters that were passed in to your currently running instance. If you don't pass those in, you are not doing a real restart. Set the Process.StartInfo with a clone of your process' parameters, then do a start.
For example, if your process was started as myexe -f -nosplash myfile.txt, your method would only execute myexe without all those flags and parameters.
I wanted the new application start up after the old one shuts down.
Using process.WaitForExit() to wait for your own process to shutdown makes no sense. It will always time out.
So, my approach is to use Application.Exit() then wait, but allow events to be processed, for a period of time. Then start a new application with the same arguments as the old.
static void restartApp() {
string commandLineArgs = getCommandLineArgs();
string exePath = Application.ExecutablePath;
try {
Application.Exit();
wait_allowingEvents( 1000 );
} catch( ArgumentException ex ) {
throw;
}
Process.Start( exePath, commandLineArgs );
}
static string getCommandLineArgs() {
Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() );
args.Dequeue(); // args[0] is always exe path/filename
return string.Join( " ", args.ToArray() );
}
static void wait_allowingEvents( int durationMS ) {
DateTime start = DateTime.Now;
do {
Application.DoEvents();
} while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS );
}
You could also use Restarter.
Restarter is an application that automatically monitor and restarts crashed or hung programs and applications. It was originally developed to monitor and restart game servers, but it will do the job for any console or form based program or application
public static void appReloader()
{
//Start a new instance of the current program
Process.Start(Application.ExecutablePath);
//close the current application process
Process.GetCurrentProcess().Kill();
}
Application.ExecutablePath returns your aplication .exe file path
Please follow the order of calls. You might want to place it in a try-catch clause.
The problem of using Application.Restart() is, that it starts a new process but the "old" one is still remaining. Therefor I decided to Kill the old process by using the following code snippet:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
And it works proper good. In my case MATLAB and a C# Application are sharing the same SQLite database. If MATLAB is using the database, the Form-App should restart (+Countdown) again, until MATLAB reset its busy bit in the database. (Just for side information)
How about create a bat file, run the batch file before closing, and then close the current instance.
The batch file does this:
wait in a loop to check whether the process has exited.
start the process.
Here's my 2 cents:
The sequence Start New Instance->Close Current Instance should work even for the applications that don't allow running multiple copies simultaneously as in this case the new instance may be passed a command-line argument which will indicate that there is a restart in progress so checking for other instances running will not be necessary. Waiting for the first instance to actually finish my be implemented too if it's absolutely imperative that no two intstances are running in parallel.
Application.Restart();
Environment.Exit(0);
I had a similar problem, but mine was related to unmanageable memory leak that I couldn't find on an app that has to run 24/7. With the customer I agreed that safe time to restart the app was 03:00AM if the memory consumption was over the defined value.
I tried Application.Restart, but since it seems to use some mechanism that starts new instance while it is already running, I went for another scheme. I used the trick that file system handles persist until process that created them dies. So, from The Application, i dropped the file to the disk, and didn't Dispose() the handle. I used the file to send 'myself' executable and starting directory also (to add flexibility).
Code:
_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
WorkingDirectory = Application.StartupPath,
Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();
Close() at the end would initiate app shutdown, and file handle I used for StreamWriter here would be held open until process really dies. Then...
Restarter.exe comes into action. It TRIES to read the file in exclusive mode, preventing it to gain access until main app wasn't dead, then starts main app, deletes the file and exists. I guess that it can't be simpler:
static void Main(string[] args)
{
string filename = args[0];
DateTime start = DateTime.Now;
bool done = false;
while ((DateTime.Now - start).TotalSeconds < 30 && !done)
{
try
{
StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
string[] runData = new string[2];
runData[0] = sr.ReadLine();
runData[1] = sr.ReadLine();
Thread.Sleep(1000);
Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
sr.Dispose();
File.Delete(filename);
done = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
I use the following and it does exactly what you are looking for:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info = null;
info = ad.CheckForDetailedUpdate();
if (info.IsUpdateRequired)
{
ad.UpdateAsync(); // I like the update dialog
MessageBox.Show("Application was upgraded and will now restart.");
Environment.Exit(0);
}
for using As logout you need to terminate all app from Ram Cache
so close The Application first and then Rerun it
//on clicking Logout Button
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
You could enclose your code inside a function and when restart is needed you can just call the function.
Take for instance an application that:
While application is not registered; (upon start) the application should prompt the user to register the application and create a login account.
Once registration is submitted and login credentials are created; the application should restart, check for registration and prompt the user to login with the inserted credentials (so the user can access to all the application features).
Problem:
By building and launching the application from Visual Studio; any of the 4 alternatives bellow will fail to accomplish the tasks required.
/*
* Note(s):
* Take into consideration that the lines bellow don't represent a code block.
* They are just a representation of possibilities,
* that can be used to restart the application.
*/
Application.Restart();
Application.Exit();
Environment.Exit(int errorCode);
Process.GetCurrentProcess().Kill();
What happens is: After creating the Registration, Login and calling Application.Restart(); the application will (strangely) reopen the Registration Form and skip data in a Database (even though the resource is set to "Copy if Newer").
Solution:
Batch Building the application was (for me) a proof that any of the lines above were actually working as expected.
Just not when building and running the application with Visual Studio.
In first place I'd try batch building the application; run it outside Visual Studio and check if Application.Restart() actually works as expected.
Also Check further Info regarding this thread subject:
How do I restart my C# WinForm Application?
I've found a new way that's pretty convenient and has quite a few upsides.
There's never more than one instance running.
Command line args are persisted.
No exit events are raised from the application.
No process handles are broken.
I had a third party application managing my application with Process.Start and using Exit event to reload the application. Many of these solutions would break this implementation which is how I ended up on the following solution.
public static CancellationTokenSource _restartTokenSource;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
while (_restartTokenSource == null || _restartTokenSource.IsCancellationRequested)
{
_restartTokenSource = new System.Threading.CancellationTokenSource();
_restartTokenSource.Token.Register(() =>
{
foreach (Form form in Application.OpenForms)
form.Close();
});
Application.Run(new FlashMain(args));
}
}
Since Application.Run blocks until all forms in the application are closed I put this portion of the initialization into a loop that only executes when a CancellationTokenSource is null (the first run) or IsCancellationRequested is true (restart requested).
I register an event on the CancellationTokenSource that closes all forms in the application when .Cancel() is called, therefore unblocking Application.Run and restarting the loop.
Call Program._restartTokenSource.Cancel(); anywhere in the application to restart it.
P.S. This also works great for injecting into a BlazorWebView to restart the application from .NET Core.
My program is in win forms (c#). It should open an external program, do a printscreen of it's main window, and close it.
By using Process.Start() I can open the the program, but then all the focus is on it and my code is halted. Only when I close it myself my form continues- but it's too late for the screenshot.
So how do I force my code to keep running?
public void Runttk(string maromnum)
{
Process runttk = new Process();
runttk.StartInfo.UseShellExecute = true;
runttk.StartInfo.FileName = #"C:\\program.exe";
runttk.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
runttk.Start();
this.Focus();
try
{
if (runttk.WaitForInputIdle()==true)
{
PringJpg(maromnum);
Killttk();
}
}
catch (Exception e)
{
}
}
Thank you
UPDATE:
eventuanlly I've used Thread.Sleep(3000). Crued but do the trick.
I didn't used backgroundworker because the sync between the finale uplaod the the extenral program and my code wasn't clear enough.
Trying your code, but with another program like notepad.exe, Notepad runs and then control drops through to where you call PringJpg.
So I think the problem is that it is blocking on if (runttk.WaitForInputIdle()==true), please try adding a timeout to this operation.
Maybe your programm is never idle - means that runttk.WaitForInputIdle()==true let your app wait until you close it.
Add a limit ( for example runttk.WaitForInputIdle(500)==true) should fulfill your needings.
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.