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.
Related
I'm using a FileSystemWatcher to watch a directory. I created a _Created() event handler to fire when a file is moved to this folder. My problem is the following:
The files in this directory get created when the user hits a "real life button" (a button in our stock, not in the application). The FileSystemWatcher take this file, do some stuff in the system and then delete it. That wouldn't be a problem when the application runs only once. But it is used by 6 clients. So every application on every client is trying to delete it. If one client is too slow, it will throw an exception because the file is already deleted.
What I'm asking for is: Is there a way to avoid this?
I tried using loops and check if the file still exists, but without any success.
while (File.Exists(file))
{
File.Delete(file);
Thread.Sleep(100);
}
Can someone give me a hint how it could probably work?
Design
If you want a file to be processed by a single instance only (for example, the first instance that reacts gets the job), then you should implement a locking mechanism. Only the instance that is able to obtain a lock on the file is allowed to process and remove it, all other instances should skip the file.
If you're fine with all instances processing the file, and only care that at least one of them succeeds, then you need to figure out which exceptions indicate a genuine failure and which ones indicate a failure caused by the actions of another instance.
Locking
To 'lock' a file, you can open it with share-mode FileShare.None. This prevents other processes from opening it until you close the file. However, you'll then need to close the file before you can delete it, which leaves a small gap during which another instance could open the file.
A better solution is to create a separate lock file for that purpose. Create it with file-mode FileMode.Create and share-mode FileShare.None and keep it open until the whole process is finished, including the removal of the processed file. Then the lock file can be closed and optionally removed.
Exception
As for the UnauthorizedAccessException you got, according to the documentation, that means one of 4 things:
You don't have the required permission
The file is an executable file that is in use
The path is a directory
The file is read-only
1 and 4 seem most likely in this case (if the file was open in another process you'd get an IOException).
If you want to synchronize access between multiple clients on the same computer you should use a Named Mutex.
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.
here is my question:
I have developed a program that uses Microsoft.Excel COM components in order to read/write over Excel files. Well, my app is doing good but when I open, for instance, another file directly with Excel while my program is running, the file(s) that my app uses appear within Excel. I do not want this. I tried also the Visibility property of Excel Application class, but that was not the solution, it just does not work.
NOTE : I have checked this question out.
Restrict access to excel file opened by C# program
Yet, it says no proper solution actually.
You can use Application.IgnoreRemoteRequests = true. This will avoid users opening excel files in the same Excel process as the one you are using.
There is one caveat though: you have to make sure that all execution paths of your application reset this property to false. This property WILL NOT reset itself when you quit and release your Excel application which means that Excel will not respond correctly to a subsequent user who double clicks on a *.xls file for example.
EDIT: Possible issues with IgnoreRemoteRequest
Ok, to make this clearer I'll detail a little bit more what issues you can run into using this feature (at least these are the only ones I've run into when I had to use this feature).
When setting IgnoreRemoteRequests = true you have to make sure you reset this property BEFORE quiting and/or releasing the COM Excel application. If you don't, Excel will not respond to DDE requests which means if someone double clicks on a *.xls file, the file will not open (Excel will start up, but it wont open the file automatically).
This however is only true if you quit the application and/or release it without reseting the property. You just have to make sure that wherever it is in your code that you are quitting/resetting you set the IgnoreRemoteRquests back to false before.
If you'r application crashes and it hasn't been able to clean up (unhandled exception) then the EXCEL process will keep running (if invisible, you will only see it in the Task Manager). That is normal as your app didnt have a chance to quit and release the internal Excel it is using. This however is not an issue. If a user ignores this "leaked" Excel process until it's eventually killed in next reboot or whatever, or manually kills it from the task bar, Excel will work perfectly fine.
Note: MS Excel 2007. Don't know about behavior of previous versions.
Have you tried running your program under a service account? This should avoid the excel com object interfering with the instance used by the logged in console user, so they will not see the effects of your com objects. It's probably also better security practice to run COM type applications under a service account instead of a user account as well, but that's for another question.
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
Is there a built in method for waiting for a file to be created in c#? How about waiting for a file to be completely written?
I've baked my own by repeatedly attempting File.OpenRead() on a file until it succeeds (and failing on a timeout), but spinning on a file doesn't seem like the right thing to do. I'm guessing there's a baked-in method in .NET to do this, but I can't find it.
What about using the FileSystemWatcher component ?
This class 'watches' a given directory or file, and can raise events when something (you can define what) has happened.
When creating a file with File.Create you can just call the Close Function.
Like this:
File.Create(savePath).Close();
FileSystemWatcher can notify you when a file is created, deleted, updated, attributes changed etc. It will solve your first issue of waitign for it to be created.
As for waiting for it to be written, when a file is created, you can spin off and start tracking it's size and wait for it stop being updated, then add in a settle time period, You can also try and get an exclusive lock but be careful of locking the file if the other process is also trying to lock it...you could cause unexpected thigns to occur.
FileSysWatcher cannot monitor network paths. In such instances, you manually have to "crawl" the files in a directory -- which can result in the above users error.
Is there an alternative, so that we can be sure we don't open a file before it has been fully written to disk and closed?