IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Limiter le nombre d'instances de mon application sur la même machine


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Inscrit en
    Mai 2010
    Messages
    407
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 407
    Par défaut Limiter le nombre d'instances de mon application sur la même machine
    Bonsoir a tous,
    SVP , y a t il une astuce pour limité le nombre d'instance a exécuté sur la même machine ,
    par exemple interdire d'exécuté une instances de mon application plus de 5 fois.

    j'ai vue la faq , mais c'est limité a une seul fois seulement.
    cordialement.

  2. #2
    Membre éclairé

    Inscrit en
    Mai 2010
    Messages
    407
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 407
    Par défaut
    Bonsoir a tous,
    j'ai trouvé la solution .

    voici le source du Projet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    program Project1;
     
    uses
      Forms,
    Dialogs,Windows,TlHelp32,SysUtils,
      Unit1 in 'Unit1.pas' {Form1};
     
    function ProcessCount(const ExeName: String): Integer;
    var
      ContinueLoop: BOOL;
      FSnapshotHandle: THandle;
      FProcessEntry32: TProcessEntry32;
    begin
      FSnapshotHandle:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      FProcessEntry32.dwSize:= SizeOf(FProcessEntry32);
      ContinueLoop:= Process32First(FSnapshotHandle, FProcessEntry32);
      Result:= 0;
      while Integer(ContinueLoop) <> 0 do
      begin
        if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
          UpperCase(ExeName)) or (UpperCase(FProcessEntry32.szExeFile) =
          UpperCase(ExeName))) then
            Inc(Result);
        ContinueLoop:= Process32Next(FSnapshotHandle, FProcessEntry32);
      end;
      CloseHandle(FSnapshotHandle);
    end;
     
     
    {$R *.res}
     
    begin
        if ProcessCount(ExtractFileName(Application.ExeName)) > 2 then // je précise le nombre d'instances autorisés.
        begin
            MessageDlg('Application is already running!', mtError, [mbOK], 0);
            Application.Terminate;
        end
        else
        begin
            Application.Initialize;
            Application.CreateForm(TForm1, Form1);
            Application.Run;
        end;
    end.

    le lien de la solution
    https://www.tek-tips.com/faqs.cfm?fid=7523
    peut être ca va servir quelqu'un d'autre.
    cordialement.

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 941
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 941
    Par défaut
    Ce code n'est pas très beau !

    TH32CS_SNAPPROCESS retourne le nom de l'exécutable mais sans le chemin. Tous ces tests sont donc inutiles.

    Utilise plutôt SameText qui fait une comparaison de chaînes sans tenir compte de la casse.

    Une boucle First..Next s'écrit ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if First then
    repeat
    until not Next;
    Prend aussi l'habitude de protéger la libération d'un handle par un bloc try..finally.

    Ce qui donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function TForm1.InstanceCount: integer;
    var
      FileName :TFileName;
      Handle   :THandle;
      Process  :TProcessEntry32;
     
    begin
      Result         := 0;
      FileName       := ExtractFileName(Application.ExeName);
      Process.dwSize := SizeOf(TProcessEntry32);
      Handle         := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     
      try
        if Process32First(Handle, Process) then
        repeat
          if SameText(Process.szExeFile, FileName) then
            Inc(Result);
        until not Process32Next(Handle, Process);
     
      finally
        CloseHandle(Handle);
      end;
    end;
    Et dans le corps du programme, pourquoi appeler Application.Terminate puisqu'il n'y a pas d'Application.Run ?


    Mais à l'instar du mutex pour une seule instance, tu peux ici aussi utiliser un objet de synchronisation : TSemaphore.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    uses SyncObjs;
     
    var
      MaxInstance :TSemaphore;
     
    begin
      //5 instances max
      MaxInstance := TSemaphore.Create(nil, 5, 5, 'MyApp_MaxInstanceCount', FALSE);
     
      try
        //WaitFor décrémente le compteur du sémaphore.
        //Timeout s'il est déjà à 0 => Exit.
        if MaxInstance.WaitFor(1) <> wrTimeout then
        try
          Application.Initialize;
          Application.MainFormOnTaskbar := True;
          Application.CreateForm(TForm1, Form1);
          Application.Run;
     
        finally
          //Incrémente le compteur, nouvelle instance possible.
          //IMPORTANT ! Free ne lance pas de Release !
          MaxInstance.Release;
        end;
     
      finally
        MaxInstance.Free;
      end;
    end.

  4. #4
    Membre éclairé

    Inscrit en
    Mai 2010
    Messages
    407
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 407
    Par défaut
    Bonsoir,
    Merci beaucoup pour la réponse ,
    svp , je veux bien tester la solution des Semaphore ,
    mais j'obtient une erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    identificateur non déclaré TSemaphore
    .
    je suis sous delphi 7.
    amicalement.

  5. #5
    Membre Expert
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 704
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 704
    Par défaut
    Gestion des mutex (à améliorer):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var
    	H : THandle;
    	Erreur: Integer;
    begin
      SetLastError(NO_ERROR);
      H := CreateMutex(nil, False,'MONAPPLI');
      Erreur := GetLastError;
      if ( Erreur = ERROR_ALREADY_EXISTS ) or ( Erreur = ERROR_ACCESS_DENIED )
        then
        begin
        MessageDlg('MONAPPLI est déjà utilisé sur votre poste.'+#13+
        'Vous ne pouvez pas ouvrir 2 fois l''application.',mtInformation,[mbOK],0);
        CloseHandle(H);
        Exit;
      end;
     
    //...
     
    end;
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. :bug: ___ "http://club.developpez.com/regles/#LIII-A"Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.3 Entreprise - Visual studio 2022
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.7)

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 941
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 941
    Par défaut
    La classe TSemaphore est l'encapsulation Delphi des API Windows mais elle ne simplifie pas tellement les choses, tellement les appels directs semblent identiques
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    uses Windows;
     
    var
      MaxInstance :THandle;
     
    begin
      //5 instances max
      MaxInstance := CreateSemaphore(nil, 5, 5, 'MyApp_MaxInstanceCount');
     
      try
        //WaitForSingleObject décrémente le compteur du sémaphore.
        //Timeout s'il est déjà à 0 => Exit.
        if WaitForSingleObject(MaxInstance, 1) <> WAIT_TIMEOUT then
        try
          Application.Initialize;
          Application.MainFormOnTaskbar := True;
          Application.CreateForm(TForm1, Form1);
          Application.Run;
     
        finally
          //Incrémente le compteur, nouvelle instance possible.
          ReleaseSemaphore(MaxInstance, 1, nil);
        end;
     
      finally
        CloseHandle(MaxInstance);
      end;
     
    end.
    A noter que si le nombre limite est fixé à 1, le comportement est similaire à celui du mutex

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 22
    Dernier message: 26/09/2011, 16h14
  2. [Administration] Gérer plusieurs applications sur une même machine
    Par ego dans le forum Subversion
    Réponses: 0
    Dernier message: 19/06/2009, 08h27
  3. Réponses: 9
    Dernier message: 14/09/2006, 17h03
  4. installation de mon application sur un poste
    Par issam16 dans le forum Access
    Réponses: 6
    Dernier message: 08/08/2006, 17h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo