Newsgroup: it.comp.lang.visual-basic
Titolo: Istanza già attiva dell'applicazione

Ho visto spesso richieste su come capire se l'applicazione eseguita è già in esecuzione, e soprattutto su come 
visualizzare automaticamente la finestra relativa all'istanza già avviata; io ho risolto il problema in questo modo,
fatemi sapere come vi sembra e soprattutto se si può fare di meglio:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Nel punto di ingresso dell'applicazione leggo dal registry di windows se è già presente un'istanza dell'applicazione.
MODULO: basApp.bas
---------------------------------
dim gl_HwndPrevInst as Long
...............
sub Main()
   ...............
   ' Ricevo l'handle eventualmente memorizzato dall'istanza attiva, se esistente
   gl_HwndPrevInst = GetSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND, 0)
   ' - Se esiste già un'istanza avviata segnalo l'errore e richiamo il metodo di uscita dall'applicazione con parametro false per non fare
   '   cancellare la chiave sul registry di windows.
   ' - Altrimenti carico il form principale
   If (gl_HwndPrevInst > 0) Then
      Call Segnala_Errore(...,...,...,...)
      Call QuitApplication(False)
   Else
      Load frmMain
      frmMain.Show
   End If
   ...............
End Sub
' Metodo di uscita dall'applicazione, per abbandonare l'applicazione si deve assolutamente richiamare questo metodo in quanto deve essere
' cancellata dal registry la chiave che indica la presenza di una istanza già avviata
Public Sub QuitApplication(Optional pb_Registry As Boolean = True)
   .............
   ' Cancello la chiave sul registry se non è stato indicato diversamente dal parametro ricevuto
   If pb_Registry = True Then
      Call DeleteSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND)
   End If
   ' Se è stata rilevata una istanza già avviata chiamo il metodo che mi permette di portarla in primo piano
   If gl_HwndPrevInst > 0 Then
      Call ShowPrevInstance(gl_HwndPrevInst)
   End If
   End
End Sub
-------------------------------------------------------
MODULO: basShowPrevInstance.bas
-------------------------------------------------------
' - API: ShowWindow
' Dichiarazione costanti API
Public Const SW_HIDE = 0 ' finestra nascosta ma attivata
Public Const SW_SHOWNORMAL = 1 ' posizione di default e attivata
Public Const SW_SHOWMINIMIZED = 2 ' ridotta a icona e attivata
Public Const SW_SHOWMAXIMIZED = 3 ' ingrandita e attiva
Public Const SW_SHOWNOACTIVATE = 4 ' pos. di default, non att.
Public Const SW_SHOW = 5 ' nella posizione corrente, attiva
Public Const SW_MINIMIZE = 6 ' riduce a icona
Public Const SW_SHOWMINNOACTIVE = 7 ' minimizza, non attiva
Public Const SW_SHOWNA = 8 ' nella pos. corrente, non attiva
Public Const SW_RESTORE = 9 ' alla posizione di default, attiva
Public Const SW_SHOWDEFAULT = 10 ' posizione di default, attiva
' Dichiarazione funzione API
Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Public Function ShowPrevInstance(pl_Hwnd As Long) As Boolean
   ' Le 2 seguenti chiamate alle API permettono di scatenare l'evento resize del form relativo all' handle
   ' memorizzato nel registry all'avvio dell'applicazione nell'istanza precedente
   Call ShowWindow(pl_Hwnd, SW_SHOWMINIMIZED)
   Call ShowWindow(pl_Hwnd, SW_SHOWNORMAL)
End Function
----------------------------------------------------------------------------------------------------------------------------------------------------------
FORM: frmMain.frm
---------------------------------
Public Sub Form_Load()
   ...........
   ' Memorizzo nel registry l'handle del form principale (un form MDI sarebbe l'ideale)
   Call SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND, Me.hwnd)
   ...........
End Sub
Private Sub Form_Resize()
   ' Quando viene scatenato l'evento resize porto in primo piano e assegno il focus al form in questione
   On Error Resume Next
   Me.ZOrder 0
   Me.SetFocus
   On Error GoTo 0
