Newsgroup: it.comp.lang.delphi
Titolo: Lanciare un programma exe solo una volta

Come faccio a controllare a run-time se un programma in delphi
che l'utente ha mandato in esecuzione non sia già stato lanciato
precedentemente ?
Vorrei impedire all'utente di lanciare più di una copia dello stesso
programma !
Grazie mille,
Riccardo
---
* Dott. Riccardo Fiorenza
* Dr.Soft - Soluzioni Internet
* web: 
http://www.drsoft.it
* email: 
fior...@drsoft.it

 ha scritto nel messaggio
news:hM0L8.785$K4.1...@twister2.libero.it...


sulle faq trovi delle indicazioni.
Bye
AS

Io faccio così, comunque sulle FAQ dovrebbe esserci, come è stato scritto
sulla unit di progetto
var
   Avviato : Boolean;
begin
   if OpenMutex(MUTEX_ALL_ACCESS,False,PChar('MiaApplicazione')) <> 0 then
      Avviato := True
   else
      Avviato := (CreateMutex(nil,False,PChar('MiaApplicazione')) = 0);
   sleep(1000);
   if not Avviato then
   begin
      Application.Initialize;
      Application.Title := 'MiaApplicazione';
      Application.CreateForm(TMainForm, MainForm);
        .
        .
        .
      Application.Run;
   end
   else
   begin
      // porto in primo piano l'istanza già aperta
      PostMessage(GetDesktopWindow,WM_SYSCOMMAND, SC_HOTKEY,
FindWindow(Nil,'MiaApplicazione'));
    end;
CIAOUX

 FindWindow(Nil,'MiaApplicazione'));
mi dice che WM_SYSCOMMAND non è dichiarato, di quale unit devo fare la Uses
?
L'ho trovato nell'Help, ma non ho capito dove possa essere.
Grazie Gianluigi

 Grazie Gianluigi
Approfitto per ringraziare tutte delle utilissime risposte.
Saluti,


 scritto 
sconsiglio *vivamente* l'uso di un solo mutex. Diventa un inferno 
avviare un programma come più utenti contemporaneamente. Più in 
generale: se un vostro programma ha bisogno di una singola istanza 
attiva per funzionare correttamente, avete sbagliato qualcosa
Consiglio una cosa del genere:
se sistema supporta sessioni multiple:
 crea/apri mutex con nome "Local\<nome mutex>"
altrimenti, se sistema supporta multiutenza:
 crea/apri mutex con nome "<nome mutex><id utente>"
altrimenti:
 crea/apri mutex con nome "<nome mutex>"
la prima condizione si verifica controllando se kernel32.dll esporta la 
funzione ProcessIdToSessionId. Se non esiste, il sistema non ha le 
sessioni multiple. Se chiamandola con l'id del processo attuale si 
ottiene un id di sessione uguale a zero, il sistema non ha le sessioni 
multiple
per seconda condizione, ai fini del particolare problema, advapi32.dll 
deve esportare OpenProcessToken. Se la esporta, il sistema può essere 
considerato "abbastanza multiutente" per i nostri scopi. Otteniamo il 
token del processo, poi con GetTokenInformation il SID dell'utente. 
Convertiamo il SID in una stringa (documentato nel PSDK), e costruiamo 
la stringa del mutex
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!


Perchč?
Cosa te lo fa pensare?
Se non voglio avere due servers in ascolto sulla stessa porta socket? Se non
voglio due application servers?
In generale, quando si parla di risorse uniche all'interno di un particolare
contesto, limitare un servizio ad una sola istanza non č un'idea cosě
sbagliata...
G.

 attiva per funzionare correttamente, avete sbagliato qualcosa
