How to make a single instance application refresh with command line args
Hi all,
I'm using a named mutex to ensure that my C# Windows Forms Application is only running in a single instance, on Windows. The program I'm writing is an image viewing program, and it takes in the path to the image to display through command a command line argument.
I'm needing to know the best way to have my original, first instance of the image viewer program load up any image path that is passed to a new instance of the program. I just want this to be a seamless process - "pass path to image to the image viewer app, if it isn't running then start a new process, if it's already running then use the running one to display the image".
Right now I'm just killing the original process, and starting up a new one if there was one already running. This works, but it's not pretty. I'd like the one that is already running to just display the newly specified image.
Re: How to make a single instance application refresh with command line args
You'll need to use some sort of interprocess communication for the 2nd instance to communicate with the 1st instance. Once the 2nd instance passes the new path data to the 1st instance, it will exit as it does now.
One way to do this in C# is to use WCF and make a small WCF web service hosted by your process. When the 2nd instance starts up, it simply passes the path info to the web service (which runs in the context of the 1st instance). The 1st instance would just use this info to display the new image.
Re: How to make a single instance application refresh with command line args
Here's a sample that passes the data using WCF.
Code:
namespace SingleInstanceWcf
{
#region Using Directives
using System;
using System.ServiceModel;
using System.Threading;
#endregion Using Directives
// Declare a simple WCF service interface
// to pass data between two instances of
// the same application
[ServiceContract]
publicinterfaceILauncher
{
[OperationContract]
void OpenImage( string path );
}
publicclassLauncher : ILauncher
{
publicvoid OpenImage( string path )
{
Console.WriteLine ( String.Format ( "Image opened from 1st instance {0}", path ) );
}
}
classProgram
{
staticvoid Main( string [ ] args )
{
bool newInstance = false;
// Restrict the app to a single instance using a named mutex.
Mutex singleMtx = newMutex ( true, "{8cdaba99-857c-44d7-bfc1-b66b347965c2}", out newInstance );
// Check if we're the 2nd instance. If so, use the WCF service
// to pass the path data to the 1st instance
if ( !newInstance )
{
if ( args.Length == 0 )
{
Console.WriteLine ( "Error: 2nd instance must pass in image path as a cmd parameter" );
return;
}
// Connect to the 1st instance using wcf and pass the image path
using ( ChannelFactory<ILauncher> factory = newChannelFactory<ILauncher> ( "ILauncherServiceConfig" ) )
{
ILauncher channel = factory.CreateChannel ( );
channel.OpenImage ( args [ 0 ] );
}
// Exit the app after passing the path data to the 1st instance
return;
}
//
// 1st instance code
//
// Host the WCF service
ServiceHost host = newServiceHost ( typeof ( SingleInstanceWcf.Launcher ) );
host.Open ( );
// Wait for 60 seconds before exiting the app
System.Threading.Thread.Sleep ( 60000 );
// Shutdown the WCF Service
host.Close ( );
}
}
}
Re: How to make a single instance application refresh with command line args
Just throw a spanner in the works I dont think mutexs are a great way of implementing single instance application, I know they have failed for me once or twice on the rare occasion.
I now create a file in some preset common location say (Application.CommonAppDataPath + "\lock.file") an test for a file lock on startup of each instance as for passing command line args there are a few ways least of all sending messages to the processes window this seems to work particularly well.
Re: How to make a single instance application refresh with command line args
A named mutex is the defacto way to limit an app to a single instance. How did it fail "in rare instances" for you? How did you code the mutex to check for the single instance?
Re: How to make a single instance application refresh with command line args
using a semaphore file is definitely one way to produce the single instance application. I think it's less elegant (and far less useful) than using a mutex, but it does solve the denial of service issue that can occur with mutexes.
unless you just didn't implement it right, mutexes will always work (that's their entire purpose in life is to work).
Last edited by MadHatter; October 30th, 2009 at 03:38 PM.
Re: How to make a single instance application refresh with command line args
Fair enough, I know vey little about mutexs except how to implement them in the simple circumstances (ie try to apply mutex,catch an error => another instance is running) so its more likely there was an error in the code.
One of the times I remember it failing was when the same app was run from two diffrent users, Im guessing mutexs aren't desinged to work across users.
Usually I use single instances because I dont want data saved on the disk to be corrupted, so the filelock approch will only fail if each instance is looking at a different directory but if thats the case the data isnt shared so it cant be corrputed.
Re: How to make a single instance application refresh with command line args
So what happens if your app crashes the the file isn't deleted? Suddenly the app can't be started up anymore. At least with the mutex approach this can be detected.
NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.
Re: How to make a single instance application refresh with command line args
Originally Posted by Mutant_Fruit
So what happens if your app crashes the the file isn't deleted?
No you maintain a file lock, the mere existence of the file doesn't indicate anything, only the failure to obtain the lock indicates a second instance of the application.
I think firefox uses this method:
"%appdata%\Roaming\Mozilla\Firefox\Profiles\%profile%\.parentlock"
This approach as yet to fail for me, and I find it simple to understand and implement.
Re: How to make a single instance application refresh with command line args
I'm pretty sure the reason moz uses this is because they're platform independent, so they have to utilize a common SI methodology to be consistent across the realm.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.