Using Mutex to track another app's lifetime - c#

MyApp1 (C#) launches MyApp2 (C#). When MyApp2 is fully up, it executes:
new Mutex(true, "MyApp2IsRunning");
Meanwhile, MyApp1 has been waiting for this to happen using:
Mutex myApp2Mutex = null;
while (myApp2Mutex == null && !timedOut)
{
try
{
myApp2Mutex = Mutex.OpenExisting("MyApp2IsRunning");
}
catch(WaitHandleCannotBeOpenedException)
{
Thread.Sleep(100);
}
}
if (timedout) {return error;}
myApp2Mutex.WaitOne();
So if MyApp2 launches within the allotted time, MyApp1 now waits on the MyApp2IsRunning mutex to know when user has exited MyApp2.
I'm rewriting only MyApp1 in C++. What is the equivalent Mutex-related code to detect MyApp2's status? So MyApp1 will still be responsible for launching MyApp2, and I still want it to detect when MyApp2 is up and when the user has exited MyApp2. Same code as above, but in C++.

A simple google search give you:
HANDLE mutex_you_want = CreateMutex(nullptr, true, "MyApp2IsRunning");

This pseudocode enables MyApp1 to wait for MyApp2 to launch and then detect when user exits MyApp2:
HANDLE hMutex = nullptr;
while (hMutex == nullptr && !timedout)
{
hMutex = OpenMutex(
SYNCHRONIZE,
FALSE,
"MyApp2IsRunning");
Sleep(1000);
}
if (timedout){return error;}
DWORD wait_result = WaitForSingleObject(hMutex, INFINITE);

Related

Single Instance Application in C++/CLI using Mutex

I am developing a tray icon based application in C++ CLI. I am using Mutex to ensure single instance of my application running at a time. But each time a new instance starts, the current instance's window should go active.
I am sending a message to the window using PostMessage(Pinvoke). But after 3 or 4 successive run, my application crashes.
Any ideas why that happen. please help!!
The code I have written in the main() function is,
Mutex ^mutex = gcnew Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
if (mutex->WaitOne(TimeSpan::Zero, true))
{
// New Instance. Proceed......................
}
else// An instance is already running. Activate it and return
{
// send our Win32 message to make the currently running instance
// jump on top of all the other windows
try
{
HWND hWindow = FindWindow( nullptr, "MyWindow" );
if(hWindow)
PostMessage(hWindow, WM_ACTIVATE_APP, nullptr,nullptr);
}
catch(Exception^ Ex)
{
}
return -1;
}
Thanks & Regards,
Rohini
Try this instead of PostMessage():
ShowWindowAsync(hWindow, 1); // SW_SHOWNORMAL
SetForegroundWindow(hWindow);

Thread will not close, doesn't seem to reach changed variable

I am working on a multiplayer game, using the lidgren library for networking.
I am currently having issues with a my function that reads messages sent from my server.
The function looks like this:
public class Client
{
/* code omitted */
public void ReadMessage()
{
//Read Messages
while (running)
{
Debug.Log("InREAD");
//wClient is a NetClient (lidgren library)
NetIncomingMessage msg;
while ((msg = wClient.ReadMessage()) != null)
{
switch (msg.MessageType)
{
case NetIncomingMessageType.Data:
if (msg.ReadString().Contains("Position"))
{
Debug.Log("Hej");
/*string temp = msg.ReadString();
string[] Parts = temp.Split(" ");
int x = int.Parse(Parts [1]);
int y = int.Parse(Parts [2]);
int z = int.Parse(Parts [3]);*/
//set player position to xyz values below
} else if (msg.ReadString().Contains("Instantiate"))
{
Debug.Log("Instantiate");
/* string temp = msg.ReadString();
string[] Parts = temp.Split(" ");*/
}
break;
}
}
}
}
}
as you can see, there is a while-loop that runs when the bool running is true (and yes I am setting it as true when declaring.).
Now, in my GUI class where the button for connecting is etc, I have a function call to OnApplicationQuit which looks like this:
void OnApplicationQuit()
{
client.running = false;
client.Disconnect();
Debug.Log(client.running);
Debug.Log("Bye");
}
However, the change of running doesn't reach the thread (I believe the thread is running on a cached version of the variable?). So my question is, how do i make the while-loop stop when the program is closed? (Ive tried calling on the .Abort() function on the thread in the OnApplicationQuit(), but it doesn't work either.
Also, i know its not very efficient to send strings over a network unless you need to (so no need telling me about that!)
Just guessing (since I do not know library lidgren): isn't it possible that you're thread is stuck in call wClient.ReadMessage() just because you are not receiving any message from the client? If wClient.ReadMessage() is a blocking call then the resulting behaviour would be the one you described.
Furthermore: even calling Thread.Abort() won't work because the thread is in a sleep state (since it is waiting for something coming from the network connection): the thread will be aborted as soon as your wClient.ReadMessage() returns. Looking MSDN here it tells that "If Abort is called on a managed thread while it is executing unmanaged code, a ThreadAbortException is not thrown until the thread returns to managed code" and this exactly your situation assuming that ReadMessage() at some point will perform a system call just to wait for some data coming from the underlying socket.
You must call client.Shutdown().

Start an offline ClickOnce Application and wait for Exit

I have deployed a ClickOnce Windows Forms application (App A)
Another application (App B) starts App A with a filename as parameter.
I do this with this Code
var basePath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
var location = String.Format(#"{0}\{1}\{2}\{3}",
basePath, "MyCompany", "MyProduct", "MyApp.appref-ms");
var fileName = #"c:\temp\somefile.ext";
var uri = new Uri(fileName).ToString();
Process.Start(location, uri);
App A grabs the file name from AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0] and show the content.
This works like a charm. However, now I want App B to wait for App A to exit.
But a call to Process.WaitForExit() returns instantly.
Is there a way to open a ClickOnce App and wait for it to exit? I can, if necessary, change the way the app is opend but the requirement is that I need to run the app as a ClickOnce app (I know that somewhere in my user profile AppData\Local\Apps\2.0\ folder the exe exists and can be started directly but If I do that ApplicationDeployment.IsNetworkDeployed is false and ApplicationDeployment.CurrentDeployment is null. In that I loose the ClickOnce Update Capabilities).
my suggestion would be to use Mutex in App A, and let App B check and wait for it. This is the cleanest way from my point of view.
App A does this when starts:
private static Mutex mutex;
public static void Main()
{
// if you want your app to be limited to a single instance
// across ALL SESSIONS (multiple users & terminal services), then use the following line instead:
// string mutexName = string.Format("Global\\{0}", ProgramInfo.AssemblyGuid);
var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
mutex = new Mutex(true, mutexName, out singleInstance);
if (singleInstance == false)
{
// that means your app has more than one instance running
// you need to decide what to do here.
}
// rest of initialization code
Application.Run();
// release the mutex so App B can continue
mutex.ReleaseMutex();
}
and App B just waits for the mutex to be released:
Process.Start(location, uri);
Thread.Sleep(5000); // give it 5 seconds or so to check for updates and start
var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
mutex = new Mutex(false, mutexName);
mutex.WaitOne();
The problem is that starting the appref-ms process does not actually start the application it starts the deployment manifest, which then launches the application itself, so the process you are starting exits straight away.
You can add a check to see when you application has started if you know the name (which I assume you do) like this:
string myAppName = "YourAppName";
DateTime startTime = DateTime.Now;
int newProcessId = 0;
List<int> runningProcessIds = new List<int>();
//find all the running processes and record their Ids
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
proc = proc_loopVariable;
runningProcessIds.Add(proc.Id);
}
//start the new process
Process.Start(location);
//wait for the new application to be started
while (!(Process.GetProcessesByName(myAppName).Count != runningProcessIds.Count)) {
//timeout if we have not seen the application start
if ((DateTime.Now - startTime).TotalSeconds > 30)
break;
}
//loop through all the running processes again to find the id of the one that has just started
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
proc = proc_loopVariable;
if (!runningProcessIds.Contains(proc.Id)) {
newProcessId = proc.Id;
break;
}
}
//wait for the application to finish
Process.GetProcessById(newProcessId).WaitForExit();
Debug.WriteLine("Finished");

