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 WaitForSingleObject 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 WaitForSingleObject 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 WaitForSingleObject 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...
Related
Is there a way to detect when a file is open by another process?
I've tried the following
Search for handles in processes to get if file is open
This only helps for programs that keep the file open for use. but doesn't work for even simple apps like notepad.exe, notepad++ that close the file immediately after loading to memory.
Continuously check for the Date Accessed property of the file to know it was opened when it changes.
Doesn't work since it doesn't change when file is opened. eg I opened and read it in notepad but never changed.
Use FileSystemWatcher to get event triggered when file is opened
Only can works for events such as Changed, Created, Deleted, Renamed.... and doesn't detect when file is opened.
So is there any way to detect this? I am thinking it is possible because most antiviruses can sharply detect and block infected when files are opened.
Language used: C#
Theory:
I want to create a file with the flag FileOptions.DeleteOnClose in a temporary folder.
The file is successfully created and I write dato onto it, the next step is to launch the application associated with the file Process.Start(...) and allow the user to inspect the document, finally I close my handle and as soon as other process close the handle to the temporary file, the file is deleted by operating system.
My problem is that other processes cannot open the file, even for reading, despite if I add FileShare.ReadWrite | FileShare.Delete to the sharing mode.
Any suggestions?
The other processes need to specify FileShare.Delete when they open the DeleteOnClose file
From the MSDN CreateFile docs:
"FILE_FLAG_DELETE_ON_CLOSE... Subsequent open requests for the file fail, unless the FILE_SHARE_DELETE share mode is specified."
Check this:
You need to make sure that all processes are opening the file with FileShare.ReadWrite and FileShare.Delete.
Even if the creator opens with share-readwrite, if a second program tries to open with share-read, the second program is basically saying no-one else can write. But the first program already has that power so the second open fails.
Switch to Linux scnr
Ok, seriously now: That is a flaw in the Windows operating system which can't really be worked around. Each program opening the file must agree on other programs having the file open in the same time. That was a problem I got many years back when I still used Windows as well. It doesn't suffice to open a file and say: Let anyone else open this as well. The others must also say open this file even if it's open already.
On Linux on the contrary, the operating system doesn't allow any file locking in the way Windows does at all. Here, if any file is used by more than one program simultaneously, the programs itself must make sure, that concurrent accesses get locked out. Additionally, on Linux, we can just create the file, make sure the other process has been started and opened the file and then just delete the file (while it is open). The filename is then removed from the file system immediatelly, but the file is still maintained by the file system driver until the last link (including open file handles) got removed.
Back to your problem: As all of this doen't work on Windows, you could do two other approaches:
Register the file to be deleted on next boot (in the Win3x days, there was a section in the win.ini for that. Newer Windows version still support that, I just can't recall any longer, how it's done now).
Start the other process, wait for it to open the file, close the file and then try each minute to delete the file until deletion succeeds ...
Regards, Bodo
To be honest, I can't say I actually know where to begin with this question. So, I'll start from the beginning.
I have C# code that invokes Process.Start based on a OFD box. Basically allowing the user to open anything from the box, this is absolutely intended.
System.Diagnostics.ProcessStartInfo starter = new System.Diagnostics.ProcessStartInfo(OFPbasicfile.FileName);
starter.UseShellExecute = true;
System.Diagnostics.Process alpha = new System.Diagnostics.Process();
alpha = System.Diagnostics.Process.Start(starter);
Now, it perfectly executes and opens, but I've noticed something of an odd duck. If the first file opens say a .docx file I can then read alpha.ID just fine. However, the next time it opens a .docx file alpha.ID will be assigned a new process ID that corresponds to nothing in the task list. Worse yet, I get absolutely no useful information from alpha as it now has a handler to a non-existent process.
Near as I can figure this is probably something to do with the fact that the program doesn't realize everything perfectly. It tries to create a new process and reserves the ID for it, but then the running instance of word, etc. takes ownership of the started file and my program never gets advised of this change.
Ideally I was trying to find a way to track any and every file opened (process ID, window handles, however worked), but now I'd be more than happy if alpha would just recognize that the process is opened by Word (Or Excel, or what have you).
The basic question boils down to this: When using Process.Start is there any way to ensure it gives the proper process ID (or just the program used to open it) every time?
Or, alternatively: Is there any way to set a process variable with a reference to the exact window it opened?
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.
Language used: C#
Theory:
I want to create a file with the flag FileOptions.DeleteOnClose in a temporary folder.
The file is successfully created and I write dato onto it, the next step is to launch the application associated with the file Process.Start(...) and allow the user to inspect the document, finally I close my handle and as soon as other process close the handle to the temporary file, the file is deleted by operating system.
My problem is that other processes cannot open the file, even for reading, despite if I add FileShare.ReadWrite | FileShare.Delete to the sharing mode.
Any suggestions?
The other processes need to specify FileShare.Delete when they open the DeleteOnClose file
From the MSDN CreateFile docs:
"FILE_FLAG_DELETE_ON_CLOSE... Subsequent open requests for the file fail, unless the FILE_SHARE_DELETE share mode is specified."
Check this:
You need to make sure that all processes are opening the file with FileShare.ReadWrite and FileShare.Delete.
Even if the creator opens with share-readwrite, if a second program tries to open with share-read, the second program is basically saying no-one else can write. But the first program already has that power so the second open fails.
Switch to Linux scnr
Ok, seriously now: That is a flaw in the Windows operating system which can't really be worked around. Each program opening the file must agree on other programs having the file open in the same time. That was a problem I got many years back when I still used Windows as well. It doesn't suffice to open a file and say: Let anyone else open this as well. The others must also say open this file even if it's open already.
On Linux on the contrary, the operating system doesn't allow any file locking in the way Windows does at all. Here, if any file is used by more than one program simultaneously, the programs itself must make sure, that concurrent accesses get locked out. Additionally, on Linux, we can just create the file, make sure the other process has been started and opened the file and then just delete the file (while it is open). The filename is then removed from the file system immediatelly, but the file is still maintained by the file system driver until the last link (including open file handles) got removed.
Back to your problem: As all of this doen't work on Windows, you could do two other approaches:
Register the file to be deleted on next boot (in the Win3x days, there was a section in the win.ini for that. Newer Windows version still support that, I just can't recall any longer, how it's done now).
Start the other process, wait for it to open the file, close the file and then try each minute to delete the file until deletion succeeds ...
Regards, Bodo