Single Instance Application in C++/CLI using Mutex - c#

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);

Related

Using Mutex to track another app's lifetime

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);

Mutex kills application

This is my code:
protected override async void OnStartup(StartupEventArgs e)
{
// Used to check if we can create a new mutex
bool newMutexCreated = false;
try
{
// Create a new mutex object with a unique name
mutex = new Mutex(false, MutexName, out newMutexCreated);
}
catch (Exception ex)
when (ex is UnauthorizedAccessException ||
ex is IOException ||
ex is WaitHandleCannotBeOpenedException ||
ex is ArgumentException)
{
Logger.Error("Error while launching application. Failed to check for other instances.", ex);
Shutdown((int)ExitCode.ApplicationAlreadyRunning);
}
// When the mutex is created for the first time
// we run the program since it is the first instance.
if (newMutexCreated)
{
await ContinueStartup(e);
return;
}
else
{
// Otherwise we get the first instance with that process name,
Process[] currentProcesses = Process.GetProcessesByName(AssemblyName);
IntPtr mainWindowHandle = currentProcesses[0].MainWindowHandle;
if (mainWindowHandle != IntPtr.Zero)
{
// maximize it, if it was minimized, and set it to foreground.
Logger.Info("Another instance of the application is already running.");
ShowWindow(mainWindowHandle, WindowShowNormal);
SetForegroundWindow(mainWindowHandle);
}
// Then shutdown this instance.
Logger.Info("Shutting down.");
Shutdown((int)ConsoleModeExitCode.ApplicationAlreadyRunning);
}
}
protected override void OnExit(ExitEventArgs e)
{
Logger.Info("Exiting application.");
// Close mutex.
mutex.Dispose();
base.OnExit(e);
}
What happens here is that my application should start once. While it is running, every attempt to start a new instance should bring the first instance to the front.
But what actually happens is: after 2-10 launch-attempts the first instance's GUI is killed, the process is still running and blocking the Mutex and can only be killed in the TaskManager. If I try to debug this behaviour and run the application in VisualStudio, it just never happens. Trying to open the application 50 times never kills it, so I can't follow the events that seem to occur.
Is it normal behaviour of the GarbageCollector? It kills the first instance in case it is hanging?
Or am I missing something?
Okay, as #Luaan mentioned the problem was not the Mutex.
I fixed my code with this solution:
https://stackoverflow.com/a/9059657/3319147
ShowWindowAsync and a slightly different handling of the IntPtr-value of the handle seems to make this way more stable. Couldn't crash it since. For me this is enough stability :)

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");

Silently update a Windows service

I have built a Windows service, now I want it to auto-update. I have read about a creating a second service to do that or different program , cant use click one, what about myBuild? Does anyone know it? What is the best way? Can I just change assemblies?
If you want your service to run while you are performing an update, here is what I had done before to achieve this:
Put your updateble logic into a separate DLL.
Create an AppDomain within your service.
Create file monitor that fires an event whenever you copy that file (you can use MSFT Ent Lib Updates)
Unload the old dll while blocking (queue) the threads that execute stuff from that dll
Load in the new dll file into the app domain.
Let your threads know to continue processing.
Download the new exe and any additional assembly's.
Rename your existing assembly's.
Copy in your new assembly's.
Restart Service. You can build the service restart function into your main service exe.
When service starts check for renamed files from step 2 and delete them to clean up.
To restart your service do
System.Diagnostics.Process.Start
(System.Reflection.Assembly.GetEntryAssembly().Location)
Then in your service do
private const string _mutexId = "MyUniqueId";
private static Mutex _mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
try
{
bool alreadyRunning = false;
try
{
Mutex.OpenExisting(_mutexId);
alreadyRunning = true;
}
catch (WaitHandleCannotBeOpenedException)
{
alreadyRunning = false;
}
catch
{
alreadyRunning = true;
}
if (alreadyRunning)
{
using (ServiceController sc = new ServiceController("MyServiceName"))
{
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 120));
sc.Start();
}
return;
}
}
catch
{
}
_mutex = new Mutex(true, _mutexId);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
// Load the service into memory.
ServiceBase.Run(ServicesToRun);
_mutex.Close();
}
You could modify your Windows Service so that it is simply a runner for your main application, and has the functionality to update your main application.
So you would have:
Service.exe: Runs Application.exe, monitors remote location for updates to Application.exe. Sends start/stop events to Application.exe
Application.exe : What used to be your Service.exe. Recieves start/stop events.

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