Suspending main process in C# - 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.

Related

How to wait for a task to finish

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.

Stalling program until JSFL file finishes

I am trying to run a JSFL script from within a C# project, where the JSFL script opens up a .fla file, modifies it n times, and exports n .swf files before closing. From the C# project, I am starting up the JSFL script through the Process class. I try to wait for the JSFL process to finish through the myProcess.WaitForExit() command, but it doesn't work. The remainder of my code C# executes before the JSFL process finishes exporting its .swf files. Is there any way I can throw something that the C# project can catch from the JSFL file or some other solution?
One solution (although most likely not the best one) would be for your C# code to look for the SWF files being created. Only once they've been updated/created will the JSFL script have finished, so you know that it will be safe for your C# to move on. In case there is no way of knowing how many SWF files the C# program needs to look for, you could instead let the JSFL script write to a log file of some sort, and to have the C# program read that log on a interval, looking for some sort of token to indicate that the JSFL script has completed it's task.
Granted, this may be far from the best method (and I don't know C# well enough to know whether what you're seeing is by design or a sign of something being wrong). But it may just be the case that running JSFL/Flash is completely asynchronous and if so, maybe the log file approach is the quickest path to solving the problem.
I have the same problem with another application that calls an external JSFL script.
What I do is write a file once finished to a target directory, and in the calling application, poll for that file. As soon as the file appears, I know the task has finished, and I delete the temp file, and carry on. Oh - and before starting I look for and delete any temp files so I don't get a false positive.
It's not so nice as events, but you have to work with what you've got.
Have you tried to set a custom Listener that will execute a function when the JSFL done. Don't forget that it's still based on ECMA which is a procedual language.
By the way, JSFL has a LOW-LEVEL C API.
C LEVEL API
This is absolutely possible, and I've already posted a solution here on stack overflow, complete with a detailed problem description and all the C# and JSFL source code necessary to implement it: Automating publishing of FLA files; calling Process.Start multiple times
To summarize... first of all, waiting on the JSFL script process is useless, because you're actually calling Flash.exe, which will remain open/running after the JSFL completes, so you'd be waiting on a process exit event that will never occur.
The trick is to use a JSFL function at the end of the JSFL script which executes a windows command line command, and it's that call which will signal your C# app that the JSLF script has completed. So basically you'll have your main instance of your C# app, but you want to modify your C# app so that a 2nd instance can be run from a command line with a particular switch. When you're C# app is called with a particular switch (from the JSLF file), then instead of running normally, you want your program to simply signal a wait handle in the main instance of your application and then close. I use a simple third-party open-source library called XDMessaging, which facilitates such inter-process communication. It lets you open a named channel in your C# app, which can receive a command from the 2nd instance, signaling the main instance that the JSFL script has finished and it's safe to continue.
But involving file watcher like this is not the best solution so I catch the Flash process and keep watch on the process title and tell the JSFL render some window title for the flash window after finish the execution.

Restart other application. C#, .net

I want to restart some process. Lets call it someApp.exe.
How can I restart that process? It's not my application. It's some external program.
What you want to do is:
Kill the process
Start it again
There are some ways of obtaining a Process instance in C#. Let's suppose you know the name of the process:
var process = Process.GetProcessesByName("notepad++")[0];
Then you can do:
process.Kill();
But to start it again, you need to know the path of the process, so before killing it, save the path of the executable:
var path = process.MainModule.FileName;
And then you can do:
Process.Start(path);
You should check if GetProcessesByName returns elements before taking the first element, but I just wanted to focus on the important thing here.
You can use the Process.Start.
http://msdn.microsoft.com/en-us/library/53ezey2s.aspx#Y1400

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...

Kill process started with System.Diagnostic.Process.Start("FileName")

I am trying to create an app that will perform actions on specific times (much like the Windows Task Scheduler). I am currently using Process.Start() to launch the file (or exe) required by the task.
I am initiating a process by calling a file (an .mp3) and the process starts WMP (since it is the default application). So far so good. Now I want to kill that process. I know that it is normal behavior for the Process.Start(string, string) to return nothing (null in C#) in this case.
So I am asking how can I close WMP when I called it through Process.Start(string, string)??
Edit:
Please note that I am not opening WMP directly with Process.Start() and this is the line with which I run the process:
VB: Me._procs.Add(Process.Start(Me._procInfo))
C#: this._procs.Add(Process.Start(this._procInfo))
_procInfo is a ProcessStartInfo instance. _procInfo.FileName is "C:\route\myFile.mp3". That is why WMP opens. In any case, all of the Start() methods, except for the instance-one which returns a boolean, return nothing (null in C#), because WMP is not the process that was directly created (please note that WMP is run and the song does play).
Process.Start(string,string) returns you a Process resource that you can use to further control the new process.
Process newProcess = Process.Start("param1", "param2");
if (newProcess != null && !newProcess.HasExited)
newProcess.Kill();
The same structure works if you use Process.Start(string), or any other static Process.Start overload.
Process.Start() is a member function and associates a new or reused Process with the Process component identified by this. Behaviour of this method depends on the properties of the Process identified by this.
Don't do it this way.
It's not clear whether the intent of your program is 'Always launch with Windows Media Player' or 'Launch with the registered MP3 player', which might be, say, iTunes.
If you need WMP, use Process.Start with the full path to windows media player.
If you need the registed MP3 player, you can find out the correct exe using the code shown here. Again, start the process with this exe path, passing the MP3 as a parameter.
Two ways:
1-
Process customProc = Process.Start("ExecutablePath", "Argument(s)");
customProc.Kill()
2-
Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("ProcessName")
For Each p As Process In pProcess
p.Kill()
Next
If you are letting the registered windows program to open the file, rather than picking the program you want. Then I advise you do not kill the process.
The reason for this is what say your program does use the default application, but that application is already in use, and contains unsaved data. A user would not be happy for your program to overtake there application with the new file and then kill off the process that was already in use by the user for another purpose. Sure, it might not be in use but you must consider the worst case.
As such, I recommend what has been suggested. use Process.Start() with the full path to the program to be used and the file to be opened.
I tried to open .txt file and the process of my text editor was returned, also I tried .mp3 by WMP and it returned null. So it depends on the application. Do you need to run you mp3 only with WMP? If not, you definitely can create the application which will return the Process object.
proc = Process.Start(filename) should work, but like you say, it returns null instead of a process.
That seems to be inherent to Windows Media Player. Other applications return the process. You can get Windows Media Player's process by specifying the application in the start method.
proc = Process.Start("C:\Program Files\Windows Media Player\wmplayer.exe", filename)
Then you can kill it normally.
proc.Kill()
You will probably need to get the location of the application assiciated with .mp3 files from the registry.

Categories

Resources