L_art_ment
Messages postés302Date d'inscriptionvendredi 21 septembre 2007StatutMembreDernière intervention 6 février 2013
-
10 déc. 2007 à 13:47
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 2014
-
17 déc. 2007 à 18:26
Mes cieux d'âmes,
Bouh j'ai une question pour vous, j'ai une application qui se lance automatiquement au démarrage de windows et qui n'est pas visible par l'utilisateur, j'aimerais que lorsqu'il désire lancer l'appli (donc il l'execute une deuxiéme fois) la premiére devienne visible et que la deuxiéme se ferme...
Alors j'ai vu le composant RunOne d'aprés ce que j'ai compris il permettrait de faire cela, mais je ne comprend pas bien comment il s'emploie...
Si vous pouviez m'éclairer (je n'ai pas la lumiére à tous les étages lol)
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 10 déc. 2007 à 18:57
Salut,
Sans compo, avec un Mutex:
IMPLEMENTATION
{$R *.dfm}
var HandleMutex : THandle;
function ExecuteDeja : Boolean;
begin
SetLastError(NO_ERROR);
result := true;
if OpenMutex(MUTEX_ALL_ACCESS, false,
pChar(ExtractFileName(Application.ExeName))) <>0 then exit;
HandleMutex := CreateMutex(Nil, true,
pChar(ExtractFileName(Application.ExeName)));
if HandleMutex = 0 then exit;
result := false;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if ExecuteDeja then begin
...
...
Rendre la 1ère visible...
...
Halt;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if HandleMutex <> 0 then ReleaseMutex(HandleMutex);
end;
END.
L_art_ment
Messages postés302Date d'inscriptionvendredi 21 septembre 2007StatutMembreDernière intervention 6 février 2013 11 déc. 2007 à 09:28
Euh re-bonjour,
J'ai essayé la methode Caribensila, j'ai implenté le morceau de code que tu m'as donné dans le miens, mais je ne vois pas comment "rendre la 1er visible" j'ai essayé avec les OLEs sans succées, lorsque j'ouvre une seconde fois mon appli, windows me dit "monappli.exe a rencontré un probléme" lol sans dec' ?
J'vois pas trop comment faire autrement :s ...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 11 déc. 2007 à 09:49
je reitere en te conseillant UnPas2, il est super simple a utiliser.
- Tu le pose sur ta form
- tu met la propriete StopSiDejaLance a True
- tu implemente l'evenement OnOtherTryToRun, qui sera appelé (sur ton instance a conserver) quand une autre instance sera lancée
L_art_ment
Messages postés302Date d'inscriptionvendredi 21 septembre 2007StatutMembreDernière intervention 6 février 2013 11 déc. 2007 à 13:55
Oui je sais que c'est pratique, je m'était fait avoir pour un autre composant dont j'avais besoins pour une autre application (je ne sais plus lequel c'était) et c'est comme ca que je me suis appercu que je ne pouvais pas en installer de nouveaux :s mais là j'avais reussi à bidouiller.
Je vais me pencher sur la methode de Cari, car ca m'aiderait bien de reussir !
Je suis en train de chercher comment envoyer un mail aussi, alors ce n'est pas compliqué lorsqu'on connait le SMTP mais dés lors qu'on ne le connais pas, c'est déjà moins amusant lol
J'ai essayé avec ShellExecute, mais l'email ne s'envoit pas, peut être parce que la machine sur lequel je programme est connecté reseau je ne sais pas...
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 11 déc. 2007 à 16:28
Re
« mais je ne vois pas comment "rendre la 1er visible" »
Le plus simple, ce serait de créer un Thread dans la première instance qui surveille un fichier qui est mis à jour au lancement de la deuxième instance.
Ou alors, plus complexe peut-être, créer un sémaphore...
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 11 déc. 2007 à 16:41
... J'pense à un truc.
Il y a aussi un autre objet de synchronisation : l'événement avec "CreateEvent".
C'est une valeur booléenne globale qu'un nombre quelconque de processus peuvent attendre qu'il soit déclenché.
L_art_ment
Messages postés302Date d'inscriptionvendredi 21 septembre 2007StatutMembreDernière intervention 6 février 2013 12 déc. 2007 à 09:27
Je n'arrive pô à utiliser les methodes sur le lien que j'ai posté au dessus, alors j'me lance dans le thread, c'est une grande premiére lol mais ca va j'viens de lire un tuto sur les threads ca n'a pô l'air mechant, enfin ....
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 13 déc. 2007 à 12:46
Arf, = pour l'affectation et guillemets doubles... C détend fortement sur mon Delphi...
Pas top la méthode du FindWindow. J'ai essayé de faire comme Cari mais
je parviens pas non plus à mettre la fenêtre de l'ancienne au premier
plan :
unit pasOneInstance;
interface
uses
Forms, Windows, SysUtils, Classes;
// Mettre en commentaire la ligne suivante pour que la première instance
// affiche sa form normalement au lancement de l'appli.
{$DEFINE STARTHIDDEN}
type TNewInstanceWaiter = class(TThread)
protected
procedure Execute(); override;
end;
type TOneInstance = class(TObject)
public
constructor Create();
destructor Destroy(); override;
private
hMutex: THandle; // Le mutex permettant de savoir si l'application est déjà lancée
hEvent: THandle; // L'event déclenché quand la première instance doit être activée
bFirstInstance: Boolean; // Est ce la première instance
lpNewInstanceWaiter: TNewInstanceWaiter; // Thread qui attend le lancement d'une nouvelle instance
function ThereIsAPreviousInstance(): Boolean;
procedure WaitForNewInstance();
procedure CreateBringToFrontEvent();
procedure FreeResources();
end;
var
lpOneInstance: TOneInstance;
implementation
procedure TNewInstanceWaiter.Execute();
begin
while True do
begin
lpOneInstance.WaitForNewInstance();
if Terminated then Exit;
// La fenêtre ne fait que signaler qu'elle souhaiterait être au premier plan
Synchronize(Application.BringToFront);
//Synchronize(Application.MainForm.BringToFront);
//SetForegroundWindow(Application.MainForm.Handle);
//SetWindowPos(Application.MainForm.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end;
end;
procedure TOneInstance.FreeResources();
begin
if bFirstInstance then
begin
ReleaseMutex(hMutex);
lpNewInstanceWaiter.Terminate;
SetEvent(hEvent);
lpNewInstanceWaiter.WaitFor();
lpNewInstanceWaiter.Free();
end;
CloseHandle(hMutex);
CloseHandle(hEvent);
end;
function TOneInstance.ThereIsAPreviousInstance(): Boolean;
var
nWaitResult: Cardinal;
begin
// Création du mutex qui va permettre de savoir si une instance est déjà lancée
hMutex:= CreateMutex(nil, False, PChar(ExtractFileName(Application.ExeName) + 'Mutex'));
if hMutex = 0 then
begin
RaiseLastOSError();
FreeResources();
Halt;
end;
// On regarde si une instance possède déjà le mutex
nWaitResult:= WaitForSingleObject(hMutex, 0);
case nWaitResult of
WAIT_FAILED :
begin
bFirstInstance:= False;
RaiseLastOSError();
FreeResources();
Halt;
end;
WAIT_TIMEOUT :
bFirstInstance:= False;
else
bFirstInstance:= True;
end;
Result:= not bFirstInstance;
end;
procedure TOneInstance.CreateBringToFrontEvent();
begin
// Création ou récupération d'un event demandant l'affichage de la fenêtre de la première instance
hEvent:= CreateEvent(nil, False, False, PChar(ExtractFileName(Application.ExeName) + 'Event'));
if hEvent = 0 then
begin
RaiseLastOSError();
FreeResources();
Halt;
end;
end;
procedure TOneInstance.WaitForNewInstance;
begin
if WaitForSingleObject(hEvent, INFINITE) = WAIT_FAILED then
begin
RaiseLastOSError();
FreeResources();
Halt;
end;
end;
constructor TOneInstance.Create();
begin
CreateBringToFrontEvent();
if ThereIsAPreviousInstance() then
begin
SetEvent(hEvent);
FreeResources();
Halt;
end
else
begin
{$IFDEF STARTHIDDEN}
WaitForNewInstance();
Application.BringToFront();
{$ENDIF}
lpNewInstanceWaiter:= TNewInstanceWaiter.Create(False);
end;
end;
destructor TOneInstance.Destroy();
begin
FreeResources;
end;
L_art_ment
Messages postés302Date d'inscriptionvendredi 21 septembre 2007StatutMembreDernière intervention 6 février 2013 13 déc. 2007 à 15:49
Whaou il vat me falloir 3 jours pour comprendre ce que ca fait
Merci pour ce "petit" code, là je ne peux pas trop faire de tests car je suis un petit peu occupé ailleurs, mais dés que je me remettrais dessus je te tiens au courant voir si j'arrive à le faire fonctionner, là j'avais essayé une autre methode mais vaine également (copier mon .exe à un autre endroit puis changer son titre : "application.title" mais ca ne marche pô même pô juste )
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 13 déc. 2007 à 19:17
J'atteins là l'ultime limite de mes compétences, mais je poste quand même car ça a l'air de marcher... :)
implementation
{$R *.dfm}
var HandleMutex : THandle;
Event : THandle;
HandleThread : THandle;
function ExecuteDeja : Boolean;
begin
SetLastError(NO_ERROR);
result := true;
if OpenMutex(MUTEX_ALL_ACCESS, false,
pChar(ExtractFileName(Application.ExeName))) <>0 then exit;
HandleMutex := CreateMutex(Nil, true,
pChar(ExtractFileName(Application.ExeName)));
if HandleMutex = 0 then exit;
result := false;
end;
procedure RendreVisible(HWnd:THandle);
begin
//attend le déclenchement de l'événement...
WaitForSingleObject(Event,INFINITE);
//...et indique à l'application ce qu'elle doit faire dans ce cas:
Form1.Memo1.Lines.Add('Une 2ème instance a été lancée puis détruite');
//Ici, ton code qui rend la 1ère visible...
end;
procedure TForm1.FormCreate(Sender: TObject);
var id : Cardinal;
begin
if ExecuteDeja then begin //Si c'est une 2ème instance.
Event := CreateEvent(nil,True,False,'MonEvent');//On ouvre un événement...
PulseEvent(Event);//déclenche l'événement et le désarme aussotôt.
Halt; end //et on massacre cette instance.
else begin //Si 1ère instance.
Memo1.Lines.Add('ceci est la 1ère instance');
Event := CreateEvent(nil,True,False,'MonEvent');//On ouvre un événement...
//...et mise en attente de l'événement ds un Thread.
if Event<>0 then CreateThread(nil,1,@RendreVisible,pointer(Handle),0,id);
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if HandleMutex <> 0 then ReleaseMutex(HandleMutex);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(Event);
if HandleThread <> 0 then CloseHandle(HandleThread);
end;
END.
Pour des explications plus détaillées, il vaudra mieux demander à rt15, car je n'ai pas la lumière à tous les étages non plus et j'ai fait ça à l'intuition... ;)
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 14 déc. 2007 à 14:53
Tu es trop modeste Cari, l'idée, les idées même étaient de toi, et on a
fait pas exactement le même code, mais on a fait globalement le même
algo.
Mais il reste le problème de mettre la première instance au premier plan...
La première instance lance un thread qui va attendre la création d'une
nouvelle instance via un évènement, et la deuxième (Ou xième pour mon
code) qui regarde si le mutex est possèdé/existe.
Form1.Memo1.Lines.Add('Une 2ème instance a été lancée puis détruite');
Faut peut être bien un Synchronize ici. cf l'aide de Delphi.
<hr size="2" width="100%" />3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 16 déc. 2007 à 20:11
@rt15
Je ne pense pas qu'un Synchronize soit nécessaire ici car, en principe, on n'exécutera jamais des appels de méthode concurrents dans le thread principal.
J'ai testé comme ça :
procedure RendreVisible(HWnd:THandle);
begin
//attend le déclenchement de l'événement...
WaitForSingleObject(Event,INFINITE);
//...et indique à l'application ce qu'elle doit faire:
Form1.Memo1.Lines.Add('Une 2ème instance a été lancée puis détruite');
//Ton code qui rend la 1ère visible...
Form1.Visible := true;
Application.ShowMainForm := true;
end;
procedure TForm1.FormCreate(Sender: TObject);
var id : Cardinal;
begin
if ExecuteDeja then begin //Si c'est une 2ème instance.
Event := CreateEvent(nil,True,False,'MonEvent');//On ouvre un événement...
PulseEvent(Event);//déclenche l'événement et le désarme aussotôt.
Halt; end //et on massacre cette instance.
else begin //Si 1ère instance.
Form1.Visible := false;
Application.ShowMainForm := false;
Memo1.Lines.Add('ceci est la 1ère instance');
Event := CreateEvent(nil,True,False,'MonEvent');//On ouvre un événement...
//...et mise en attente de l'événement ds un Thread.
if Event<>0 then CreateThread(nil,1,@RendreVisible,pointer(Handle),0,id);
end;
end;
Ca marche, mais je ne suis pas très sûr de moi.
Qu'en penses-tu?