title image

Smiley Re: wie kann ich verhindern das mein Prog mehrmals gestartet wird ?
Hallo!Hier ein Auszug aus der MSDN vom Bruce McKinney, einer der "VB-Päpste":Handling Multiple InstancesThe discussion of Windows so far in this chapter might have enlightened you, but it probably hasnÂ’t put much bread on your table. HereÂ’s a more practical problem.What happens if you try to start two copies of the same program? Some programs, such as Calculator, donÂ’t mind at all and will keep starting copies until you run out of memory. Others quit after displaying a message box saying that you can run only one copy. Still others, such as Microsoft Exchange, reactivate the current copy every time you try to start a new copy. For every program you write, you need to think about this issue and choose a strategy.If itÂ’s OK to run multiple copies, you donÂ’t need to do anything. ThatÂ’s the default. If you want to run only one copy, terminating each additional attempt with an error message, you donÂ’t need to do much. Just put the following in Form_Load:If App.PrevInstance Then MsgBox “You cannot start more than one copy" EndEnd IfThis technique has one problem—App.PrevInstance is always False in the Visual Basic environment. You can launch multiple versions of Visual Basic running the same program, but each will think that itÂ’s the only one. YouÂ’ll have difficulty debugging complicated code that uses the PrevInstance property. You canÂ’t test it in the environment because it wonÂ’t behave the same, but you canÂ’t easily test it outside the environment because you donÂ’t have a debugger.A bigger problem with putting up an error message in this situation is that itÂ’s rarely the right thing to do. ItÂ’s much better to change the focus to the first copy and terminate the second copy. On the surface, it doesnÂ’t seem to be hard to accomplish this in Visual Basic. The technique on the following page (from ALLABOUT.FRM) will work for many programs. If App.PrevInstance Then Dim sTitle As String 'Save my title sTitle = Me.Caption 'Change my title bar so I wonÂ’t activate myself Me.Caption = Hex$(Me.hWnd) 'Activate other instance AppActivate sTitle 'Terminate myself End End IfIs changing the caption before activating the other instance a neat trick or what? This works great for programs that always have the same title, but what if the other instance has a different title? NotepadÂ’s title contains the name of the current file. So does the Visual Basic environment. In fact, the Windows interface standard specifies that any window representing a document should have the document name in the title. But if you donÂ’t know the document name, you canÂ’t call AppActivate.WinWatch handles multiple copies the hard way. It calls the GetFirstInstWnd function to find out whether there is another instance. If so, it activates that window by calling the SetForegroundWindow API function. The call looks like this: Dim hWndOther As Long hWndOther = GetFirstInstWnd(Me.hWnd) If hWndOther hNull Then 'Uncomment this line for debugging 'MsgBox “Activating first instance" SetForegroundWindow hWndOther End End IfThe GetFirstInstWnd function does the actual work. It works by looping through all the top windows until it finds one that has a different process ID, but the same module name. ThatÂ’s the duplicate. The code (in MODTOOL.BAS) looks like this:Function GetFirstInstWnd(hWndMe As Long) As Long Dim hWndYou As Long, idMe As Long, sExeMe As String 'Get my own process ID and executable name idMe = MWinTool.ProcIDFromWnd(hWndMe) sExeMe = ExeNameFromWnd(hWndMe) 'Get first sibling to start iterating top-level windows hWndYou = GetWindow(hWndMe, GW_HWNDFIRST) Do While hWndYou hNull 'Ignore if process ID of target is same If idMe MWinTool.ProcIDFromWnd(hWndYou) Then 'Ignore if module name is different If sExeMe = ExeNameFromWnd(hWndYou) Then 'Return first with same module, different process GetFirstInstWnd = hWndYou Exit Function End If End If ' Get next sibling hWndYou = GetWindow(hWndYou, GW_HWNDNEXT) LoopEnd FunctionThis technique works for most applications, but itÂ’s not infallible. Your program might have multiple top-level windows, and the first one returned might not be the one you want to activate. ThatÂ’s why MODTOOL.BAS also contains the GetAllInstWnd function, which returns a Collection of all the window handles of other instances. GetAllInstWnd enables you to follow one of Joe HackerÂ’s favorite design rules: “If in doubt, let the user decide.” You could create a dialog box form with a list box of existing instances. Let the user decide whether to cancel the request, launch a new instance, or activate an existing one. This would be an excellent way to handle the new multiple instance model that is becoming popular as an alternative to the Multiple Document Interface—each document is handled by a separate independent instance of a small program rather than by a separate MDI window of a large program. WARNING Terminating a duplicate instance is one of those rare cases when you should actually use the End statement. Although the name sounds harmless, End is actually more like an Abort statement that means stop by any means even if it canÂ’t do normal cleanup. Experienced Visual Basic programmers terminate their programs by unloading all the active forms. Normally, all it takes is an Unload Me statement in the main form. But if youÂ’re trying to terminate in the main Form_Load, there is, by definition, nothing to unload. So the rule is simple: Never use End except in Form_Load. In the first edition of this book, I violated this rule by providing a procedure that looked for a duplicate instance and terminated that instance with an End statement inside the procedure. I got a rude surprise when I tried to put that procedure in the VBCore component. Visual Basic wonÂ’t let you use the End statement in a DLL or a control. The GetFirstInstWnd function can be in a DLL because it returns the other instance rather than trying to take action about it. This is a more flexible structure anyway. The caller of GetFirstInstWnd can decide what it wants to do about the duplicate instance.Gruß Stefan

geschrieben von




Beitrag anfügen