Rick Glos Life in Portland, Oregon.

WPF Application Single Instance Detection - Only allow running your application once

14. June 2013 09:57 by Rick Glos in Programming

I have a requirement where I only want the application to be launched once.  If a subsequent launch of the application occurs, I want it to not pop-up a message to the user but to gracefully select the existing application that has already been launched, therebye preventing multiple launches of the same application.

The current application I’m targeting is a utility application (WoT Kit) I’ve written for World of Tanks that parses your battle results.  Part of the parsing process involves using an external 3rd parties site to convert the battle results from binary python in JSON.  The application uploads the binary file and gets back a string of JSON.  The guy running the website emailed me because he saw the same file getting uploaded in his logs.  Further investigation points to a user running the application more than once, most likely by accident as sometimes we get a lot of applications running.

So how is this done using a WPF application?  Further complicating this is that I’m using the Prism Patterns & Practices libraries for composite WPF applications.  I lean on this often for work related projects so this is useful in many scenarios.

Implement the Main method

First we need to take over how the application is launched.  In a WPF application, the entry point is generated for you.  If you select the option to view all files, you’ll see in your obj\$(Configuration) folder a App.g.cs file that contains the code that is the entry point.

6-14-2013 9-15-47 AM

   1:/// <summary>
   2:/// App
   3:/// </summary>
   4:public partial class App : System.Windows.Application {
   5:
   6:/// <summary>
   7:/// Application Entry Point.
   8:/// </summary>
   9:        [System.STAThreadAttribute()]
  10:        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
  11:        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
  12:public static void Main() {
  13:            WoTBattleResultsKit.App app = new WoTBattleResultsKit.App();
  14:            app.Run();
  15:        }
  16:    }

Instead we want to be in control of this bit of code.  So add a class called Startup to your project and add a Main method and just copy+paste the internal stuff from the prior Main method.

   1:class Startup
   2:    {
   3:        [STAThread]
   4:static void Main()
   5:        {
   6:            WoTBattleResultsKit.App app = new WoTBattleResultsKit.App();
   7:            app.Run();
   8:        }
   9:    }

Change your project startup object to specifically use your class.

6-14-2013 9-07-52 AM

When you F5, your application should launch just as it did previously.

Add a Activate method to your existing Application class

Next we want to open our existing class that contains the inheritance of our Application class.  For most people, and Prism users as well, this will be your App.xaml.cs file.

6-14-2013 9-38-06 AM

Crack that open and add the Activate method.

6-14-2013 9-39-24 AM

Codez:

   1:public void Activate()
   2:        {
   3: // Reactivate application's main window
   4: this.MainWindow.Activate();
   5:        }

Add the SingleInstanceManager class to encapsulate handling the single instance logic

I put this code in the Startup.cs file.  Here we are going to add a class to handle the logic for when the application is launched and when it is launched again.  We are also going to rely on the WIndowsFormsApplicationBase which is inside of Microsoft.VisualBasic library.

Here’s where you go “ermhagerd you can’t do this!  VB in my C#.”  Well get over it.  That library is in the .NET Framework, you’re not requiring the user a separate download.  Who cares if it’s VisualBasic or System.ConfigurationUtils.  It’s also the recommended implementation from MSDN (Single Instance Detection Sample).  I’ve seen other solutions using Mutex, etc – but seems unnecessarily complex – each his own.  Read all the glorious arguments for and against on StackOverflow.

Here’s the code for the entire Startup.cs with the modified Main method to use the SingleInstanceManger and the Main methods code moved inside the SingleInstanceManager.OnStartup.

   1:class Startup
   2:    {
   3:        [STAThread]
   4:static void Main(string[] args)
   5:        {
   6:            SingleInstanceManager manager = new SingleInstanceManager();
   7:            manager.Run(args);
   8:        }
   9:    }
  10: 
  11:public class SingleInstanceManager : WindowsFormsApplicationBase
  12:    {
  13:        App app;
  14: 
  15:public SingleInstanceManager()
  16:        {
  17: this.IsSingleInstance = true;
  18:        }
  19: 
  20:protected override bool OnStartup(StartupEventArgs eventArgs)
  21:        {
  22: // First time app is launched
  23:            app = new WoTBattleResultsKit.App();
  24:            app.Run();
  25: return false;
  26:        }
  27: 
  28:protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
  29:        {
  30: // Subsequent launches
  31: base.OnStartupNextInstance(eventArgs);
  32:            app.Activate();
  33:        }
  34:    }

From here you are good to go.

I’ll be using the technique for future applications and using it to update some existing applications that do this currently but do things like searching thru the processes running on the machine and throwing pop-up windows, like “You already have one of this application running" as this technique is much more user friendly.

Visual Studio 2012 theme, caps and pending changes window

1. May 2013 11:19 by Rick Glos in Programming

I’ve been living in Visual Studio 2012 for a couple weeks now, finally making the switch from Visual Studio 2010 to Visual Studio 2012 for most of my work and doing the usual stuff of upgrading projects and tools, etc.

Many people have complained about the UI and I’m not normally one to customize but it has been hard.  I find myself having having mental hiccups figuring out which tab is active or why can’t I see xyz in the pending changes window?  My co-worker and I were discussing and came across some good links I wanted to document.

  1. Customizing the theme.

    A really good extension called Color Theme Editor. A good video on how it works.

  2. Getting rid of the all caps.

    It involves the registry, but thankfully there's a way to remove those capitals.

  3. Getting the old pending changes window back.

    I think Pending Changes merits its own window, not being buried in the Team Explorer window.

VS2012 unit tests fail when using Microsoft.SqlServer.Smo

24. April 2013 06:30 by Rick Glos in Programming

I’ve got a bunch of unit tests that were in an existing VS2010 project that worked great.  They had an AssemblyInitialize method that dropped and recreated the database and used Microsoft.SqlServer.Smo to run scripts.

When I upgraded this solution to VS2012 the unit tests would no longer execute and I was receiving the following error:

System.IO.FileLoadException: Mixed mode assembly is built against version ‘v2.0.50727’ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.. Aborting test execution.

I can’t very well change how Microsoft.SqlServer.Smo is compiled.

Googling around I didn’t find much but eventually ran across a comment buried in StackOverflow question about hand editing the VS2012 test runner.

The solution is to open the config file at C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.executionengine.x86.exe.config and add the following:

<startup useLegacyV2RuntimeActivationPolicy="true"><supportedRuntime version="v4.0"/></startup>

Note that I had to restart VS2012 to unload the exe and reload it.  You can see it running as a child process of VS2012 in Process Explorer.

4-24-2013 6-25-49 AM

Hope that helps someone else.