Ich möchte mein VB-Programm nur einmal
starten dürfen; d.h. wenn mein Programm
schon läuft soll es kein weiteres mal gestartet
werden können.
Wie macht man das?
Ich weiß, daß diese Frage schon des öfteren
in der NG gestellt wurde; aber ich komme leider
nicht mehr an diese Informationen.
Danke
Gruß Andreas
If (App.PrevInstance) Then
End
End If
einfügen. App.PrevInstance ist TRUE, falls es nicht Die erste Instanz ist.
Andreas
--
_____________________________________________________________
NewsGroups Suchen, lesen, schreiben mit http://netnews.web.de
app.previnstance (oder so)
ist der wert 1 (oder true?) dann sag einfach end
grüße
-nico
Hallo Andreas,
Beschreibung siehe unten. Mit App.PrevInstance kannst Du prüfen, ob
schon eine Instanz Deines Proggis läuft.
Der restliche Code bewirkt, das die bereitslaufende Instanz aktiviert
wird und Dein neu gestartetes Programm beendet wird.
Das Sample wurde vor einigen Wochen hier angesprochen und ist irgenwo
auf den M$-Seiten zu finden.
Hoffe, Dir geholfen zu haben.
Gruß Uwe
In Main bzw. FormLoad Deiner Startform (oder an der gewünschten
Stelle) :
'Prüfen, neue Instanz
If App.PrevInstance Then
ActivatePrevInstance
End
End If
'In einem Modul :
Option Explicit
'Diese Funktion aktiviert eine bereits laufende Instanz des gleichen
Programmes
'und bringt diese in den Vordergrund.
Private Const GW_HWNDPREV = 3
Private Declare Function apiOpenIcon Lib "user32" Alias "OpenIcon"
(ByVal hwnd As Long) As Long
Private Declare Function apiFindWindow Lib "user32" Alias
"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As
String) As Long
Private Declare Function apiGetWindow Lib "user32" Alias "GetWindow"
(ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function apiSetForegroundWindow Lib "user32" Alias
"SetForegroundWindow" (ByVal hwnd As Long) As Long
Sub ActivatePrevInstance()
Dim OldTitle As String
Dim PrevHndl As Long
Dim result As Long
'Save the title of the application.
OldTitle = App.Title
'Rename the title of this application so apiFindWindow
'will not find this application instance.
App.Title = "unwanted instance"
'Attempt to get window handle using VB4 class name.
PrevHndl = apiFindWindow("ThunderRTMain", OldTitle)
'Check for no success.
If PrevHndl = 0 Then
'Attempt to get window handle using VB5 class name.
PrevHndl = apiFindWindow("ThunderRT5Main", OldTitle)
End If
'Check if found
If PrevHndl = 0 Then
'Attempt to get window handle using VB6 class name
PrevHndl = apiFindWindow("ThunderRT6Main", OldTitle)
End If
'Check if found
If PrevHndl = 0 Then
'No previous instance found.
Exit Sub
End If
'Get handle to previous window.
PrevHndl = apiGetWindow(PrevHndl, GW_HWNDPREV)
'Restore the program.
result = apiOpenIcon(PrevHndl)
'Activate the application.
result = apiSetForegroundWindow(PrevHndl)
''End the application.
'End
End Sub
Vielen Dank an Euch beide.
Andreas
Andreas Binder schrieb:
> Ich möchte mein VB-Programm nur einmal
> starten dürfen; d.h. wenn mein Programm
> schon läuft soll es kein weiteres mal gestartet
> werden können.
In der Sub Main oder Form_Load:
If App.PrevInstance then
'Andere Instanz
else
'Keine andere Instanz
end if
HTH
Chris
--
Christopher Kleinheitz Offenburg Germany
http://jahresarbeit.virtualave.net
Die Welt ist eine Datenbank
> Das Sample wurde vor einigen Wochen hier angesprochen und ist irgenwo
> auf den M$-Seiten zu finden.
> (...)
> End
Wobei in weiteren Postings diskutiert wurde, ob "End" hier
_ausnahmsweise_ nicht zur Steinigung des Programmierers fuehrt.
Besser waere (*mal eben aus Christophers Posting klau und ergaenz*)
If App.PrevInstance then
'Andere Instanz
Unload me
else
'Keine andere Instanz
end if
...ansgar
Hi Uwe,
wenn ich Dein Prev. Instanz Modell einsetzte, wird der Tray icon nicht
aktiviert. Ich krieg aber die Meldung "previous instance found".
Das handle findet also die prev instance aber öffnet das Icon nicht.
Was mach ich falsch ? Für Deine Hilfe 1000 Dank im voraus.
Hier mein Code:
Private Sub Form_Load()
If App.PrevInstance Then
For Each Form In Forms
Unload Form
Next Form
ActivatePrevInstance
Else .....
(schnipp)
end if
end sub
'Modul:
Option Explicit
Private Const GW_HWNDPREV = 3
Private Declare Function apiOpenIcon Lib "user32" Alias "OpenIcon" (ByVal
hwnd As Long) As Long
Private Declare Function apiFindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As _
String) As Long
Private Declare Function apiGetWindow Lib "user32" Alias "GetWindow" (ByVal
hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function apiSetForegroundWindow Lib "user32" Alias _
"SetForegroundWindow" (ByVal hwnd As Long) As Long
Sub ActivatePrevInstance()
Dim Terminator As String ' Terminator = Programmname
Dim PrevHndl As Long
Dim result As Long
Terminator = App.Title
App.Title = "unwanted instance"
PrevHndl = apiFindWindow("ThunderRTMain", Terminator)
If PrevHndl = 0 Then
PrevHndl = apiFindWindow("ThunderRT5Main", Terminator)
End If
If PrevHndl = 0 Then
PrevHndl = apiFindWindow("ThunderRT6Main", Terminator)
End If
If PrevHndl = 0 Then
MsgBox "No previous instance found."
Else: MsgBox "previous instance found"
Exit Sub
End If
PrevHndl = apiGetWindow(PrevHndl, GW_HWNDPREV)
result = apiOpenIcon(PrevHndl)
result = apiSetForegroundWindow(PrevHndl)
End Sub
mfG.
Bert
Mhm, lass uns mal nachdenken :
Ich denke mal, Du führst den Code im Form_Load Deines Startforms aus.
Richtig ???
Was passiert da ??? Die For-Each-Schleife durchläüft alle Forms und
entlädt diese, incl. Deines Startforms. Ich bin mir da nicht so
sicher, das das ActivatePrevInstance noch so ganz sauber ausgeführt
wird oder ob sich da schon was beim Entladen in die Quere kommt.
Vorschlag :
Falls Du als Startobjekt keine Form sondern Sub Main verwendest, dann
packe die PrevInstance-Abfrage da rein (dann wird der ganze
Form-Semmel erst gar nicht geladen und Du kannst Dir auch das Entladen
schenken).
Falls Du als Startobjekt eine Form hast, dann solltest Du das evtl.
ändern.
Modul anlegen (sinnvollerweise modMain nennen) und folgendes
reinkopieren :
Public Sub Main()
'Prüfen, neue Instanz
If App.PrevInstance Then
ActivatePrevInstance
End
End If
frmStartform.Show
End Sub
Den Startformname musst Du natürlich noch anpassen. Das Für und Wider
des End können wir gerne noch ein wenig weiter diskutieren, aber an
der Stelle dürfte es nicht schaden.
Als Letztes noch unter Projekt/Eigenschaften Sub Main als Startobjekt
festlegen.
Vorteil dieser Version : Du musst Dir um Konflikte beim Laden und
Entladen keine Sorgen machen und es geht auch schneller als die obige
Variante.
> wenn ich Dein Prev. Instanz Modell einsetzte, wird der Tray icon nicht
> aktiviert. Ich krieg aber die Meldung "previous instance found".
> Das handle findet also die prev instance aber öffnet das Icon nicht.
> Was mach ich falsch ?
Ich schätze, daß das Ganze mit GetWindow nicht so einfach funktioniert.
Versuch mal meinen Code (für VB6-Programme), der listet, nachdem er den
Thread gefunden hat, dessen Fenster auf und stellt diese wieder her.
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal
lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function OpenIcon Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd
As Long, lpdwProcessId As Long) As Long
Private Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId As
Long, ByVal lpfn As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA"
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long)
As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As
Long) As Long
Public Function PrevInstanz() As Boolean
Dim hWndApp As Long
Dim sWindowTitle As String
Dim Projektname As String
Dim ThreadID As Long
Dim ProcessID As Long
Projektname = App.Title
App.Title = "ZweiterAufruf"
' Hauptwindow der Application
hWndApp = FindWindow("ThunderRT6Main", Projektname)
If hWndApp = 0 Then
' App ist nicht im Speicher
PrevInstanz = False
Else
' App ist schon gestartet
PrevInstanz = True
' ID des Threads ermitteln
ThreadID = GetWindowThreadProcessId(hWndApp, ProcessID)
' Auflisten aller Kindfenster
EnumThreadWindows ThreadID, AddressOf EnumThreadWndProc, 0
End If
App.Title = Projektname
End Function
Private Function EnumThreadWndProc(ByVal hwnd As Long, ByVal lParam As Long)
As Long
Dim Ret As Long
Dim sText As String
sText = Space(255)
' Klassennamen ermitteln
Ret = GetClassName(hwnd, sText, 255)
sText = Left$(sText, Ret)
' Nur für VB-Forms
If sText = "ThunderRT6FormDC" Then
' Minimierte Fenster normalisieren
If OpenIcon(hwnd) = 0 Then
MsgBox "OpenIcon-Fehler"
End If
' Fenster aktivieren
If SetForegroundWindow(hwnd) = 0 Then
MsgBox "SetForeGround-Fehler"
End If
End If
' Enumeration fortsetzen
EnumThreadWndProc = 1
End Function
Bis denn dann,
Frank
--
Wisdom starts where knowledge ends - Rage (Ghosts-1999)
dazu vielleicht auch noch folgendes:
http://www.aboutvb.de/khw/artikel/khwprevinstanceax.htm
Viele Grüße
Harald M. Genauck
--
ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
>Uwe Naumann schrieb in Nachricht ...
>Falls Du als Startobjekt keine Form sondern Sub Main verwendest, dann
>packe die PrevInstance-Abfrage da rein (dann wird der ganze
>Form-Semmel erst gar nicht geladen und Du kannst Dir auch das Entladen
>schenken).
Das klingt nicht schlecht.
Private Sub Main()
If App.PrevInstance Then
ActivatePrevInstance
End
Else
Form1.Show
End If
End Sub
und jetzt kann ich die form1 aus der Taskleiste hochheben, falls die
PrevInstance schon existiert.
Einziger Wermutstropfen: Ich krieg den Tray Icon nicht auf.
Dabei wird der doch eindeutig angesprochen
Public Declare Function apiOpenIcon Lib "user32" Alias "OpenIcon" _
(ByVal hwnd As Long) As Long
'Restore the program.
result = apiOpenIcon(PrevHndl)
Ist Programmieren nicht faszinierend ?
MfG.
Bert
.
Frank Schumacher schrieb in Nachricht ...
>Ich schätze, daß das Ganze mit GetWindow nicht so einfach funktioniert.
>Versuch mal meinen Code (für VB6-Programme), der listet, nachdem er den
>Thread gefunden hat, dessen Fenster auf und stellt diese wieder her.
Ich krieg das nicht so ganz auf die Reihe. Hast Du ein mini Beispielprojekt
?
mfg
Bert
> und jetzt kann ich die form1 aus der Taskleiste hochheben, falls die
> PrevInstance schon existiert.
> Einziger Wermutstropfen: Ich krieg den Tray Icon nicht auf.
> Dabei wird der doch eindeutig angesprochen
>
> Public Declare Function apiOpenIcon Lib "user32" Alias "OpenIcon" _
> (ByVal hwnd As Long) As Long
>
> 'Restore the program.
> result = apiOpenIcon(PrevHndl)
>
> Ist Programmieren nicht faszinierend ?
Eben weil die GetWindow/OpenIcon-Geschichte gelegentlich ihre Macken hat,
habe ich einen anderen Weg gesucht und gefunden (der meines Erachtens sogar
noch mehr Vorteile bietet) - noch einmal:
> Ich krieg das nicht so ganz auf die Reihe. Hast Du ein mini
Beispielprojekt
Wo genau liegt denn das Problem, bzw. was genau funktioniert denn nicht?
Von der Sache her mußt du die beiden Funktionen einfach in ein Modul packen
und dann in der Sub Main aufrufen ...
Sub Main
if not PrevInstance
' Programm initialisieren
' erste Form rufen
end if
end sub
Zu Problemen, die diese Vorgehensweise hat, kannst du den von Harald
angegebenen Artikel lesen ...
>Wo genau liegt denn das Problem, bzw. was genau funktioniert denn nicht?
>Von der Sache her mußt du die beiden Funktionen einfach in ein Modul packen
>und dann in der Sub Main aufrufen ...
Liegt wahrscheinlich daran, daß ich immer noch mit der VB5/LE. arbeite.
Danke für die Mühe,
Bert
Diese Quälerei kann man sich sparen:
Seit kurzem ist die "dshandle.dll" nebst anderem auf
http://www.allapi.net/vbasic/misc.php
als Freeware zum Download verfügbar, und da heißt es dann
hWndApp = GetHandle("thunder", "main", Projektname, "", ..................)
bzw.
hWnd = GetHandle("thunder", "form", Caption, "", ..................),
und das paßt immer (auch in der IDE).
Jürgen.