How do I programmatically use the "using" keyword in C#?

I have some System.Diagnotics.Processes to run. I'd like to call the close method on them automatically. Apparently the "using" keyword does this for me.
Is this the way to use the using keyword?
foreach(string command in S) // command is something like "c:\a.exe"
{
try
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
catch (Exception e)
{
// notify of process failure
}
}
I'd like to start multiple processes to run concurrently.
using(p = Process.Start(command))
This will compile, as the Process class implements IDisposable, however you actually want to call the Close method.
Logic would have it that the Dispose method would call Close for you, and by digging into the CLR using reflector, we can see that it does in fact do this for us. So far so good.
Again using reflector, I looked at what the Close method does - it releases the underlying native win32 process handle, and clears some member variables. This (releasing external resources) is exactly what the IDisposable pattern is supposed to do.
However I'm not sure if this is what you want to achieve here.
Releasing the underlying handles simply says to windows 'I am no longer interested in tracking this other process'. At no point does it actually cause the other process to quit, or cause your process to wait.
If you want to force them quit, you'll need to use the p.Kill() method on the processes - however be advised it is never a good idea to kill processes as they can't clean up after themselves, and may leave behind corrupt files, and so on.
If you want to wait for them to quit on their own, you could use p.WaitForExit() - however this will only work if you're waiting for one process at a time. If you want to wait for them all concurrently, it gets tricky.
Normally you'd use WaitHandle.WaitAll for this, but as there's no way to get a WaitHandle object out of a System.Diagnostics.Process, you can't do this (seriously, wtf were microsoft thinking?).
You could spin up a thread for each process, and call `WaitForExit in those threads, but this is also the wrong way to do it.
You instead have to use p/invoke to access the native win32 WaitForMultipleObjects function.
Here's a sample (which I've tested, and actually works)
[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
static extern uint WaitForMultipleObjects( uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds );
static void Main( string[] args )
{
var procs = new Process[] {
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'" ) };
// all started asynchronously in the background
var handles = procs.Select( p => p.Handle ).ToArray();
WaitForMultipleObjects( (uint)handles.Length, handles, true, uint.MaxValue ); // uint.maxvalue waits forever
}
For reference:
The using keyword for IDisposable objects:
using(Writer writer = new Writer())
{
writer.Write("Hello");
}
is just compiler syntax. What it compiles down to is:
Writer writer = null;
try
{
writer = new Writer();
writer.Write("Hello");
}
finally
{
if( writer != null)
{
((IDisposable)writer).Dispose();
}
}
using is a bit better since the compiler prevents you from reassigning the writer reference inside the using block.
The framework guidelines Section 9.3.1 p. 256 state:
CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.
In your code example, the outer try-catch is unnecessary (see above).
Using probably isn't doing what you want to here since Dispose() gets called as soon as p goes out of scope. This doesn't shut down the process (tested).
Processes are independent, so unless you call p.WaitForExit() they spin off and do their own thing completely independent of your program.
Counter-intuitively, for a Process, Close() only releases resources but leaves the program running. CloseMainWindow() can work for some processes, and Kill() will work to kill any process. Both CloseMainWindow() and Kill() can throw exceptions, so be careful if you're using them in a finally block.
To finish, here's some code that waits for processes to finish but doesn't kill off the processes when an exception occurs. I'm not saying it's better than Orion Edwards, just different.
List<System.Diagnostics.Process> processList = new List<System.Diagnostics.Process>();
try
{
foreach (string command in Commands)
{
processList.Add(System.Diagnostics.Process.Start(command));
}
// loop until all spawned processes Exit normally.
while (processList.Any())
{
System.Threading.Thread.Sleep(1000); // wait and see.
List<System.Diagnostics.Process> finished = (from o in processList
where o.HasExited
select o).ToList();
processList = processList.Except(finished).ToList();
foreach (var p in finished)
{
// could inspect exit code and exit time.
// note many properties are unavailable after process exits
p.Close();
}
}
}
catch (Exception ex)
{
// log the exception
throw;
}
finally
{
foreach (var p in processList)
{
if (p != null)
{
//if (!p.HasExited)
// processes will still be running
// but CloseMainWindow() or Kill() can throw exceptions
p.Dispose();
}
}
}
I didn't bother Kill()'ing off the processes because the code starts get even uglier. Read the msdn documentation for more information.
try
{
foreach(string command in S) // command is something like "c:\a.exe"
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
}
catch (Exception e)
{
// notify of process failure
}
The reason it works is because when the exception happens, the variable p falls out of scope and thus it's Dispose method is called that closes the process is how that would go. Additionally, I would think you'd want to spin a thread off for each command rather than wait for an executable to finish before going on to the next one.

How can I check for a running process per user session?

I have a .NET application that I only allow to run a single process at a time of, however that app is used on Citrix boxes from time to time, and as such, can be run by multiple users on the same machine.
I want to check and make sure that the application is only running once per user session, because right now if user A is running the app, then user B gets the "App already in use" message, and should not.
This is what I have now that checks for the running process:
Process[] p = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
if (p.Length > 1)
{
#if !DEBUG
allowedToOpen &= false;
errorMessage +=
string.Format("{0} is already running.{1}", Constants.AssemblyTitle, Environment.NewLine);
#endif
}
EDIT: Improved the answer according to this cw question ...
You can use a mutex for checking wether the app already runs:
using( var mutex = new Mutex( false, AppGuid ) )
{
try
{
try
{
if( !mutex.WaitOne( 0, false ) )
{
MessageBox.Show( "Another instance is already running." );
return;
}
}
catch( AbandonedMutexException )
{
// Log the fact the mutex was abandoned in another process,
// it will still get aquired
}
Application.Run(new Form1());
}
finally
{
mutex.ReleaseMutex();
}
}
Important is the AppGuid - you could make it depend on the user.
Maybe you like to read this article: the misunderstood mutex
As tanascius already say, you can use the Mutex.
On a server that is running Terminal Services, a named system mutex can have two levels of visibility. If its name begins with the prefix "Global\", the mutex is visible in all terminal server sessions. If its name begins with the prefix "Local\", the mutex is visible only in the terminal server session where it was created.
Source: msdn, Mutex Class
Just stating the obvious - although Mutex is usually considered better solution, you can still solve the single-instance-per-session issue without Mutex - just test the SessionId as well.
private static bool ApplicationIsAlreadyRunning()
{
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
// test if there's another process running in current session.
var intTotalRunningInCurrentSession = processes.Count(prc => prc.SessionId == currentProcess.SessionId);
return intTotalRunningInCurrentSession > 1;
}
Source (no Linq)
If Form1 launches non-background threads, and that Form1 exits, you've got a problem: the mutex is released but the process is still there. Something along the lines below is better IMHO:
static class Program {
private static Mutex mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createdNew = true;
mutex = new Mutex(true, #"Global\Test", out createdNew);
if (createdNew) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else {
MessageBox.Show(
"Application is already running",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
}
The mutex won't be released as long as the primary application domain is still up. And that will be around as long as the application is running.

Categories