Friday, November 21, 2008
Single instances

I used your old ways to force a single instance of VB 3,4, 5 and 6 ... how do you do it in VB.Net?

If there is some single-line Framework method that gets around the age-old silliness, we haven't come across it. But it's not all that hard.

We just ported our old Delphi Mutex logic over and it seemed to do the trick quite nicely. It's done with System.Threading working the Mutex (a Mutex could be thought of as a systemwide flag that goes away when it's creator process ends - they're quite handy little suckers), Process objects to iterate through what's running on the machine, and traditional Win32 API calls for the form visibility manipulation.

Add this module to your WinForms project and make the Sub Main the entry point of the program (in VS project properties). The thing to change is the name of the primary form in your app.

You see that this will not only restrict your app to a single instance, but bring a running instance back to the top of the ZOrder and even bring it back from the minimized state.

Module main

   Private Const MB_TITLE As String = "Smithvoice.com Demo"

   Public Const SW_RESTORE = 9
   Public Const HWND_TOPMOST = -1
   Public Const HWND_NOTOPMOST = -2
   Public Const SWP_NOMOVE = &H2
   Public Const SWP_NOSIZE = &H1

   Declare Function ShowWindowAsync Lib "user32" (ByVal hwnd As Integer, _
      ByVal nCmdShow As Integer) As Integer

   Declare Function SetWindowPos Lib "user32" _
      (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, _
      ByVal x As Integer, ByVal y As Integer, _
      ByVal cx As Integer, ByVal cy As Integer, _
      ByVal wFlags As Integer) As Integer

   Private m_Mutex As System.Threading.Mutex

   Private m_UniqueIdentifier As String = _
      Process.GetCurrentProcess.MainModule.FileName.Replace("\", "_")


   Sub main()

      m_Mutex = New System.Threading.Mutex(False, m_UniqueIdentifier)
      Dim bFound As Boolean = False
      If m_Mutex.WaitOne(1, True) Then
         'first instance
         Dim f As New frmMain
         'start the app by showing the primary form
         f.ShowDialog()
      Else
         'not first instance
         Try
            Dim Procs() As Process = Process.GetProcesses()
            Dim proc As Process
            For Each proc In Procs

               If proc.MainModule.FileName.Replace("\", "_") = m_UniqueIdentifier _
                  And proc.Id <> Process.GetCurrentProcess.Id Then
                     'MsgBox("another")
                     bFound = True
                  Exit For

               End If

            Next proc

            If bFound Then
               'start this one
               Dim temphwnd, x As Integer
               temphwnd = proc.MainWindowHandle.ToInt32
               x = ShowWindowAsync(temphwnd, SW_RESTORE)
               'bring it to the top of the z-order
               SetWindowPos(temphwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
               'and release it
               SetWindowPos(temphwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
            End If

            'exceptions from Process.GetProcesses are possbile 
            'on certain hardware running Win2kPro and using Hyperthreading
            'MS is aware of this and while they are not fixing .Net1x
            'they say that the fix will be in .Net2

         Catch ex As ArgumentOutOfRangeException
            MsgBox("This program is already running." & vbCrLf & _
            "To maximize performance of your computer only one instance of" & vbCrLf & _
            "this program can run at a time.", MsgBoxStyle.Information, MB_TITLE)
         Catch ex As InvalidOperationException
            MsgBox("This program is already running." & vbCrLf & _
            "To maximize performance of your computer only one instance of" & vbCrLf & _
            "this program can run at a time.", MsgBoxStyle.Information, MB_TITLE)
         End Try

      End If

   End Sub

End Module

 

Hope it helps!

Robert Smith
Kirkland, WA

 

added to smithvoice October 2004


Print  

pagecomment
  Add Comment



Submit Comment
  View Ratings
50.00%0
40.00%0
30.00%0
20.00%0
10.00%0

Number of Comments 0 , Average of Ratings
  View Comments
No comment.


Privacy Statement  |  Terms Of Use
Copyright 2008 by Robert C. Smith