Reputation: 277
I have a c# application executable in a shared drive. This allows the users (3) with access to the shared drive to open the executable. It is now required that not more than person can run the executable at the same time. I have looked around and the solution seems to be to use mutex, which I don't quite understand. Is there any other solution/workaround for this issue.
Upvotes: 3
Views: 2185
Reputation: 84765
If your operating system and/or network file system support this, you could create a empty file on a network file server (if it does not exist yet) and ask for exclusive write access whenever your application starts.
If your application is not granted exclusive write access, that means that your application might already be running somewhere else on the network. (There is some risk of a false positive here: Perhaps someone just opened the file in an editor out of curiosity, or someone changed the file's permissions.)
When the application terminates, it should close the file handle, thereby releasing the exclusive lock on the file.
Even if your application terminates abnormally, the OS will clean up the process and thereby release the file handle, allowing another instance of your application to claim the file lock.
(Again: This might not work with all operating systems and network file server protocols; I assume this should work on Windows networks and Samba file servers.)
Upvotes: 1
Reputation: 11658
OK, I'll make another attempt, now that additional informaion has been provided.
I don't know for sure if this is viable, but why not have a file on the server that is used as a kind of "one at a time lock file". At the start of the program, open this file for writing. That should place an exclusive lock on it, if it works. If it doesn't work, that indicates that another program currently has the file open for writing, and you say "sorry, program is currently running on another machine." If it does work, then you keep the file open for writing for as long as the program is running. Probably not necessary to explicitly close the file, that should happen automatically when the program terminates, or crashes.
Upvotes: 0
Reputation: 1709
You can create a very very small controlling file, a file with any format, txt or XML add in this file flag
any instance starts, if the flag is true, exit the application else, set the flag to true
And on exit of your application who set the flag to true, revert the flag to false
But this will lock the application in case that the application who locked the flag is turned off up-normally.
So best way is to use the Mutex, or create a small server application on a common place that your application connects to, and use it in the same way of using the file, to set flags; this way, even when the application shuts down in a not normal way, the server will be able to detect that and it will still free the flag status to allow other instance to start.
Edit:
using a file to control the flags, issue when application shuts down up-normally:
This can be fixed using TimeStamp
along with the flag, if the TimeStamp
is older than a certain time, that means no one is using the application, and thus it is allowed to use it, this involves updating this TimeStamp
each period of time while the application is running, like a heartbeat
Upvotes: 3
Reputation: 32455
if you do not want use a Mutex, then you can write in your application code which check all Processes on machine and if same process already found, then exit application
System.Diagnostic.Process.GetProcesses(); // get a array of processes
But this solution have own minuses, because you compare processes only by his name...
Upvotes: 0
Reputation: 11658
Edit: By popular demand, I'll point out that this answer is in response to the questionioner's mentioning of mutex, so I'm assuming he/she wants to limit the number of users per machine. If he/she instead wants to limit total usage in the network, then this is not the way to do it.
Here's what I'm currently using:
// Mutex object used to determine if there are multiple instances of this program running.
// Note that this is a reference to a .Net Mutex object, not the Windows mutex itself.
private static Mutex _onlyOneInstanceMutex;
/// <summary>
/// Method to test that there is not another instance of the program already running on this
/// machine, or at least in this Terminal Services session or Windows Vista / Windows 7
/// concurrent sessions session. If there is, a message box-style localized error message is
/// displayed and the value false is returned. This implies that this method should only be
/// used in WinForms programs.
///
/// This implementation uses a .Net Mutex object in public storage to prevent it from being
/// garbage-collected. The name of the associated Windows mutex is simply the program name as
/// provided by the caller. Neither the .Net Mutex object nor the Windows mutex are ever
/// explicitly released; they remain in existence, perhaps in an "abandoned" state, until the
/// process that created them terminates.
/// </summary>
/// <returns>false if another instance running, otherwise true</returns>
[SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive",
Justification = "Not sure if this is correct or not.")]
public static bool TestOnlyOneInstance(string programName)
{
// Funny construct to prevent the Mutex from being garbage collected
GC.KeepAlive(_onlyOneInstanceMutex);
// Test if we are the first instance, and if so create the Windows mutex, making it
// impossible for subsequent instances to successfully create their mutex
bool firstInstance;
_onlyOneInstanceMutex = new Mutex(false, programName, out firstInstance);
if (firstInstance)
return true;
// Display a (possibly localized) error message, then return
string errorMessage = MLocalizer.GetString("Error1",
"Another instance of this program is already running on this machine.") +
"\n" + MLocalizer.GetString("Error2",
"You cannot run two instances at the same time.") +
"\n" + MLocalizer.GetString("Error3", "Please use the other instance.");
MessageBox.Show(errorMessage, programName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
Upvotes: 1
Reputation: 11232
Use a named mutex. That is the normal way of doing it. Create a named mutex (make sure the name is unique) from your program. The constructor will tell you whether new mutex was created or an existing one was opened using the out bool createdNew
parameter. If this flag is false then one instance of the program is already running.
Upvotes: 0