How to wait for a task to finish - c#

I've got a Windows Form, where I've got a report being exported to PDF format.
After the report is generated, I would like to have the application terminated completely. I have added an Application.Exit() clause, however this sometimes closes the process while exporting is still happening.
Hence, I would like to close the application only if the exporting is complete.
I have tried the following:
while(true)
{
if (Process.GetCurrentProcess().WaitForInputIdle())
{
Application.Exit();
}
}
and also:
while(true)
{
if (Process.GetCurrentProcess().Responding)
{
Application.Exit();
}
}
None have worked however - the application still sometimes closes before the export is complete.
What am I doing wrong?

You could start exporting in another process and wait for it to finish (check out the related post: Wait till a process ends).
If you don't want that, you can check whether the file to which the exporting is done exists and whether it is locked (check out Wait Until File Is Completely Written).

The problem is that if the application is designed to be responsive to user interactions, both ways will close the application even though it is still working.
Maybe you should monitor the output of the application? That is: If the PDF file is present, the process is done. Or rather: If the PDF file is present and hasn't been modified for 15 seconds or something, exit the application.

Related

Multiple WinWord in Task Manager

my c# application creates winword in task manager and close properly from taskmanager. but in case my application crashed then the winword remains opened in task manager and cannot able to process those word document.
so in that case i want to kill those winword alone which is created by my application and not all.
please help to finish this.
When instances of winword.exe are created through interop, they'll have the string "/Automation -Embedding" included in the process command line.
So, if you want to manually kill only your interop winword processes, without killing any user-initiated instances of Microsoft Word, you can open up Mark Russinovich's free ProcessExplorer utility, right click on a line with winword.exe, choose "properties", and look at the command line (in the Image tab). If you see the /Automation switch, you'll know it's an interop process and you can kill it. Here's how the interop winword.exe will look in ProcessExplorer:
Try the following:
try
{
// open your word document
// process your word document
}
catch
{
// handle any errors (e.g. provide error messages
}
finally
{
// close the word document properly
}
To prevent orphaned word processes you will need to store the open processes in a central way in your application and close all remaining processes before shutting down the application. Furthermore you could register to the unhandled error event and then close all processes if that happens.
Shutting down word processes if you cannot open a document is no option in most cases, because that document might be opened for editing in a "real" word instance.

Issue Message without locking up exe

I have essentially two programs:
main.exe
update.exe
Update creates a flag file (update.inprogress) so that main cannot run while the update is in progress.
If main opens and that file exists, it immediately exits to prevent a program in use conflict.
I'm only having one issue. If the update is in process, the main program closes without and reason when they try to go in. I need to tell them the program is updating to keep them from calling us that the world has come to an end...
My question is, how can I issue a message that the update is in progress without tying up the main.exe? If I issue it from main.exe, then it will be in use and cannot be updated.
I was thinking of opening up notepad and putting a message in there but that just seems like a bad way of doing it.
I could also create another exe that only displays this message, but, if I have to update it, it will be in use too.. kind of defeats my purpose.
Anyone have a better idea?
Clarification:
This is a peer-to-peer network. The update could be run on workstation XYZ and someone could attempt to get into the main.exe at workstation ABC. This is why I am using a flag file. I have to way to check the process running on another workstation.
I assume that when update.exe runs, it does not need to update itself? If that is the case, you can modify update.exe to invoke main.exe if no updates are necessary.
For instance, if an update is necessary(you can accomplish this via a adding a version number to your main.exe and checking it), update.exe will create your update.inprogress file and run the updates. Then if another instance of update.exe runs, it will see the update.inprogress file and alert the user that update is in progress and terminate itself without tying up main.exe. If update.exe runs when no updates are necessary and update.inprogress does not exist, it will invoke main.exe programmatically.
I would suggest to create a thread from your update.exe to check for the existence of your main.exe process. In case it shows up, alert the user with a message from your update.exe.

Suspending main process in C#

I am developing an application in C#. As part of an error condition, I would like to bring up a file in Notepad for the user to edit (while pausing the main process). I am able to bring the file up using Process.Start. What I can't figure out is how to pause the main application until the user saves or quits out of the notepad file. Is there something other than Process.start that I could use that would launch the Notepad.exe in the main process or some other trick I can use. I feel like there is an easy solution to it that I am overlooking. Thanks in advance.
You could use Process.WaitForExit to block the main program until Notepad is closed.
Making it block until the file is saved or closed would be a bit trickier.
One option here would be to have a ManualResetEvent, and wait on it. You could then listen for Process.Exited (after setting Process.EnableRaisingEvents), and use this to call Set() on the wait handle. This would handle allowing your code to continue when the process exits.
For handling the file being saved, a separate FileSystemWatcher could watch for the save (file change) on the file itself. If the file saves/changes, you could continue on by calling Set().
I believe you should be able to do something like this.
var notePad = new Process { StartInfo = { FileName = "notepad.exe", Arguments = "newfile.txt" } };
notePad.Start();
while(!notePad.HasExited)
{
}
MessageBox.Show("Done.");
The "Done." message box shouldn't show up until you close notepad. Then again, the answer above mine is less hackish.

