Newsgroup: it.comp.lang.delphi
Titolo: Una sola istanza di una applicazione

Sapete se c'è un metodo per sapere se
un'applicazione è già stata eseguita
per prevenire che l'utente la lanci + volte?
Ho trovato un paio di tips in giro
ma non riesco a farli andare.
C'è un metodo elegante, una funzione API,
un oggetto o qualcos'altro che avete testato e che funzioni?
Grazie 1024.
Alan Solo

 un oggetto o qualcos'altro che avete testato e che funzioni?
La soluzione più efficace e meno dispendiosa è usare un mutex...
Crea il mutex (CreateMutex) nel file di progetto (dpr) e testane l'esistenza
prima di crearlo.
Ricorda di liberare il mutex alla fine dell'esecuzione del programma e cerca
una stringa univoca per distinguerlo da tutti gli altri (se proprio vuoi
essere sicuro che sia univoca usa una GUID)
Ciao :-)
--
(¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
AntiSpam: rimuovere il trattino basso dall'indirizzo per rispondere
AntiSpam: remove the underscore from the e-mail address to reply

La soluzione più efficace e meno dispendiosa è usare un mutex...
Beh ce n'è una ancora piu' facile: vai su torry, scarichi il componente
OnlyOne (si chiamava così ?), lo metti nella form e basta :)
Ciao !

{MSX}

grazie.
... da quando scrivo su questo ng sono diventato un po' scansa fatiche. :)
Per la cronaca su torry system-istance ho scaricato XJustOne,
funziona bene, oltre a prevenire + istanze porta in primo
piano quella già in esecuzione...
Scusate per la domanda idiota, potevo anche fare da solo ;)
ps per Andrea: per il momento mi basta l'oggettino, grazie cmq...
Ciao!
Alan Solo

ps per Andrea: per il momento mi basta l'oggettino, grazie cmq...
per quel che posso ti do un consiglio, è vero che l'oggettino è sufficiente,
ma è sempre meglio provare quello che fai [anche perchè l'implementazione di
un mutex è tutt'altro che difficile] prima di utilizzare un componente.
Inoltre mi sembri parecchio pratico con Delphi, quindi penso che 2 righe di
codice in + non ti spaventino! :-)
Ciao!
--
- Carlo -

mi sembra che devi usare globalatom o qualcosa del genere dai un'occhiata
sull'help
--
Gna...@Wappi.com
ICQ# 76488613
http://gnaffy.tripod.com/

 ps per Andrea: per il momento mi basta l'oggettino, grazie cmq...
Immaginavo...


 un mutex è tutt'altro che difficile] prima di utilizzare un componente.
haaaargh! è mezzanotte passata e mi avete costretto
ad andare a vedermi i source, altrimenti non riuscivo a dormire!!
posto una versione ridotta (fa funzionante e, se permettete,
migliore, mettendo un pchar anzichè usare
StrPCopy come ha fatto l'autore dell'oggetto):
var Mutex: hWnd;
...
begin
 Mutex := CreateMutex(nil, False, pchar(Application.title));
 if (GetLastError = ERROR_ALREADY_EXISTS) or (Mutex = 0)
  then begin // istanza già esistente
   Application.ShowMainForm := False;
   Application.Terminate;
  end
  else begin // prima esecuzione...
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
  end;
end.
... e alla fine un bel CloseHandle(Mutex);
aaah, avete ragione, ora che so COSA fa quell'oggettino mi sento
molto meglio!! :-)
Alcune curiosità:
-perchè si chiama mutex??
-Come fà a sapere che è proprio quell'applicazione?
... mi spiego, ho provato a fare un programma 'vuoto'
mettento come app.title 'Calcolatrice', e con la calcolatrice
di win aperta il mio programma va ugualmente...xchè?
Le domande ve le siete cercate voi, eh? :-))))
Ciao!
Alan Solo.

 di win aperta il mio programma va ugualmente...xchè?