Non vedo perche' bisogna necessariamente aver sbagliato 
qualcosa.  E' lo stesso principio che si applica, per
esempio, alla programmazione.  Mai sentito parlare di 
singleton ? Io posso scrivere un oggetto di cui voglio
una ed un'unica istanza e non solo: quando, da qualche
parte si chiede di instanziare la classe singleton, io
non costruisco un nuovo oggetto, ma restituisco sempre 
lo stesso oggetto.  Immagina, a questo punto, di avere
un programma X che svolge una determinata funzione e
che si occupa di "loggare" ogni funzione su un db.
Ogni volta che qualcuno chiama questo programma con un
parametro, non apro istanze diverse dello stesso 
programma, ma passo semplicemente il parametro al
programma gia' aperto.  E' solo un esempio, ma ci sono 
moltissimi casi in cui e' necessario, oltre che conveniente, 
avere un'unica istanza della propria applicazione.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 avere un'unica istanza della propria applicazione.
Dimmene uno in cui è *necessario*. Io sono dell'avviso che impedire a 
priori di lanciare una nuova istanza è un abuso, e i sistemi operativi 
forniscono vie alternative e più corrette per ottenere gli stessi scopi 
che si ottengono con l'istanza singola


 è un'idea così sbagliata...
Soluzione sbagliata. Lascia che sia l'utente a decidere quante istanze 
lanciare, tu limitati a fare in modo che l'accesso alle risorse venga 
sincronizzato appropriatamente. Ripeto che è *quasi sempre* un problema 
di design, e che l'istanza singola è semplicemente la soluzione più 
"comoda"


"comoda"
Scusa, ma come fai a dire che la soluzione è sbagliata, lo hai letto
sulle foglie degli alberi?   :-)  (concedimi la battuta....).
Perchè secondo te limitare l'esecuzione ad un solo gestore (di una o
piu' ) risorse è la soluzione sbagliata?
E' come se tu dicessi che è corretto scrivere su sfondo bianco ed
invece è sbagliato scrivere su sfondo nero.
Esponi i pro/contro dell'una e dell'altra soluzione e prova a
convincerci.
Ciao, Rocco.

 "comoda"
Qui siamo d'accordo. Il design è fondamentale. E poi, spesso, la soluzione +
comoda è anche quella + corretta.
Ciao,
G.

 "comoda"
imho se una _soluzione_ e' comoda e raggiunge lo scopo non puo'
contemporaneamente definirsi sbagliata.
Il fatto che esistano altre soluzioni (sincronizzazione sull'accesso
alle risorse da usare effettivamente in esclusiva) non puo' rendere di
per se' sbagliata un'altra soluzione, anche se questa ha effetti che
vanno al di la' del minimo richiesto.
Saluti
Paolo Arosio

 ottenere gli stessi scopi che si ottengono con l'istanza singola
Per esempio ?


 singola è semplicemente la soluzione più "comoda"
Allora se e' la soluzione piu' "comoda" e' anche (probabilmente),
la piu' indicata, indi per cui non capisco come tu possa definirla
"sbagliata".  
Dicesi "soluzione" la risposta ad un problema e se il problema
e' "voglio un'istanza unica", allora la soluzione non puo' essere
sbagliata.


 Per esempio ?
Due parole: advisory locking. E non solo


 sbagliata.
se la metti così: è sbagliato il problema. Prima che chiedersi come 
fare qualcosa, è sempre meglio chiedersi perchè



Io ti do un'altro approccio: modellizza il tuo sistema sulla carta (o altro
supporto), lì ti salteranno subito agli occhi le necessità e le
caratteristiche fondamentali. Se un'entità della tua architettura
rappresenta qualcosa che PER SUA NATURA (ossia per le caratteristiche del
modello) è di cardinalità 1, permettere che la sua implementazione software
consenta invece n istanze vuol dire che nella realizzazione del progetto hai
perso informazione. Il tuo prodotto ha perso aderenza al modello originale
che risolve il problema.
Se poi per vendere dobbiamo assecondare utenti anarchici con psicosi da
costrizione da singola istanza, beh, è un problema commerciale, non di
ingegneria del SW.   ;o)
Ciao,
G.

 Due parole: advisory locking. E non solo
Ma il fatto che esistano tecniche diverse costituisce un
altro discorso.  Tu ribatti al fatto che e' sbagliato 
pretendere che vi sia un'unica istanza e quindi suppongo che,
comunque venga fatto, per te e' errato a livello di design.
Cosa che, personalmente, non condivido.


 fare qualcosa, è sempre meglio chiedersi perchè
ROTFL ;) ... I problemi non sono mai "sbagliati"...
Con tutto il rispetto, datti un'occhiata in giro e guarda
quanto software, sotto Windows, lavora per istanze singole.


 Cosa che, personalmente, non condivido.
