RunOne

L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013 - 10 déc. 2007 à 13:47
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Derniè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)

Merci à vous ! ^^

21 réponses

Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
10 déc. 2007 à 18:12
tu peux aussi aller voir ce composant de michel bardou: UnPas2
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
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.
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
11 déc. 2007 à 08:40
Merci bien à vous trois ! J'vais voir un p'tit peu les trois solutions, j'vous tiens au courant !

Bien à vous, bonne journée !
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Derniè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  ...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
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

voila, c'est tout !!!
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
11 déc. 2007 à 10:38
D'acc merci Guillemouze, je test ca de suite !
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
11 déc. 2007 à 11:29
   J'ai turbo delphi et je ne peux pas ajouter ni installer de composants :s
0
Guillemouze Messages postés 991 Date d'inscription samedi 25 octobre 2003 Statut Membre Dernière intervention 29 août 2013 6
11 déc. 2007 à 12:22
c domage, c'est super pratique les compos!!!

tu peux quand meme feinter, sur le oncreate de ta form :

type
    TForm1 = class(TForm)
    private
       UnPas2: TUnPas2;
       procedure UnPas2OtherTryToRun(StopSiDejaLance: Boolean; ParamCount: Integer; ParamArray: TParamArray; StringUser: ShortString);
    end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    UnPas2 := TUnPas2.Create(self);
    UnPas2.StopSiDejaLance := true;
    UnPas2.OnOtherTryToRun := UnPas21OtherTryToRun;
end;

procedure TForm1UnPas2OtherTryToRun(StopSiDejaLance: Boolean;
ParamCount: Integer; ParamArray: TParamArray; StringUser: ShortString);
begin
    //Ton code ici
end;

mais vu que tu peux pas mettre de compo, je te conseille quand meme d'utiliser la methode de cari
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Derniè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...

   En tous cas, merci pour ton aide  !
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
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...
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
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é.

C'est peut-être une piste...
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
11 déc. 2007 à 17:01
   Merci Caribensila, je vais regardé cela de plus prés, moi j'ai trouvé ca :

http://www.developpez.com/delphi/faq/?page=interexecution#1plan

   C'est exactement ce que je désire faire, j'ai fais des tests mais je n'arrive pô à le faire tourner... Je continuerai à en faire ...

   Merci encore !
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
12 déc. 2007 à 08:34
(Aujourd'hui c'est mon anniversaire )
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Derniè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 ....
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
12 déc. 2007 à 12:26
Salut,


Joyeux anniv à toi L_art_mem !


Heu, bah tu peux faire un truc tout bête ?

Genre (Non testé) :


program Project1;

uses

  Forms,

  windows,

  ...,

  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}


var

  hWnd: Integer;

begin

  Application.Initialize;

  hWnd = FindWindow(nil, "Titre de la fenêtre");

  if hWnd <> 0 then*

  begin

    ShowWindow(hWnd, WS_SHOW);

    Application.Terminate;

  end;

  Application.CreateForm(TForm1, Form1) ;

  Application.Run;

end.
<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
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
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;

initialization
lpOneInstance:= TOneInstance.Create();
finalization
lpOneInstance.Free();
end.

<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
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Derniè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 )

   Bien à vous !
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
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... ;)
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
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
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
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?
0
Rejoignez-nous