Dunque, la CreateMutex crea un oggetto e gli dà un "nome" che è il parametro
(nel tuo caso l'application.title).
Il sistema (a livello globale) mantiene una lista di questi oggetti e va a
cercarsi il mutex ogni volta che chiami la CreateMutex o simili.
Ti consiglio di usare una stringa che identifichi in modo molto stretto il
tuo programma, ad esempio : "Nome_del_programma-Autore-versione" o cmq
qualcosa che difficilmente venga in mente a qualcunaltro: se mettiamo
entrambi "Ciao" e un utente lancia i nostri due programmi uno dei due non
va...
Se sei paranoico puoi perfino usare un GUID, che quello sei _sicuro_ che è
univoco... (usa CTRL+SHIFT+G nell'editor di Delphi)


di win aperta il mio programma va ugualmente...xchè?
Il nome che va dato non e' quello dell'applicazione, ma il nome del
mutex.
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------
#exclude <windows.h>

qualsiasi, tuttavia e' consigliabile.
Beh qualsiasi non direi...ti ricordo che all'insieme degli oggetti Kernel
appartengono anche Processi, Thread, MailSlot etc....
Non mi sembra un'ottima idea utilizzare un processo per vedere se è già
attiva un'istanza del tuo programma! :)
Direi che gli oggetti Kernel che si prestano meglio sono Semafori e
Mutex.... C'è anche chi li implementa contemporaneamente nelle proprie
applicazioni.
Ciao
--
- Carlo -


Prova questo:
Ciao,
David
{
                ------------------------------------
                   Gestione istanze multiple e no
                ------------------------------------
                   Nome      : UNIT_FINDCLASS
                   Autore    : Guadagnini David
                   Versione  : 1.0
                   Creazione : 27/10/1998
                   O.S.      : Window 95/98/NT
  Il nome della classe e' rilevabile dal file di progetto nella chiamata
  Application.CreateForm
  Esempio:
  Begin
    Application.Initialize;
    Application.CreateForm(TTFindWindow, TFindWindow);
    Application.Run;
  End;
  il nome della classe sara' TTFINDWINDOW (att. scrivere in maiuscolo)
  N.B.:
       Per prevenire le istanze multiple modificare il file di progetto
       nel seguente modo:
       1) Inserire la chiamata a LOOKIFIEXIST immediatamente prima
          di Application.Initializate
       2) Inserire la chiamata a LOOKIFIEXIST immediatamente dopo
          di Application.Initializate
       Il passo (2) e' necessario per prevenire l'eventualita' che
       l'operatore esegua un quadruplo click (non scherzo!)
       Il progetto di esempio diverrebbe :
          Begin
            LookIfIExist('TTFFINDWINDOW');  // Chiamata base
            Application.Initialize;
            LookIfIExist('TTFFINDWINDOW');  // Chiamata di emergenza
            Application.CreateForm(TTFindWindow, TFindWindow);
            Application.Run;
          End;
}
unit Unit_FindClass;
interface
Uses
  Forms, Windows, Messages, SysUtils;
// --------------------------------------------------
// Ritorna se una determinata classe e' attiva
// --------------------------------------------------
Function  IsClassPresent(Const NomeClasse : String) : Boolean;
// --------------------------------------------------
// Ritorna l'handle della finestra della classe
// NOMECLASSE presente nel sistema (0=Non Presente)
// --------------------------------------------------
Function  GetWindowFromClass(Const NomeClasse : String) : HWND;
// --------------------------------------------------
// Passa il fuoco alla finestra di classe NOMECLASSE
// (False -> Classe non trovata)
// --------------------------------------------------
Function  MakePrimaryWindow(Const NomeClasse : String) : Boolean;
// --------------------------------------------------
// Passa il fuoco alla finestra di classe NOMECLASSE
// e termina il programma
// (ottimo per prevenire le istanze multiple)
// --------------------------------------------------
Procedure LookIfIExist(Const NomeClasse : String);
implementation
Function IsClassPresent(Const NomeClasse : String) : Boolean;
Var
  S : Array[0..255] Of Char;