No, ho detto che avere un'istanza singola solo per il gusto di averla 
non ha senso, e potrebbe causare, no, *causerà* problemi. Va fatto solo 
quando è necessario, cioè molto raramente. Dimmi, ad esempio, quanti 
programmi conosci tu che non si possano in nessun caso lanciare più di 
una volta. Una mia lista:
 - AOL ICQ. Perchè? nessuna reale ragione. Beh, tranne un'evidente
   falla nel design, ovviamente. Altri client ICQ non hanno questa
   limitazione. Io ora uso un altro client ICQ
 - Macromedia HomeSite. Perchè? per nascondere che il programma è un
   mostro in quanto ad utilizzo di risorse
 - Explorer. Perchè? chissà. Poco male: Internet Explorer può prendere
   tranquillamente il suo posto nella maggior parte dei casi
E ho fatto fatica a tirar fuori questi *tre* nomi. In nessuno dei tre 
casi l'istanza singola è necessaria o anche solo giustificata. E' 
necessario che ti produca una lista dei due-trecento programmi che 
*non* hanno questa limitazione?


 quanto software, sotto Windows, lavora per istanze singole.
Questo mi fa capire che cercare di spiegartelo č inutile. Pace


 non ha senso, e potrebbe causare, no, *causerà* problemi.
??? Secondo me, e ripeto, secondo me, crea più problemi un'applicazione che può avere
istanze multiple che una che ne ha una singola, sia dal punto di vista della
programmazione che dell'utente.
Comunque, il succo del discorso è che non puoi dire *a prescindere* che un *qualunque*
programma a istanza singola *causerà* problemi... mi sembra un attimo esagerato: ci sono
programmi che possono beneficiare dell'istanza multipla e altri per cui non serve
assolutamente a niente, anzi, complica la vita sia al programmatore che all'utente.
--
Jax augh.


Ok, ci arrendiamo.
Hai vinto.

 - Un server web come apache (anche se in effetti è un servizio)
Apache si lancia tranquillamente anche come programma. Anche come 
servizio, basta installarlo come più servizi, e ne hai quante istanze 
vuoi


 Hai vinto.
no, ha vinto l'ignoranza



Esatto.

 programma legato all'hardware, esonerato
<SNIP>
Va bene, alcuni esempi non erano calzanti, altri secondo me lo rimangono, come OE (gli
account multipli sono stati inventati per questo), ma comunque non hai risposto alla parte
più importante, cioè
"Comunque, il succo del discorso è che non puoi dire *a prescindere* che un *qualunque*
programma a istanza singola *causerà* problemi... mi sembra un attimo esagerato: ci sono
programmi che possono beneficiare dell'istanza multipla e altri per cui non serve
assolutamente a niente, anzi, complica la vita sia al programmatore che all'utente."
Mi sembra un ragionamento ragionevole (pardon).
Invece tu, ancor prima di sapere il tipo di programma di cui l'autore del post originale
stava parlando, hai detto:
"Più in generale: se un vostro programma ha bisogno di una singola istanza
attiva per funzionare correttamente, avete sbagliato qualcosa"
E' questa frase, credo, che a molti ha dato fastidio (insieme all'ultima "no, ha vinto
l'ignoranza")... io personalmente non sono d'accordo con le tue motivazioni, ma non ti
dico e non ti dirò mai che stai *sbagliando* o che ha vinto l'*ignoranza*.
Tutto qua; anzi, tanto di cappello se ogni tuo programma è multi-istanziabile,
multi-utente e cose del genere.
Ma c'è caso e caso, e ti ripeto che non puoi dire a prescindere che si sbaglia a fare
programmi a istanza singola, ogni programma è una storia a sé stante.
--
Jax per conto mio, stop.

 no, ha vinto l'ignoranza
Nel qual caso, suppongo, sia la stessa cosa ;)
A parte gli scherzi, e' fin troppo semplice concludere una
discussione con un "sei tu che non capisci".  Se sei veramente
convinto di quanto affermi, allora cerca di convincere anche
gli altri con argomentazioni valide.  Tu non stai spiegando
assolutamente nulla, stai solo dicendo che ci saranno sicuramente
dei problemi, con l'uso dell'istanza singola di un'applicazione.
Se hai questa certezza, ne saprai spiegare sicuramente i motivi.
Cosa che finora non hai fatto.


 quando è necessario, cioè molto raramente. 
