Newsgroup: it.comp.lang.visual-basic
Titolo: -- ESECUZIONE SINGOLA

ecco il mio problema.
Ho digitato questa riga:
if app.previnstance then end
in modo tale che la mia applicazione venga aperta una sola volta anche se
l'eseguibile viene lanciato + volte.
IL FATTO E' QUESTO
se copio l'eseguibile in un'altra directory, il programma viene aperto
ugualmente 2 volte.
Insomma x rendervene conto provate a fare in questo modo:
1.aprite vb e create un nuovo progetto
2.inserite nell'evento form_load() la seguente istruzione:
     if app.previnstance then end
3.compilate l'eseguibile nella dir 'c:\dir1' (ad esempio),dandogli il nome
'prova.exe'
4.create una seconda directory con il nome 'c:\dir2'
5.copiate questo file (prova.exe) in questa directory
a questo punto la situazione è la seguente:
abbiamo questi due file (identici)
c:\dir1\prova.exe
c:\dir2\prova.exe
anche se stanno in directory diverse
6.aprite c:\dir1\prova.exe
7.aprite c:\dir2\prova.exe
Come vedete entrambe le istanze vengono eseguite.
Come ovviare a tutto questo???
Mi hanno consigliato di creare un'aplicazione tipo server.Come si fà???
aspetto qualche suggerimento.
--
RISPONDETEMI SUL NEWSGROUP

