.Net Code Monkey RSS 2.0
 Friday, July 30, 2010

VB.Net Single Instance application on Terminal Server

Yesterday at work I spent nearly the whole day bashing my head against a wall trying to replicate functionality that our original VB6 application had into the new .Net conversion. The orginal VB6 application used "App.PrevInstance" to determine if another instance was running or not. This appeared to work for multiple users on Terminal Servers, so each user could run an instance of the app, but it would warn if they tried to open another.

VB.Net does not appear to have such direct functionality. Looking on the web provided various 'solutions' to the problem. However each one seemed to have an 'issue' with our scenario. By the afternoon I was looking at the Mutex objects which a lot of people seemed to find worked for them. However for me I was getting an "Object synchronization method was called from an unsynchronized block of code" error when closing the second instance onwards.

Looking into the Mutex object in a bit more depth it seemed that maybe it was not the right object for our purpose but maybe the Semaphore object would be better.

In the end the solution I used was to use a named Semaphore. When the application first instance runs it would attempt to open the named Semaphore and if it did not exist, assume it was the first instance and create one. The second instance when run would again look for and open the named Semaphore and if it exists and it manages to open it then it would assmue it is a second instance of the application.

By prefixing the Semaphorename with "Local\" it will allow each Terminal Server session to have it's own Semaphore so each remote user would not affected by another.

The elements of the code I used are below.

Imports:

Imports System.Threading

Declarations:

Private SingleInstanceSemaphore As Semaphore = Nothing ' This needs to live for the life of the application
Private Const MAX_SESSION_INSTANCES As Integer = 1
Private Const SEMAPHORE_NAME As String = "{9A49BB2C-45D2-4bb9-B38E-74F9DB612B96}" ' Unique for each application

Main Method:

''' <summary>
''' This is the main application entrance point.
''' </summary>
Public Sub Main()
' We need a name for the semaphore that is specific to to the Application / User combination
' We prefix the semaphoreName with "Local\" to allow this to run under terminal services. 
' The "Local\" prefix forces this into local user space. 
' If we want to forbid this in TS, use the "Global\" prefix.
Dim semaphorePrefix As String = "Local" ' Or "Global" if required
Dim semaphoreName As String = String.Format("{0}\{1}{2}", semaphorePrefix, SEMAPHORE_NAME, Environment.UserName)
Dim anotherInstanceRunningForUser As Boolean = True
Dim runAnotherDialogResult As DialogResult = DialogResult.No
Dim mainForm As Form1 = Nothing

Try
    Try
        SingleInstanceSemaphore = Semaphore.OpenExisting(semaphoreName)
    Catch ex As Exception
        anotherInstanceRunningForUser = False
    End Try

    If (anotherInstanceRunningForUser = False) Then
        SingleInstanceSemaphore = New Semaphore(0, MAX_SESSION_INSTANCES, semaphoreName)
    End If

    If (anotherInstanceRunningForUser) Then
        runAnotherDialogResult = MessageBox.Show("Another instance is already running. Do you want to run another?", _
"Already Running...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) End If ' If this is the first instance of the application, or a further instance but the user wants more than one... If (anotherInstanceRunningForUser = False) Or _ ((anotherInstanceRunningForUser = True) And (runAnotherDialogResult = DialogResult.Yes)) Then ' Run the application mainForm = New Form1(mutexName) Application.Run(mainForm) End If Catch ex As Exception MsgBox(ex.Message) End Try

I hope that mayhelp someone in the future and save them a day trawling through the web sticking examples of code together and getting failed results like I did.

Regards,
Dib.

 

Friday, July 30, 2010 7:21:34 AM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.Net | Mutex | Semaphore | Single Instance | Terminal Server
Archive
<September 2014>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
Blogroll
 Clemens Vasters
 Harry Pierson
Passion * Technology * Ruthless Competence
 Joshua Flanagan
A .NET Software Developer
 Michael Schwarz's Blog
Developing applications on the Microsoft platform since Windows 3.1!
 Omar Shahine
Yet another Microsoft blogger
 Scot GU
Scott Guthrie lives in Seattle and builds a few products for Microsoft
 Scott Hanselman
Programming Life and the Zen of Computers
 Tom Mertens
Tom's corner
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014
Duane Wingett
Sign In
Statistics
Total Posts: 52
This Year: 9
This Month: 0
This Week: 0
Comments: 49
Themes
Pick a theme:
All Content © 2014, Duane Wingett
DasBlog theme 'Business' created by Christoph De Baene (delarou)