End Sub
----------------------------------------------------------------------------------------------------------------------------------------------------------
Spero possa essere utile a qualcuno e magari di avere indicazioni su come migliorare il codice o su eventuali
problemi a me sfuggiti.
Ciao Stefano  ;-)
_________________________________________________________________________
la tua email gratuita e per sempre su 
http://www.freemail.it
 (anche POP3)
-- 
Posted from 
qma...@hermes.evo.it
 [194.184.29.10] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Nel punto di ingresso dell'applicazione leggo dal registry di windows se è



 e' il caso in cui app.previnstance non lo capisce ?
A vederla cosi', mi sembra una bella idea per risolvere proprio questo caso.
Mi rimane pero' un dubbio: che succede al successivo riavvio del prg se
questo e' precedentemente uscito per crash (suo o dello stabilissimo windows
?)
Ciao
Aldo





Funziona poichè non uso App.Previnstance ma 
utilizzo il registry di windows


Ciao Stefano







Ciao Aldo,


hai giusto evidenziato il punto che sto ancora 
cercando di risolvere...


...anzi a dire il vero mentre sto rispondendo al 
post forse mi è venuta un'idea, ma visto che non sono sicuro ne approfitto per 
avere un aiuto.


Nel caso di crash di sistema riavviando 
l'applicazione dopo il riavvio del sistema


andrei a leggere l'handle di un qualcosa non più 
esistente o (non ne sono sicuro) assegnato, dopo il riavvio del sistema 
operativo, a qualcos'altro che non centra niente con la mia 
applicazione.


Sai se tramite l'handle è possibile sapere se si 
sta fancendo riferimento al form


della mia applicazione.


 


A me è venuta in mente questa possibile 
soluzione:


 


Utilizzo 1 flag nel registry per sapere se il 
metodo resize del form è stato chiamato da un'altra applicazione o no, questo 
mettendo nel metodo main appena prima del


metodo QuitApplication la scrittura del flag nel 
registry. Nel metodo resize del form verificherò nel registry la presenza di 
tale flag per capire se scrivere un secondo


flag per capire se è effettivamente avviata 
un'altra istanza della mia applicazione. A questo punto nel metodo quit posso 
testare il secondo flag per capire se 


è stato effettivamente chiamato il metodo resize di 
una mia applicazione, in tal caso cancellerò dal registry tutte le 
chiavi.


 


MODULO: 
basApp.bas
---------------------------------
dim gl_HwndPrevInst as 
Long
...............
sub Main()
   
...............
   ' Ricevo l'handle eventualmente memorizzato 
dall'istanza attiva, se esistente
   gl_HwndPrevInst = 
GetSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_HWND, 0)
   ' - Se esiste già un'istanza 
avviata segnalo l'errore e richiamo il metodo di uscita dall'applicazione con 
parametro false per non fare
   '   cancellare la chiave 
sul registry di windows.
   ' - Altrimenti carico il form 
principale
   If (gl_HwndPrevInst > 0) 
Then
      Call 
Segnala_Errore(...,...,...,...)


 




      ' - MODIFICA 
3-12-2000
      ' MEMORIZZO IL PRIMO FLAG 
(AVVIO APPLICAZIONE)
      Call SaveSetting(GCS_APP_REGISTRY, 
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_START, 
"1")


 


      Call 
QuitApplication(False)
   End If


   Load frmMain
   
frmMain.Show


   ...............
End Sub
' 
Metodo di uscita dall'applicazione, per abbandonare l'applicazione si deve 
assolutamente richiamare questo metodo in quanto deve essere
' cancellata dal 
registry la chiave che indica la presenza di una istanza già avviata
Public 
Sub QuitApplication(Optional pb_Registry As Boolean = True)
   
.............
   ' Cancello la chiave sul registry se non è stato 
indicato diversamente dal parametro ricevuto
   If pb_Registry = 
True Then
      Call DeleteSetting(GCS_APP_REGISTRY, 
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND)
   End 
If
   ' Se è stata rilevata una istanza già avviata chiamo il 
metodo che mi permette di portarla in primo piano
   If 
gl_HwndPrevInst > 0 Then
      Call 
