Hallo Woellmi,
ich schrieb schon: Deine Starter-Exe muss auf das Mutex-Handle aufpassen wie die Henne auf das Ei oder der Hahn auf die Hennen. Dein Probramm schließt das Mutex nämlich sofort nachdem das andere Probramm aufgerufen wurde.
Der Fehler am Beispiel:
Sub Main()
static nCounter as Long
hMutex=CreateMutex(0&, 1&, "AufrufendesProg")
nCounter = nCounter + 1
If Is2ndProgStarted() Then
MsgBox "Fehler: bitte 2ndProg beenden! (" & Cstr(nCounter) & ")"
Else
Start2ndProg()
'Hier fehlt eine Function die verhindert dass der Thread die If-Anweisung
'nicht gleich verlassen kann. Es wird sofort CloseHandle hMutex
' aufgerufen, sofern
'das andere Programm asynchron gestartet wurde. Die Funktionen Shell und
' ShellExecute()
'sind asynchrone Funktionen!
End If
CloseHandle hMutex
End Sub Ich nehme mal an, du nimmst die VB-Shell-Funktion zum Aufruf des externen Programms. Die Syntax dazu ist ja dann:
Dim hProcessID As Long
hProcessID = Shell("NotePad.EXE", 1)
Die Programmausführung setzt, weil Shell() asynchron ist, sofort weiter. Aber Du hast: hProcessID.
Mittels dieser ID lässt sich der Handle des Process erruieren, dass das den über Shell gestarteten
Prozess identifiziert. Das erlaubt, dass man sich über diese ProcessID private Zugriffsrechte auf
den gestarteten Prozess holen kann um, evtl. was Du ja brauchst, den Prozess aus dem asynchronen Lauf
in einen kontrollierten synchronen Lauf zu zwingen. Dazu erbt man mit OpenProcess() einfach einen
Handle:
Dim hProcessID As Long
Dim hProcess As Long
hProcessID = Shell("NotePad.EXE", 1)
hProcess = OpenProcess(PROCESS_SYNCHRONIZE, True, hProcessID)
WaitForSingleObject hProcess, INFINITE
Jetzt wartet man einfach nur darauf, dass hProcess, das ja signalisiert ist auf
einen unsignalisierten Zustand kippt und das genau macht die Funktion: WaitForSingleObject()
Somit synchroner Aufruf eines beliebigen Prozess und warten, bis der beendet ist:
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" _
(ByVal lpMutexAttributes As Long, _
ByVal bInitialOwner As Long, _
ByVal lpName As String) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As _
Long
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" ( _
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Const ERROR_ALREADY_EXISTS = 183&
Private Const PROCESS_SYNCHRONIZE = &H100000
Private Const INFINITE As Long = &HFFFFFFFF
Private m_hMutex As Long
Private Const s_NamedMutex As String = "MyExistAppCheck" 'Der Name des Mutex
' ist eigentlich egal,
'soll aber in der App
' unikat sein
Public Sub Main()
Dim hProcessID As Long
Dim hProcess As Long
m_hMutex = CreateMutex(0&, 1, s_NamedMutex)
If Err.LastDllError = ERROR_ALREADY_EXISTS Then
MsgBox "Solange die andere Anwendung läuft kann das Programm nicht" & _
"wieder gestartet werden"
Exit Sub
End If
hProcessID = Shell("NotePad.EXE", 1)
hProcess = OpenProcess(PROCESS_SYNCHRONIZE, True, hProcessID)
'Warten bis der Prozess beendet wurde. VB-Programm startet Notepad.EXE und
'es wird sich hier weiter nichts tun, bis Notepad.EXE geschlossen wurde.
WaitForSingleObject hProcess, INFINITE
MsgBox "Der zweite Prozess wurde geschlossen, jetzt das Mutex und das" & _
"Process-Object freigeben"
CloseHandle hProcess
CloseHandle m_hMutex
End Sub |