tags:

views:

2070

answers:

5

I am coding a feature in a program where users can edit documents stored in a database, it saves the document to a temporary folder then uses Process.Start to launch the document into the editing application, let's say Microsoft Word for example.

Then my app needs to wait until they've closed the called process and replace the document in the database with the newly edited copy in the temp folder.

The following code works great as long as the called application isn't already running:

ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName=TempFolder + Path.DirectorySeparatorChar + f.Name;
Process p = new Process();
p.StartInfo = pInfo;
p.Start();
//p is null at this point if called application was already running
//i.e. Microsoft Word is re-used instead of starting a fresh copy
p.WaitForInputIdle();
p.WaitForExit();

Is there a way to force starting a completely new process or can anyone think of another way to handle this. I really don't want the users to be able to do anything else in my app until they've closed the called process because I need to know if they edited that file or not at that point in time, not later when all sorts of other problems could creep up.

A: 

I'm not sure about the starting a new process, but have you considered this logic for waiting until exit:

while (Process.IsRunning) {}

basically just a holder loop until your process is done.

Ian Jacobs
Process is null immediately after calling start if it reuses an existing application.
JohnC
A: 

Yes, subscribe to the process' Exited event and set the process.EnableRisingEvents property to true. Then have your application do nothing until the Exited event gets fired!

And about forcing to use a new process, I think that's the default behavior, I think it depends on the process you're calling if it allows more than one instance running at the same time or not, which is out of your control...unfortunately.

Good Luck!

Ricardo Villamil
Ufortunately two prolems: Process is null immediately after calling start if it reuses and if they already have the app open for another document, I'm frozen out until they close that as well.
JohnC
Hmmm...have you tried getting rid of the last two lines: p.WaitForInputIdle();p.WaitForExit();? Then susbscribe to Exited and set EnableRisingEvents to true before calling start()
Ricardo Villamil
A: 

I think you're using the wrong method the solve the problem. If you're only dealing with word documents I believe you should be using COM interop to word and control word from your app. With COM you can control everything in word, you'll be able to open the document in word and you'll know when the user closed it.

No it's not only word documents, that was just an example, it could be *any* kind of file.
JohnC
A: 

After further research and coming across a number of posts mentioning the unreliability of WaitForExit and the process' Exited event, I've come up with a completely different solution: I start the process and don't bother waiting for it, just pop up a modal dialog in which the user can click on update to update the temporary folder file back into the database when they've edited and saved the temporary file or cancel.

This way it's in their hands and I don't have to rely on the vagaries of Process.Start.

Thanks for everyone's help.

JohnC
+2  A: 

Personally I'm not sure I agree with this approach at all. Displaying a modal form might get you out of this situation, but in most cases when a solution seems hard to find, it's helpful to change the problem you're trying to solve.

Option 1:

In this case, I'd recommend a checkout/checkin model. This would allow users to "checkout" a file to their machine, and then check it in when they have finished updating it. This has a number of benefits:

  • They can edit many documents at once, and perform checkin operations on multiple documents at once.
  • They can apply comments to checkins.
  • The user can shutdown their PC, or go offline and still work on their document.
  • The user can checkout multiple documents locally, then take the work home.
  • You don't have to try and work out what to do if the PC crashes (or the laptop battery runs out) while a document is open, and how to get it all back together again.

The model also fits well with the concept of creating a new document, and adding it to the database. It's the same as a checkin.

You could easily provide reports that display who has what document checked out, and what their "working copy" location is.

I would concede that typically only developers are comfortable with this model, and that you may have to invest in a small amount of re-training. I don't think it would be difficult to setup an automated reminder system that emails people when they've had a document checked out for a long time.

Option 2:

Watch the file using a FileSystemWatcher or equivalent. This would enable you to keep an eye on the file, and when the user performs a save operation, you can commit to the database. After all, it's only if the user actually saved the file that you're interested in updating the database,

Neil Barnwell
Option one is a great idea and will be useful for others who come across this; if document management was the central point of the app. I'd go that route but this is a side feature and the modal dialog is both simple and bulletproof, two things I like in software I have to support. :)
JohnC
Option two I would be very wary of using, I considered it but came across a lot of posts online about trouble with it and even it's own docs mention numerous potential problems with the buffer length and long file names etc. Too fragile I think for my purposes but could be useful to others.
JohnC