Newsgroup: it.comp.lang.visual-basic
Titolo: [VB6] Cos'è un Mutex

Vorrei impostare un mio programma a istanza singola.
Ho letto in rete che microsoft sconsiglia App.PrevInstance pare che non 
funzioni sempre.
Molti consigliano un Mutex ma non ho capito n� cos'� n� come funziona. Ho 
scaricato alcuni esempi:
Li ho testati lanciando due volte l'eseguibile
Sono tutti usati in una function GetPrevInstance()
    Dim hMutex As Long
    hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, App.Title)
    If hMutex = 0 Then
        hMutex = CreateMutex(ByVal 0, 0, App.Title)
    Else
        ReleaseMutex hMutex
        CloseHandle hMutex
        GetPrevInstance = True
    End If
Questo funziona ma solo in eseguibile
    Dim hMutex As Long
    hMutex = CreateMutex(ByVal 0&, 1, App.Title)
    If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
        ReleaseMutex hMutex
        CloseHandle hMutex
        GetPrevInstance = True
    End If
Questo non funziona ma � il pi� usato
    Dim m_hWnd As Long
    m_hWnd = Findwindow("ThunderRT6Main", App.Title)
    If m_hWnd Then
        MsgBox "Program " & App.Title & " is already running..."
        GetPrevInstance = True
    End If
Poi quest'ultimo esempio che usa Findwindow come alternativa al mutex
Voi cosa mi consigliate?
Carmelo 

 Molti consigliano un Mutex ma non ho capito nè cos'è nè come funziona. Ho
http://it.wikipedia.org/wiki/Mutex
http://msdn.microsoft.com/it-it/library/fxy8dte8(VS.90).aspx
http://msdn.microsoft.com/it-it/library/system.threading.mutex(VS.80).aspx
http://www.foonews.info/it-comp-lang-visual-basic/1022235-vb6-come-impedire-seconda-istanza-programma.html

 Carmelo
Personalmente consiglio questo, basato sul mutex, e che gira anche sui s.o. 
piï¿½ recenti e pure in terminal server client (questo ï¿½ il motivo del 
prefisso "Global" dato al nome del mutex).
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" 
(lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As 
String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) 
As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) 
As Long
Const ERROR_ALREADY_EXISTS = 183&
Const ERROR_ACCESS_DENIED = 5&
Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type
Private Function PreviousInstance() As Boolean
Dim MutexName As String
Dim hMutex As Long
Dim sa As SECURITY_ATTRIBUTES
    If InDesign() Then
        PreviousInstance = App.PrevInstance
    Else
        MutexName = "Global\" & UCase(App.EXEName)  ' Fondamentale: i mutex 
sono CASE-SENSITIVE
        ' Try to create a new Mutex
        With sa
            .nLength = Len(sa)
            .lpSecurityDescriptor = 0&
            .bInheritHandle = False
        End With
        hMutex = CreateMutex(sa, False, MutexName)
        ' Did the mutex already exist?
        Select Case Err.LastDllError
        Case ERROR_ALREADY_EXISTS, ERROR_ACCESS_DENIED
            'Clean up
            ReleaseMutex hMutex
            CloseHandle hMutex
            PreviousInstance = True
        End Select
    End If
End Function
Bye
Raf 

Questa funziona si in IDE che in EXE
Public Function GetPrevInstance() As Boolean
    Dim jCont As Integer
    Dim Instance As Object
    On Error Resume Next
    For Each Instance In GetObject("winmgmts:").ExecQuery("SELECT * FROM 
Win32_Process WHERE Name='" & App.Title & ".exe'")
        jCont = jCont + 1
        If jCont > 1 Then
            MsgBox "Impossibile eseguire due istanze di " & App.Title & " 
sullo stesso computer.", vbInformation, App.Title
            GetPrevInstance = True
            Exit For
        End If
    Next
End Function
Carmelo 

 ha scritto nel messaggio 
news:4cbd923a$0$10762$4faf...@reader2.news.tin.it...

Se puoi ragionevolmente escludere che vi sia un altro programma con nome 
identico al tuo, allora vai tranquillo con WMI.
Occhio solo che invece di "...WHERE Name='" & App.Title & ".exe" forse 
volevi scrivere "...WHERE Name='" & App.EXEName & ".exe"
Ciao
Raf 

 scrivere "...WHERE Name='" & App.EXEName & ".exe"
mica vero, WMI puï¿œ essere disabilitato sulla macchina inoltre l'utente 
deve avere i permessi per accedere a quelle informazioni.
Il Mutex ï¿œ *LA SOLUZIONE* :-P
.m
-- 
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ 
http://milestone.topics.it
whynot [ at ] topics [ dot ] it

 Il Mutex ï¿œ *LA SOLUZIONE* :-P
Infatti cosa avevo suggerito? ;-)
Ciao
Raf 

 Infatti cosa avevo suggerito? ;-)
si si, appunto :-)


Da quanto dite App.PrevInstance non lo usate anche se Rafunk lo mette 
all'inizio della routine.
A proposito quel: If InDesign() vuol dire che posso testarlo anche in fase 
di debug?
Se non sbaglio App.PrevInstance in debug restituisce sempre false
Carmelo 



A me comunque questo:
If App.PrevInstance = True Then
Non ha mai dato problemi, ma non � critical il single instance nei miei
casi.

 ha scritto nel messaggio 
news:4cbedf87$0$21363$4faf...@reader3.news.tin.it...

Nel mio esempio App.PrevInstance viene usato solo se siamo nell'IDE, perché 
in questa condizione il metodo del mutex non è affidabile.
Infatti se il tuo programma non rilascia *esplicitamente* il mutex quando 
termina e comunque anche in quel caso, se si interrompe il debug senza 
uscire in modo canonico dal programma debuggato, la volta successiva che 
avvii il programma in debug il mutex è rimasto "vivo", cosicché sembrerà 
esserci una seconda istanza in esecuzione.
L'unico rimedio è uscire dall'IDE di VB6 (in tal modo si rilascia il mutex 
automaticamente).
InDesign() è una funzione "a piacere" che restituisce True quando viene 
eseguita dentro l'IDE di VB6.
Una classica implementazione è questa:
Public Function InDesign() As Boolean
Static CallCount As Integer
Static Res As Boolean
    CallCount = CallCount + 1
    Select Case CallCount
    Case 1  ' È la prima volta
        Debug.Assert InDesign()
    Case 2  ' La seconda volta: significa che è stata eseguita
            ' l'istruzione Debug.Assert
        Res = True
    End Select
    ' Se Debug.Assert è stata chiamata, si ritorna True in modo
    ' da impedire il trap
    InDesign = Res
    ' Resettata per le future ulteriori chiamate
    CallCount = 0
End Function
Ciao
Raf