Tracking multiple processes at same time

I have an application (winforms) that downloads a file to user's temporary folder, then it opens the file for user to see contents, and when the file is closed, the file gets deleted from temp folder. The application is working ok if I open let's say one .pdf and one .doc The problem appears when trying to open one .doc if another winword process is still runing (doesn't matter if is opened by my app or directly by user).
I'm using the following code:
_OpenFileProces = System.Diagnostics.Process.Start(TempFileName);
_OpenFileProces.EnableRaisingEvents = true;
_OpenFileProces.Exited += new EventHandler(_OpenFileProces_Exited);
and this one to clear temp
void _OpenFileProces_Exited(object sender, EventArgs e)
{
string s = ((System.Diagnostics.Process)sender).StartInfo.FileName;
System.IO.File.Delete(s);
}
It seems that the running process is stopping my own.. and due to stopping it will delete the file or it will generate an error while trying to delete the file.
Do you have any suggestion how can I open my own process? The thing is I do not know what file type I have to open (it could be anything) and I'm counting on windows to choose the best application. from my test, notepad works ok, but winword and acrobat closes my process.
Thank you
I suspect that Microsoft Word is doing exactly the same thing here as Raymond Chen describes the Windows Shell as doing here:
A customer wanted help with monitoring the lifetime of an Explorer window.
"We want to launch a copy of Explorer to open a specific folder, then wait until the user closes the folder before continuing. We tried launching a copy of Explorer with the folder on the command line, then doing a Wait­For­Single­Object on the process handle, but the wait sometimes completes immediately without waiting. How do we wait until the user closes the Explorer window?"
This is another case of solving a problem halfway and then having trouble with the other half.
The reason that Wait­For­Single­Object returns immediately is that Explorer is a single-instance program (well, limited-instance). When you open an Explorer window, the request is handed off to a running copy of Explorer, and the copy of Explorer you launched exits. That's why your Wait­For­Single­Object returns immediately.
In your case, Word is already running, so when you create a second Word process and instruct it to open your document, it simply hands the request off to the instance of Word that is already running, and quits the second process you launched immediately.
That's what you're seeing when you describe that "the running process is stopping my own". Because that second instance gets closed immediately after you launch it, the Exited event is raised and your code tells it to delete the file!
You astutely observe that Notepad (unlike Word and Adobe Acrobat) works just fine. That's because Notepad is designed to be a multiple-instance application. You can open as many copies of Notepad as you want; it doesn't care if there's already 1 or 6 copies open on the desktop. And more importantly, asking the shell to open a text document in Notepad actually opens a second copy of the Notepad application, rather than sending a request to the first instance to open a new window for the new doc.
You should set the Process.StartInfo.UseShellExecute to true like this _OpenFileProces.StartInfo.UseShellExecute = true; before starting the process and then it should work I think...

Process.Start Sometimes taking a long time to come back

I have got an odd issue in an app I am writing.
It reads a master xml config file, creates a local copy for the user then performs some actions as laid out in the xml file. It checks to see if the local xml file needs updating so it doesn't need to do it every time.
Each of the actions are run in a new thread, and once all the threads have finished it writes a log and inform the user its finished.
One of the actions is to import a .reg file into the registry. I'm doing that like so:
Process regeditProcess = Process.Start("regedit.exe", "/s " + RegFilePath);
regeditProcess.WaitForExit();
regeditProcess.Close();
The issue I have is if the application creates a new config file, then the regedit process can take anything up to 30 seconds. If it doesn't create one then it finishes within a second.
In the loop that checks the threads have finished, I have put an
Application.DoEvents();
If I don't do this, the regedit process will run, and if I wait long enough I get a ContextSwitchDeadlock was detected error from the debugger. I have tried using different .reg file and only running this one action but still the same.
The creation of the xml file takes place in the main worker thread before any of the actions are attempted, but I'm sure this is having some effect on it, I'm just not sure what.
I know its a bit of a strange scenario, but has anyone hit something like this before?
Are you explicitly closing the file writer object after creating the config file? If not, you may be locking the file, preventing access from your worker.
I've worked out what the issue was, I had the STAThread directive in Program.cs. Once i took this out it worked a treat.
STAThread and multithreading
http://ilvyanyatka.spaces.live.com/blog/cns!EA0C02AB2E2FCFAC!193.entry?wa=wsignin1.0&sa=143328961

Categories

Resources