Potresti creare una chiave nel registro che ti indica se il programma è
già in esecuzione. E che quindi andrai a leggere ogni volta che lanci il
programma. 
Ad esempio supponiamo che 0 indichi che non ci sono istanze del prg in
esecuzione, e 1 il contrario.
Quando lanci il prg vai a leggere la chiave:
- se questa è uguale a 0, allora la setti a 1 e continui ad eseguire il
prg. Quando termini   l'esecuzione del prg setti al chiave a 0.
- se è uguale a 1 (un'istanza è già in esecuzione) allora esci dal prg. 
 
Per l'uso del registro puoi guardare sul sito comune.
Ciao
:-) Hd (-:
p_di...@freemail.it
  (okkio, non è politico ^_^)
hd...@azienda.net
Sito Comune:
www.murialdo.it
\it_lang_vb
----------------------------------------------------------------------------
Quando l'ultimo pesce sarà catturato, l'ultima fiamma sarà 
spenta, l'ultimo fiume avvelenato, solo allora capirete che non 
si può mangiare solo denaro.
-----------------------------------------------------------------------------

 wrote


- se è uguale a 1 (un'istanza è già in esecuzione) allora esci dal prg.
Questa è una buona soluzione. Però se ti si pianta il computer mentre
l'applicazione è attiva, al successivo riavvio, l'applicazione non si avvia
più.
In un post ho letto che si poteva avere la lista dei processi attivi
mediante l'utilizzo di API.
Quindi, una volta trovata tale lista, basta controllare che in essa non vi
sia il nome dell'eseguibile in questione.

No, come diceva Gigi, l'autore del 1° msg, se il programma si viene
lanciato da 2 directory diverse, la proprietà di app non funziona,
considera i due programmi diversi.
Se ne ra già parlato tempo fa, ma non ricordo se era stata una soluzione
valida definitiva.


Hai ragione, non ci avevo pensato. Si potrebbe risolvere creando una
piccola utility da lanciare all'avvio del pc che resetta tutte le
chiavi, magari generalizzata da aggiornare automaticamente ogni volta
che installi un tuo software. 
Per ora mi viene in mente questa. Ok perdo il sonno per una settimana!
La tua soluzione non è male, ma se l'utente ( bastardo :), l'utente)
cambia nome all'eseguibile? come lo riconosci? 
-- 



Lo riconosci comunque perchè anche variando il nome dell'eseguibile non si
riesce a variare la stringa del nome originale (che sarebbe il valore della
proprietà App.title)
 contenuta nell'elenco dei task attivi.
Secondo me la soluzione sta nell'impostare nella finestra di proprietà del
progetto la proprietà "title" con un nome fittizio.
Ad esempio: NomeApplicazione0123456
Compilare l'applicazione impostando il nome dell'eseguibile nella finestra
"Make Project"
Ad esempio: NomeApplicazione.exe
E infine controllare all'avvio dell'applicazione se nei task attivi esiste
la stringa "NomeApplicazione0123456"
Attenzione il nome fittizio dato come valore della proprietà title deve
essere una stringa poco comune.
Perchè se l'utente apre (con Explorer) una cartella con lo stesso nome della
stringa della proprietà title l'applicazione risulta (erroneamente) in
esecuzione.
Dato che nell'elenco dei task attivi risulta il nome della cartella aperta.
E' facile che per sua utilità l'utente crei una cartella NomeApplicazione,
di contro è veramente difficile che creando questa cartella la nomini
NomeApplicazione0123456 o NomeApplicazioneZRT123K ecc...
Ciao a tutti.

direttamente estrapolato dall'articolo Q185730 del Knowledge Base Microsoft
(che peraltro conteneva anche alcune piccole inesattezze...sic!) posto
questo modulo che dovrebbe fare al caso tuo;
tieni presente soltanto quattro cose:
1) il progetto parte dalla Sub Main() del modulo che riporto (non è
difficile cmq operare delle modifiche in tal senso...)
2) è necessario assegnare un "nome" univoco alla propria applicazione VB
(dal menù Progetto | Proprietà di <progetto>  e successivamente tab "Crea",
campo "Titolo" all'interno del frame "Applicazione") in quanto tale valore
viene utilizzato per determinare se l'applicazione è stata o no avviata in
precedenza;
3) è possibile "fregare" tale procedura, nel caso di avvio pressochè
contemporaneo di due istanze (situazione a mio avviso abbastanza
improbabile... provate e fatemi sapere)
4) come "feature" aggiuntiva, in caso una precedente istanza è gia in
esecuzione, essa viene "gentilmente" riportata in primo piano; inoltre, come
potrete constatare dal codice, il tutto funziona siua sotto VB4, VB5 e VB6
ciao
'----------------------------------------------------------------
Option Explicit
Private Const GW_HWNDPREV = 3
Private Declare Function OpenIcon Lib "user32" _
    (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" _
    Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindow Lib "user32" _
    (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function SetForegroundWindow Lib "user32" _
    (ByVal hwnd As Long) As Long
Public Sub Main()
    If Not AppStillRunning() Then
        Dim frmMain As Form1
        Set frmMain = New Form1
        frmMain.Show
    End If
End Sub
Private Function AppStillRunning() As Boolean
    Const Vb4ClassName = "ThunderRTMain"
    Const Vb5ClassName = "ThunderRT5Main"
    Const Vb6ClassName = "ThunderRT6Main"
    Dim strOldAppTitle As String
    Dim hwndPrev As Long
    strOldAppTitle = App.Title
    App.Title = "unwanted instance"
    hwndPrev = FindWindow(Vb4ClassName, strOldAppTitle)
    If (hwndPrev = 0) Then
        hwndPrev = FindWindow(Vb5ClassName, strOldAppTitle)
        If (hwndPrev = 0) Then
            hwndPrev = FindWindow(Vb6ClassName, strOldAppTitle)
        End If
    End If
    App.Title = strOldAppTitle
    If (hwndPrev = 0) Then
        AppStillRunning = False
        Exit Function
    End If
    hwndPrev = GetWindow(hwndPrev, GW_HWNDPREV)
    OpenIcon hwndPrev
    SetForegroundWindow hwndPrev
    AppStillRunning = True
End Function
'----------------------------------------------------------------
gigi <gi...@ccm.ot> wrote in message 7rvtar$ft5$8...@nslave1.tin.it...


 potrete constatare dal codice, il tutto funziona sia sotto VB4, VB5 e VB6
Questa parte è stata istruttiva. Grazie anche da parte mia.
Ciao
*Roby*

 wrote in message


 peccato che se c'e' un'applicazione con lo stesso .Title tutto va a monte
ahimč, č questa infatti la nota dolente del tutto.... l'unico consiglio che
posso dare č: siate fantasioni con il nome dell'applicazione; ricordate poi
che il nome dell'applicazione non va su video (non confondete la Caption
della Form principale con la App.Title...)
ciao

 >    OpenIcon hwndPrev
serve a ripristinare una eventuale applicazione "iconizzata"
ciao

 semaforo nella stessa directory della base dati.
il problema è che l'apertura di un file (così,come una chiamata a
FindWindow) non è una operazione "atomica"; mi spiego meglio: per istruzione
atomica si intende una istruzione non interrompibile; in altre parole, un
task può essere interrotto da un altro task pressochè in qualsiasi momento
(è questo il concetto di multitasking premptive...);
è possibile (anche se molto improbabile...) che un task possa interrompere
la fase di Open di un file e permettere ad un altro task di procedere; in
tal caso potrebbe anche succedere che il task partito per primo ottenga una
risposta di errore alla Open, mentre quello partito per ultimo potrebbe
procedere;
poco male, dirai tu; in effetti in una situazione come questa (evitare che
due istanze di un programma partano in contemporanea) non avrei alcun
problema per una eventualità del genere
invece, se la logica del "chi tardi arriva male alloggia" dovesse essere
implementata in maniera rigorosa beh, allora ne la Open ne la FindWindow
funzionano bene;
l'unico modo per gestire situazioni simili in un contesto multitasking è
l'utilizzo dei mutex; i mutex sono come dei semafori che servono per
realizzare la maggior parte delle sincronizzazioni in ambiente multitasking
win32;
se avrò tempo proverò a buttar giù due righe di vb per chiarire il concetto;
ciao