smithvoice.com
 Y'herd thisun? 

“There is nothing inherently expensive about rockets. It's just that those who have built and operated them in the past have done so with horrendously poor efficiency.”
-Elon Musk



Single instances

TaggedCoding

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

 

who is smith    contact smith     rss feed π
Since 1997 a place for my stuff, and it if helps you too then all the better smithvoice.com