ShowPrevInstance(gl_HwndPrevInst)




      ' - MODIFICA 
3-12-2000


      ' ELIMINO IL PRIMO FLAG 
DAL REGISTRY (AVVIO APPLICAZIONE)
      Call DeleteSetting(GCS_APP_REGISTRY, 
GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_START)
      ' SE 
NEL REGISTRY E' PRESENTE IL SECONDO FLAG ALLORA SIGNIFICA CHE ESISTE 
UN'ISTANZA DELLA MIA APPLICAZIONE


      If 
GetSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_EXIST, "0") = "1" then


         ' ELIMINO 
IL SECONDO FLAG DAL REGISTRY (APPLICAZIONE ESISTENTE)


         
Call DeleteSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_EXIST)


      
Else




         ' ELIMINO 
IL SECONDO FLAG DAL REGISTRY (APPLICAZIONE ESISTENTE) ANCHE IN QUESTO CASO, 
E CANCELLO ANCHE LA CHIAVE


         ' 
RELATIVA ALL'HANDLE DELLA APPLICAZIONE CHIUSA IN MODO ANOMALO


         
Call DeleteSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_EXIST)


         Call 
DeleteSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_HWND)
         ' 
MANDO UNA SEGNALAZIONE CHE LA PRECEDENTE ESECUZIONE DEL PROGRAMMA NON E' STATA 
CHIUSA NEL MODO CORRETTO


         msgbox "..........."


         ' ESCO DEL METODO SENZA 
CHIUDERE IL PROGRAMMA


         Exit 
Sub
      End If


 


   End If



----------------------------------------------------------------------------------------------------------------------------------------------------------
FORM: 
frmMain.frm
---------------------------------
Public Sub 
Form_Load()
   ...........
   ' Memorizzo nel registry 
l'handle del form principale (un form MDI sarebbe l'ideale)
   Call 
SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_HWND, Me.hwnd)
   ...........
End 
Sub
Private Sub Form_Resize()
   ' Quando viene scatenato 
l'evento resize porto in primo piano e assegno il focus al form in 
questione
   On Error Resume Next


   ' - MODIFICA 
3-12-2000




   ' SE NEL REGISTRY E' PRESENTE IL 
PRIMO FLAG ALLORA VALORIZZO IL SECONDO FLAG SEMPRE NEL REGISTRY


   If GetSetting(GCS_APP_REGISTRY, 
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_START, "0") = "1" 
then


      ' 
MEMORIZZO NEL REGISTRY IL SECONDO FLAG


      Call 
SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, 
GCS_KEY_REGISTRY_APP_EXIST, "1")


   End If


 


   Me.ZOrder 0
   Me.SetFocus
   On 
Error GoTo 0
End 
Sub
----------------------------------------------------------------------------------------------------------------------------------------------------------


 


Dovrebbe funzionare ma non l'ho provato, ho scritto direttamente sulla 
mail, però a logica mi sembra funzionare.


Ciao Stefano



Sempre ragionando senza provare, e quindi tanto per spandere un po' di byte
in giro, mi sembra allora che un modo piu' efficace potrebbe essere il
ricorso a FindWindow. Se viene trovata una certa finestra allora l'
applicazione e' in esecuzione, altrimenti no.
Le soluzioni che fanno uso di flag e controflag mi lasciano sempre un po'
dubbioso, perche' ho sempre paura che siano come i sistem per vincere alla
roulette: apparentemente sicuri, matematicamente perdenti.
Hai mica continuato gli esperimenti ?
Ciao
Aldo

Mi hai dato giusto giusto l'informazione che mi serviva,
ho fatto alcune prove con FindWindow ed ho risolto il problema, anche se non ho capito una cosa:
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
Io utilizzo l'API passando solo il secondo parametro (lpWindowName),
cioč il nome che compare nella barra del titolo, ma nel 
secondo parametro non ho capito che valore del form devo
passare.
Appena riesco vedrň di incapsulare il tutto e di mettere
a disposizione il codice, sperando possa essere utile.
Grazie ancora e ciao,
Stefano


 a disposizione il codice, sperando possa essere utile.
Il ng sara' riconoscente.
Ciao
Aldo