Hallo
1. Feststellen, ob schon eine Instanz des Programms läuft
Function PrevInstance() As Boolean
If Ubound(Diagnostics.Process.GetProcessesByName( _
Diagnostics.Process.GetCurrentProcess).ProcessName)) > 0 _
Then
Return True
Else
Return False
End If
End Function Der code ist von dieser Seite: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=205&lngWId=10
Alternativ und zuverlässiger ist es einen Mutex zu erstellen.
Public Shared Sub Main()
'Für jede Applikation eine neue Id nehmen!!!
Const idMutex$ = "{0670FCFC-CCC2-4597-96F6-6AFD78C6BF8D}"
Dim mut As Threading.Mutex
Dim createdNew As Boolean
mut = New Threading.Mutex(True, idMutex, createdNew)
If createdNew Then
mut.ReleaseMutex()
Else
Debug.WriteLine("Es läuft bereits eine Instanz des Programms")
ActivatePrevInst()
Return
End If
Dim fmMain As New Form1()
Application.Run(fmMain)
mut.Close()
End Sub 2. schon laufende Programminstanz in den Vordergrund bringen:
Das erledige ich immer, indem ich eine Nachricht an das Fenster der schon laufenden Instanz sende. Dazu benutze ich eine selbstdefinerte Nachricht.
In der Form der Applikation überschreibe ich dazu WndProc und gebe dem Fenster eine selbstdefinierte Eigenschaft im Form_Load-Event:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
Api.SetProp(Me.Handle, ClsStart.IdWinProp, 1)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
'Wenn die Form die selbstdefinierte Nachricht erhält,
'wird sie aktiviert.
If m.Msg = Api.WM_PRIVATE_ACTIVATE Then
Me.Activate()
End If
MyBase.WndProc(m)
End Sub Die Start-Class mit der Sub Main wird dabei um folgende Prozeduren/Deklarationen ergänzt:
'Für jede Applikation bzw. jedes Fenster einer Anwendung eine neue ID
' nehmen!!!
Public Const IdWinProp$ = "{CF9E5190-770E-4e62-AAAB-7C0020E52129}"
Friend Shared Sub ActivatePrevInst()
'Sendet die selbstdefinierte Nachricht an das Fenster der schon
' laufenden
'Instanz
Dim hwnd As IntPtr = GetPrevInstWnd()
If hwnd.Equals(IntPtr.Zero) Then
Return
End If
Api.SendMessage(hwnd, Api.WM_PRIVATE_ACTIVATE, 0, 0)
End Sub
Private Shared Function GetPrevInstWnd() As IntPtr
'Durchsucht alle Fenster bis es die Form gefunden hat,
'die die selbstdefinierte Eigenschaft ClsStart.IdWinProp aht
'und gibt das Fensterhandle zurück
Dim hWnd As IntPtr
Dim ret%
hWnd = Api.GetDesktopWindow
hWnd = Api.GetWindow(hWnd, Api.GW_CHILD)
Do Until hWnd.Equals(IntPtr.Zero)
ret = Api.GetProp(hWnd, IdWinProp)
If ret Then
Return hWnd
End If
hWnd = Api.GetWindow(hWnd, Api.GW_HWNDNEXT)
Loop
Return IntPtr.Zero
End Function Zusätzlich brauch man noch eine Klasse mit den Api-Deklarationen:
Public Class Api
Public Declare Function SetProp Lib "user32" Alias "SetPropA" ( _
ByVal hwnd As IntPtr, _
ByVal lpString As String, _
ByVal hData As Int32) As Int32
Public Declare Function GetProp Lib "user32" Alias "GetPropA" ( _
ByVal hwnd As IntPtr, _
ByVal lpString As String) As Int32
Public Declare Function GetDesktopWindow Lib "user32" () As IntPtr
Public Declare Function GetWindow Lib "user32" ( _
ByVal hwnd As IntPtr, _
ByVal wCmd As Int32) As IntPtr
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As IntPtr, _
ByVal wMsg As Int32, _
ByVal wParam As Int32, _
ByVal lParam As Int32) As Int32
Public Const GW_CHILD As Int32 = 5
Public Const GW_HWNDNEXT As Int32 = 2
Public Const WM_APP As Int32 = &H8000
Public Const WM_PRIVATE_ACTIVATE = WM_APP + 1
End Class Sicher lässt sich das Senden einer Nachricht an die vorherige Instanz auch anders gestalten. Vielleicht hat ja noch jemand einen Vorschlag dazu.
Ciao
D. |