Begin
  StrPCopy(S, NomeClasse);
  Result := (FindWindow(S, Nil) <> 0);
End;
Function GetWindowFromClass(Const NomeClasse : String) : HWND;
Var
  S : Array[0..255] Of Char;
Begin
  StrPCopy(S, NomeClasse);
  Result := FindWindow(S, Nil);
End;
Procedure _Delay(Millisec : DWORD);
Var
  Conta : DWORD;
Begin
  Conta := GetTickCount;
  Conta := Conta+Millisec;
  Repeat
  Until (GetTickCount > Conta);
End;
Function MakePrimaryWindow(Const NomeClasse : String) : Boolean;
Var
  H, I : HWND;
Begin
  H := GetWindowFromClass(NomeClasse);
  Result := False;
  If H <> 0 Then
     Begin
       I := GetLastActivePopUp(H);
       BringWindowToTop(H);
       If IsIconic(I) Then ShowWindow(I, SW_RESTORE)
                      Else SetForegroundWindow(I);
       Result := True;
     End;
End;
Procedure LookIfIExist(Const NomeClasse : String);
Begin
  _Delay(500);
  If MakePrimaryWindow(NomeClasse) Then Halt;
End;
end.

applicazioni.
Bertuccini, devi imparare a leggere i messaggi che vengono scritti :
io ho detto che la natura di un oggetto kernel e' indipendente
dall'uso che se ne fa in questo contesto. Ho chiaramente specificato
che e' CONSIGLIABILE utilizzare mutex per cio' che ci si prefigge in
questo caso.


 univoco... (usa CTRL+SHIFT+G nell'editor di Delphi)
bello! Non le aveva mai usate!
altra domanda: ma č unico in assoluto o lo č solo sul mio sistema?
(help di delphi: ...globally unique identifier??) io ho qualche
dubbio, potrebbe capitare di avere due GUID uguali, o no?
PS: Grazie 1000 per le spiegazioni sui mutex!
...certo era sě + comodo piazzare il componente e fragarsene,
ma vuoi mettere? ... ora ho imparato qualcosa in +!! ;-)
(daltronde č un po' la filsofia di delphi, quello di semplificarci
la vita, ...proprio in questi giorni sto dando un'occhiata a DelphiX,
un mega pacchetto che rende l'uso delle DirectX facile anche per
un bambino dell'asilo... mi sembra quasi di rubare...
in VC++ ci avevo messo un pacco si tempo per far girare un triangolo!
... quello che voglio dire č che in questo caso (dei mutex) non era poi
cosě difficile neanche 'a mano' ma in altri casi bisogna saper trovare
un compromesso tra
tempo a disposizione - soddisfazione - ottimizzazione - ecc....ecc...
delphi in molti casi ti offre le due strade, facile o difficile
con aspetti positivi e negativi che ne derivano...)
Byez! :-)
Alan Solo

 [...]
hmmmm... Guadagnini........ sei trentino?? :-)
Ciao!
Alan Solo

questo caso.
Guarda, non ho affatto intenzione di polemizzare, potrei essere io ad aver
interpretato male il tuo messaggio, cmq sono convinto di aver letto bene!
Ecco il tuo messaggio :
--
I mutex sono oggetti kernel.
Non e' strettamente necessario utilizzare un mutex per verificare che
un'istanza di un'applicazione sia gia' aperta, ma un oggetto kernel
qualsiasi, tuttavia e' consigliabile.
--
Io ho solo puntualizzato che, a mio avviso, quella frase incidentale
dovrebbe essere rimossa!


 ma vuoi mettere? ... ora ho imparato qualcosa in +!! ;-)
Beh, quando ho scritto "immaginavo" era perchè in genere la domanda che hai
posto salta fuori quando hai già finito il programma e ti serve solo il modo
che non venga eseguito due volte ...
Quando successe a me cercai il componente lo piazzai sulla form principale e
non lo guardai per 2 mesi.. ;-)
Certo che poi è interessante scoprire come funzionano le cose...
Ciao :-)
--
Andrea Magni
E-Mail: 
ama...@interac.it