Search code examples
c#windowsdesktop-applicationapp-certification-kitwack

Windows App Certification Kit fails: Multi user session test


I'm trying to pull a WinForms application through the Windows App Certification Kit and gets a fail on this test:

  <TEST INDEX="17" NAME="Multi user session test" DESCRIPTION="Multi User checks Application invocation in multiple sessions." EXECUTIONTIME="00h:00m:24s.22ms">
  <RESULT><![CDATA[FAIL]]></RESULT>
  <MESSAGES />

I guess that this is because I only allow one instance of the application to run, like this:

using ( var p = System.Diagnostics.Process.GetCurrentProcess() )
if ( System.Diagnostics.Process.GetProcessesByName( p.ProcessName ).Length > 1 )
{
    MessageBox.Show(
            "An instance of xxx is already running!",
            Title,
            MessageBoxButtons.OK,
            MessageBoxIcon.Exclamation );
    return;
 }

It is a tray-application activated by a hot-key combination, registered with this function:

[DllImport( "user32", EntryPoint = "RegisterHotKey", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true )]
public static extern int RegisterHotkey( IntPtr hWnd, int id, int fsModifiers, int vk );

So I guess I have two questions:

1) How can I correctly prevent multiple sessions being run within the same user session but allow several instances across multiple user sessions?

2) Will I be able to register the same hot-key in different user sessions? Or must I somehow unregister and re-register the hot-key when user sessions are switched?

TIA


Solution

  • You can achieve the same effect using a Mutex. See MSDN for details, but the short version is that any mutex created with a name starting with "Local\" will be per-session. Enter a mutex named "Local\MyAppName" and only one instance of your app can run per-session.

    Hotkeys are registered per-session and it will not be a problem to register the same hotkey in multiple sessions.

    Example Use (from Run single instance of an application using Mutex):

    bool ownsMutex = false;
    // NOTE: Local is the default namespace, so the name could be shortened to myApp
    Mutex myMutex = new Mutex(false, @"Local\myApp");
    
    try 
    {
        ownsMutex = myMutex.WaitOne(0)
    }
    catch (AbandonedMutexException)
    {
        ownsMutex = true;
    }
    
    if (!ownsMutex)
    {
        MessageBox.Show("myApp is already running!", "Multiple Instances");
        return;
    }
    else 
    {
        try 
        {
            Application.Run(new Form1());
        }
        finally 
        {
            myMutex.ReleaseMutex();
        }
    }