I'm automating a Word document from a WPF application in C#.
In the application I create a Word object with
_applicationWD = new Microsoft.Office.Interop.Word.Application();
and I terminate it with
_applicationWD.Quit(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges);
Everything is neatly put in try/catch statements. As Quit is the last thing that can go wrong, I need to check if the Quit statement succeeded and then try to terminate it in some other way, otherwise I will have a lot of WinWord.exe in the process list.
Is there any way to check if Word closed or maybe get the PID of the process and force it to terminate from code?
this should kill all the winword processes
try
{
System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcessesByName("WinWord");
foreach (var myproc in procs)
myproc.Kill();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
Related
I would like to start a process using:
ProcessStartInfo createProject = new ProcessStartInfo();
createProject.FileName = exePath;
createProject.UseShellExecute = false;
createProject.WorkingDirectory = projectDirectory;
createProject.Arguments = exeArguments;
try
{
// Start the process with the info specified.
System.Diagnostics.Process.Start(createProject);
}
catch (IOException eX)
{
// Log error.
MessageBox.Show("Unable to create project", "Error Creating Project");
}
When I put a breakpoint at the line of Process.Start() and continue with step over by pressing F10, then the process runs without any problem.
However when I press F5 at the breakpoint or just run my application without any breakpoints, I get a "Your application has stopped working" dialog, without my application throwing any exception.
I tried also using Thread.Sleep() before the Process.Start() which has no result.
I really wonder what causes this problem.
EDIT: After I check the event viewer, I see that the faulting module is MSVCR90.dll. I have the version 9.0.30729.6161 installed.
This answer is for the one who is interested in the solution of the problem not the pragmatic discussion on the question itself:
Actually the answer was in the question itself and I got it after #rene raised one question.
Process runs when I step over because then program has time to finish its job. But when I press F5 it crashes because the process itself is not completed. I used following code:
ProcessStartInfo createProject = new ProcessStartInfo();
createProject.FileName = exePath;
createProject.UseShellExecute = false;
createProject.WorkingDirectory = projectDirectory;
createProject.Arguments = exeArguments;
try
{
using (System.Diagnostics.Process exeProcess = System.Diagnostics.Process.Start(createProject ))
{
exeProcess.WaitForExit();
}
}
catch (IOException eX)
{
// Log error.
MessageBox.Show("Unable to create project", "Error Creating Project");
}
This is the reason also why it doesn't throw any exception.
Thanks to #rene again!
Check your event log (with eventvwr.exe) to see if the process you're starting is hitting anything critical.
If the started process is also yours, you can add logging to it, or use System.Diagnostics.Debugger.Launch() to have it launch a debugger at startup -- or use gflags to break into it with WinDbg or similar on startup.
today I want to open application inside of form, but it cause error.
if (File.Exists(ts3))
{
Process p = Process.Start(ts3);
Thread.Sleep(2000);
SetParent(p.MainWindowHandle, panel1.Handle);
}
foreach (var process in Process.GetProcessesByName(ts3check))
{
process.Kill();
}
Thread.Sleep(500);
Process p = Process.Start(ts3);
Thread.Sleep(2000);
SetParent(p.MainWindowHandle, panel1.Handle);
It should check, if this app is already openned, if it is, kill it and open new one inside of my form. But when I try to open process in form, it will cause fatal error and makes my form stopped working. I'm looking at it for like half a hour and I can't see it.
EDIT: app works if app is not already openned, but if it is, it will execute this part of code and make the error
foreach (var process in Process.GetProcessesByName(ts3check))
{
process.Kill();
}
Thread.Sleep(500);
Process p = Process.Start(ts3);
Thread.Sleep(2000);
SetParent(p.MainWindowHandle, panel1.Handle);
Try changing Thread.Sleep(2000) to p.WaitForInputIdle() and you might also want to take a look at Hosting EXE Applications in a WinForm project over at CodeProject; someone has created a control to do exactly what you're looking for.
I'm trying to make a console app in c# that will confirm that another application is always running. The other application periodically crashes, and I need to check every few minutes and relaunch it if it has stopped working.
There are many questions on SO that address making sure than no more than one instance of the application is running. I'm trying to confirm that one (no more or less) is running at all times.
Does anybody know how to even begin approaching this?
I would suggest using System.Diagnostics.Process.GetProcessesByName to see if your process is running and then, if not, using System.Diagnostics.Process.Start to start the process.
var processes = Process.GetProcessesByName("yourProcessName");
if(processes.Length == 0)
{
Process.Start(#"C:\Path\To\Your\Process.exe");
}
// Kill the extras
for(int i = 1; i < process.Length; i++)
{
processes[i].Kill();
}
These commands are useful to control processes:
// check for processes
Process[] processes = Process.GetProcessesByName("nameOfExecutable");
foreach (Process proc in processes)
{
// do stuff
}
// start process (need path)
Process.Start("pathToExecutable");
// close gui process gently (if needed)
bool status = proc.CloseMainWindow();
// wait for process to close gently
bool status = proc.WaitForExit(killTimeMS);
// force close (kill) process
proc.Kill();
If you implement a "no more than one" rule (which is well-documented, as you point out) and then implement the periodic crash-checker, that should be sufficient to ensure that one and only one copy is running.
In fact, the periodic process doesn't even have to check for a crash. It can just fire up an instance, which will immediately exit if another instance is already running, thanks to whatever "no more than one" mechanism you implement. This has the added benefit of avoiding a possible race-condition between detecting a dead process and starting a new one.
You have a few options. The first is checking for a running process using the Process class. I got this from a Microsoft site, but it looks like it works:
public bool IsProcessRunning(string name)
{
//here we're going to get a list of all running processes on
//the computer
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.StartsWith(name))
{
//process found so it's running so return true
return true;
}
}
//process not found, return false
return false;
}
You could also use interprocess communications. This is something we do in house. We have a watcher application that sends a message to a service being monitored. If the service doesn't return an ACK in a timeout period, we attempt to restart it.
I suggest you to check if your application is in the list of running processes:
System.Diagnostics.Process.GetProcesses();
I have a foreach loop that starts a process within a try/catch. In the finally section of my try/catch/finally I am trying to ensure the the process does not have a handle on any files. I have to delete files that were being processed.
Nothing I have tried seems to be working. I continue to get System.IO exceptions. "The file is currently in use by another process."
You can see in the finally I am using the WaitForExit() before returning from this method. The very next method call is one to delete files. Why would the process still be open or have a handle on any of these file after this?
Thanks!
try
{
foreach (var fileInfo in jsFiles)
{
//removed for clarity
_process.StartInfo.FileName = "\"C:\\Program Files\\Java\\jre6\\bin\\java\"";
_process.StartInfo.Arguments = stringBuilder.ToString();
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardOutput = true;
_process.Start();
}
}
catch (Exception e)
{
BuildMessageEventArgs args = new BuildMessageEventArgs("Compression Error: " + e.Message,
string.Empty, "JSMin", MessageImportance.High);
BuildEngine.LogMessageEvent(args);
}
finally
{
_process.WaitForExit();
_process.Close();
}
There's something seriously wrong here. You're starting a bunch of processes, but only waiting for the last spawned one to exit.
Are you sure you don't want the foreach outside the try block?
If you tell us more about what exactly you're trying to do, we could provide better suggestions.
I think you need to restructure your code. As it stands a failure for any of the processes in the foreach will cause an exit from the loop. Even if everything does succeed then your WaitForExit and Close calls in the finally block will only address the last process from the loop above.
You need to deal with each process and its success and/or failure individually. Create a method that accepts a fileInfo parameter and spawns and waits on each process. Move your loop into the client code that will be calling the suggested method.
Is the process a Console application or a GUI application?
For a GUI application, you will have to do Process.CloseMainWindow.
foreach (var fileInfo in jsFiles)
{
using (Process process = new Process())
{
try
{
//Other stuff
process.Start();
}
catch (...)
{
//Exception Handling goes here...
}
finally
{
try
{
process.WaitForExit();
}
catch (...)
{
}
}
}
}
Process.WaitForExit() might throw an exception, so it needs a try/catch of it's own.
If you create the process in the using statement, you don't have to worry about closing it, .NET will dispose of it properly.
It's usually better to not precede local variables with an underscore character. Most people just use that for their fields.
I want to create a console application that behaves as follows:
The first instance of the app will execute a process.
The second instance executed later will kill the process.
Is there a simple way to do so?
EDIT:
The second instance also terminates the first instance and itself.
EDIT 2:
More details scenario is as follows:
Assume there is no instance of my application running.
If I execute my application, the new instance will run.
The application will create a process that execute Adobe Acrobat Reader X (for example).
Later, I execute my application again just to kill the running Adobe Acrobat Reader X and of course its host (the first instance of my application).
You need to implement a mutex to do this.
private static Mutex mutex = null;
private void CheckIfRunning() {
string strId = "291B62B2-812A-4a13-A657-BA672DD0C93B";
bool bCreated;
try
{
mutex = new Mutex(false, strId, out bCreated);
}
catch (Exception)
{
bCreated = false;
//Todo: Kill your process
}
if (!bCreated)
{
MessageBox.Show(Resources.lbliLinkAlreadyOpen, Resources.lblError, MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
}
You can create a process with a known name. Then when the application starts you could get a list with all the processes that are running. If the process is not there you can start it, if it's already there you can kill the process and exit.
A more elegant solution would be as Max suggested to use a Mutex to communicate between the processes. For example to be sure that you don't kill another process with the same name.