Mi spiace, ma tu non hai detto questo e nessuno sta parlando di
"istanze singole solo per il gusto di averle".
Come al solito, in queste discussioni, prima o poi si ribalta
la frittata.  
Tu hai scritto:
"se un vostro programma ha bisogno di una singola istanza 
attiva per funzionare correttamente, avete sbagliato qualcosa"
Ora, questa frase e' talmente generale che non puoi non aspettarti
che qualcuno non sia d'accordo (anche perche', e' infondata).
Non capisco proprio (e se me lo spieghi mi fai un favore) perche'
ciascuno dei 50 impiegati che lavorano sul gestionale che ho scritto
per il mio cliente debba essere lasciato libero di lanciare il
programma piu' volte sulla stessa macchina (ti ricordo che un utente
medio non distingue, generalmente, tra "doppio-click" e 
"quadruplo-click") quando questa cosa non serve, non e' richiesta e
costituisce uno spreco di risorse inutile.
Bada bene che il mio caso non rientra negli "estramamente rari" che
citi.  E' un'applicazione gestionale multiutente che lavora su una 
base dati centralizzata e come questa ce n'e' in giro qualche buon 
milione.


 sia al programmatore che all'utente." 
Ho ammesso delle ragionevoli eccezioni, non puoi accusarmi di aver solo 
fatto affermazioni esagerate. Sto aspettando. O degli esempi attinenti, 
o della teoria convincente. Qualsiasi cosa che non sia questo ping-pong


 non e' richiesta e costituisce uno spreco di risorse inutile.
Mio parere: non è il programma in sè a doversi preoccupare di questo.  
E' il programma che lancia il programma in sè a doverlo fare. Non credo 
sia difficile scrivere qualcosa del genere, che lanci un programma e 
impedisca che venga lanciato una seconda volta. Questo ti darebbe due 
vantaggi: snellirebbe il gestionale di tutto il grasso superfluo 
rappresentato dal codice spostato nel launcher, codice che potresti 
dover togliere se il requisito dell'istanza singola non fosse più 
necessario, ad esempio in riciclaggi futuri del gestionale. E ti da' un 
programma (il launcher) tranquillamente riutilizzabile per altri scopi. 
Perchè dubito che il tuo gestionale sia l'unico programma che sia, o 
verrà mai installato su quei computer, quindi tutt'altro che l'unico a 
poter essere lanciato inavvertitamente più d'una volta


 necessario, ad esempio in riciclaggi futuri del gestionale. 
Continui a ribattere su altri argomenti.
Ti ricordo che hai obiettato al fatto che venisse usata una istanza
singola e lo ritieni sbagliato a livello di design.  Ti sto facendo
notare che cosi', moltissime volte, non e'.
Ora, non mi elencare i modi alternativi di lanciare una sola istanza
del programma, perche' le alternative si conoscono, ma si evitano
perche' non sono la scelta piu' comoda.  Non e' di questo che stiamo
parlando, ma se sia giusto o meno avere un'istanza singola.
Giusto per precisare, per me non e' affatto comodo avere uno stub che
si limita a lanciare il programma vero e proprio, quando posso 
implementare lo stesso controllo nel mio programma (il codice per 
gestire l'istanza singola e' veramente banale e corto e inoltre 
potrebbe essere benissimo incapsulato in un componente).
Pace fatta, avendo stabilito che la scelta di un'istanza singola non
e' affatto un errore di design, come erroneamente hai affermato ;).


 programma e impedisca che venga lanciato una seconda volta.
<SNIP>
*Questo* si chiama parlare... e su questo non ho alcuna difficoltà a dire che sono
d'accordo al 99% con te. Ma non potevi dirlo prima?
--
Jax
PS: Comunque, se il problema è la semplicità e la flessibilità di un pgm, esistono
componenti free che (information hiding - ovvero non mi frega più di tanto come ;) ), se
piazzati sulla form principale, impediscono che il pgm venga istanziato più volte.
Se in futuro non si vuole più questa "limitazione", basta togliere il componente e
ricompilare.
Mi sembra più semplice che avere un loader, con cui potrebbero esserci problemini, tipo
l'icona dell'exe che sarà sempre quella... ma è questione di gusti, a questo punto.