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

API, COM et SDKs Delphi Discussion :

Comment connaître la mémoire utilisée par un processus ?


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 76
    Points : 53
    Points
    53
    Par défaut Comment connaître la mémoire utilisée par un processus ?
    Bonjour à tous,

    je dois pouvoir surveiller et fermer un processus qui à la fâcheuse manie de planter de temps à autre et de commencer à phagocyter toute la ram et forcer le système à travailler avec le disque dur.

    Pour cela je pense utiliser un TMemoryStatus ( code ) qui me permet de calculer la charge dédiée de mémoire.

    En la soustrayant à la qté de mémoire physique j'obtiens un "reste"
    ResteMem:=((Mem.dwTotalPhys-(Mem.dwTotalPageFile-Mem.dwAvailPageFile)) /1024/1024);
    Lorsque ResteMem tend vers zéro je sais qu'il est temps de réagir !

    Cette méthode va certainement fonctionner mais elle ne surveille pas vraiment le processus incriminé.
    Il risque même d'être fermé si une autre appli devient trop gourmande.

    Ma question est donc : comment connaitre la mémoire utilisée par une application précise ?

    Merci pour votre aide.

  2. #2
    Membre habitué
    Inscrit en
    Août 2002
    Messages
    144
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations forums :
    Inscription : Août 2002
    Messages : 144
    Points : 157
    Points
    157
    Par défaut
    Tu peux utiliser MemProof en le téléchargent ici : memproof

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 76
    Points : 53
    Points
    53
    Par défaut
    merci, mais en fait ce que je cherche c'est le code à utiliser dans mon appli à moi pour surveiller le processus.
    Un peu comme avec les handle pour récupérer le titre d'une appli.
    Dans le gestionnaires des taches il y a bien la liste des processus avec en face la memoire qu'ils utilisent.
    Je pense donc qu'il existe une fct api... mais mes recherches restent infructueuses

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Salut,

    Cette méthode va certainement fonctionner mais elle ne surveille pas vraiment le processus incriminé.
    ... moi je me contente de :
    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 memDispo : DWORD; // mem vive libre disponible en Octets
      var      Mem : TMemoryStatus;
      begin    Mem.dwLength:=SizeOf(TMemoryStatus); 
               GlobalMemoryStatus(Mem);
               memDispo:=Mem.dwAvailPhys;
               // Pour + de détails voir MemoryStatus dans SDK-Windows
      end;
     
      function fGoMoKo(const mem : DWord) : string; // pour affichage éventuel avec conversion
      var      e : byte; s : string; r : Extended;
      begin    e:=0; r:=mem;
               if r>=0 then
               begin while r>1024 do begin r:=r/1024; inc(e); end;
                     case e of
                        0 : s:='Oct';
                        1 : s:='Ko';
                        2 : s:='Mo';
                        3 : s:='Go';
                        4 : s:='To';
                     end;
                     fGoMoKo:=FormatFloat('#.###',r)+' '+s;
               end;
      end; // fGoMoKo
    ... et je fais appel à la fonction memDispo dans les parties du processus de mon code où je sais que je vais avoir besoin d'une alloc de mémoire.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    tu peux ajouter dans ton programme, la fonction GetHeapStatus (System.pas) qui renvoie l'état de la mémoire du programme (fourni par le gestionnaire mémoire de delphi et non windows)

    tu peux ajouter ensuite un système d'échange de message (SendMessage +WM_SENDDATA par exemple) pour récupérer les données depuis un autre programme ou sinon un log régulier
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 76
    Points : 53
    Points
    53
    Par défaut
    pour ShaiLeTroll :
    de ce que je peux comprendre de GetHeapStatus , cela sert à un programme à connaitre ses propres utilisations en mémoire. Par expl mon prog de surveillance pourrait savoir combien il en consomme lui-même.
    Et pour savoir combien en consomme le prog "cible" ce dernier devrait s'auto-évaluer et renvoyer à mon prog de surveillance l'info via SendMessage.
    C'est bien ça ? Si tel est le cas cela ne résout pas mon problème étant donné que le programme "cible" est un programme tiers.

    Pour Gilbert Geyer:
    ... moi je me contente de :
    Code :

    function memDispo : DWORD; // mem vive libre disponible en Octets
    var Mem : TMemoryStatus;
    begin Mem.dwLength:=SizeOf(TMemoryStatus);
    GlobalMemoryStatus(Mem);
    memDispo:=Mem.dwAvailPhys;
    // Pour + de détails voir MemoryStatus dans SDK-Windows
    end;
    Malheureusement c'est ce que pensais utiliser au début, mais en faisant des essais je me suis aperçu que la mémoire physique libre (dwAvailPhys) ne baissait pratiquement pas alors que la charge dédiée, elle depassait deja ma qté de mémoire physique.
    Par expl, j'ai un Go de Ram, quand ça plant bien, je passe en charge dédiée à plus de 1Go et la mémoire physique disponible est encore de 200Mo...
    Donc pour le coup, j'en reste à ma petite formule, qui, je l'espère m'évitera le quasi-blocage du pc quand le dd travaille à la place de la mémoire.
    J'avais lu que la gestion de la mémoire n'était pas quelque chose de simple.
    Je commence à comprendre...

  7. #7
    Membre éclairé Avatar de rt15
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2005
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 262
    Points : 665
    Points
    665
    Par défaut
    Salut,

    Si tu as pas le source du processus qui te pose problème, voici quelques pistes.

    1 Injecter ton propre code dans le processus.
    Dans l'initialisation de la dll, a la place de modifier la table d'import, tu peux récupérer la mémoire consommer et l'envoyer avec SendMessage (Ou PostMessage) comme te l'a suggérer ShaiLeTroll.

    2 Utiliser des fonctions non documentées. NtQueryProcessInformation pour récupérer la PEB, puis... Nah je sais pas. La PEB propose un pointeur sur le tas, un pointeur sur les tas... La taille est peut être pas loin. Mais bon, les fonctions non documentées sont à éviter.

    3 Utiliser VirtualQueryEx. La méthode la plus simple que j'ai trouvée... si elle marche. Pour l'utiliser, il te faut simplement un handle sur le processus que tu auras facilement (Classique : CreateToolHelp32Snapshot, puis OpenProcess. Attention à bien choisir les droits dans le OpenProcess.) Il faut ensuite que tu précise les pages sur lesquels tu veux des infos... C'est là que ça se corse. Tu peux jeter un oeil à cette exemple en C++. Il avance dans les pages à partir de 0 jusqu'à ce qu'il tombe sur une adresse du noyau. Je sais pas si c'est Ok...

    C'est "marrant" que ce soit si dûr quand même. Y a peut être une méthode plus facile.

  8. #8
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Yep !

    Cherche donc plutôt de ce côté :
    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
    //==============================================================================
    //=== Détermine la quantité de mémoire utilisée par le process ProcessID.
    //=== Uses psapi
    //==============================================================================
    Function ProcessMemoryUsage(ProcessID: DWORD): DWORD;
    Var
      ProcessHandle: THandle;
      MemCounters: TProcessMemoryCounters;
    Begin
      Result := 0;
      ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION Or
        PROCESS_VM_READ, False, ProcessID);
      Try
        If GetProcessMemoryInfo(ProcessHandle, @MemCounters,
          sizeof(MemCounters)) Then
          Result := MemCounters.WorkingSetSize;
      Finally
        CloseHandle(ProcessHandle);
      End;
    End;
    Mes 2 cts,
    --
    jp
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 76
    Points : 53
    Points
    53
    Par défaut
    Merci Jipété pour ta solution !

    Je l'ai mise en œuvre dans le code suivant (un bouton et deux labels)
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    var
      Form1: TForm1;
      lp:integer;
      Function ProcessMemoryUsage(ProcessID: DWORD): DWORD;
      function HandleSelonTitre(TitleText: String): hWnd;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var Memoire:DWord;
      AppliHdl:THandle;
      pPId:DWord;
     
    begin
      AppliHdl:=HandleSelonTitre('Calculatrice');
      GetWindowThreadProcessId(AppliHdl,pPid);
      Memoire:=round(ProcessMemoryUsage(pPid)/1024);
      Label1.Caption:='Handle : '+ inttostr(AppliHdl);
      Label2.Caption:='Memore : ' + inttostr(Memoire)+' Ko';
    end;
     
    Function ProcessMemoryUsage(ProcessID: DWORD): DWORD;
    Var
      ProcessHandle: THandle;
      MemCounters: TProcessMemoryCounters;
    Begin
      Result := 0;
      ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION Or
        PROCESS_VM_READ, False, ProcessID);
      Try
        If GetProcessMemoryInfo(ProcessHandle, @MemCounters,
          sizeof(MemCounters)) Then
          Result := MemCounters.WorkingSetSize;
      Finally
        CloseHandle(ProcessHandle);
      End;
    End;
     
    function HandleSelonTitre(TitleText: String): hWnd;
    {renvoie le handle de la fenêtre contenant dans son titre le texte en param}
    var
      ch : HWND;
      StrBuf: Array[0..$FF] of Char;
    begin
      TitleText:=AnsiUpperCase(TitleText);
      result:=0;
      ch := GetDesktopWindow;
      ch := GetTopWindow(ch);
      while ch <> 0 do
      begin
        if GetWindowText(ch, StrBuf, 255) <> 0 then
          if pos(TitleText,AnsiUpperCase(StrBuf))>0 then begin
            result:=ch;
            exit;
          end;
        ch := GetNextWindow(ch, GW_HWNDNEXT);
      end;
    end;
     
    end.
    Comme tu peux le constater pour entrer le ProcessId en paramètre dans ta fonction j'ai d'abord du trouver le handle en fct du titre de l'application.
    Dans mon expl je cherche 'Calculatrice' et non calc.exe comme on le voit dans le gestionnaire des taches.
    Ma question reste donc à moitié en suspens, à savoir comment parvenir au même résultat mais avec le nom du process (si le titre la fenetre change, le code ci-dessus ne marche plus)

    Je cherche depuis ce matin sans succès. J'ai exploré la piste suivante
    mais je n'en ai rien tiré de plus que le titre de la fenêtre

    ici aussi je pensais y arriver car l'exemple donné avec notepad, alors que "notepad" ne figure pas dans le titre, marche bien avec FindWindow.
    Si je fais l'essai avec calc ou calc.exe, pas de résultat.

    Je ne voudrais pas avoir l'air de chipoter mais je trouve qu'entre le nom de l'exe et son titre dans la fenêtre, y'a quand même une différence..

    Merci encore à tous.
    ps: je laisse encore un peu en non-résolu au cas ou...

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    158
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 158
    Points : 158
    Points
    158
    Par défaut
    Bonjour,

    Je ne sais pas où j'ai récupéré ce code , mais tu peux essayer cela

    place un autre bouton sur ta fiche

    rajoute à tes uses tlHelp32

    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
     
    procedure TForm1.Button2Click(Sender: TObject);
    var h: Integer;
      me32: TProcessEntry32;
    begin
      // Effacement de la liste
     
      // Création d'un image de la liste actuelle des process
      h := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      me32.dwSize := sizeof(me32);
     
      try
        // Ouverture de la liste des process créée précédemment
        if Process32First(h, me32) then
          repeat
            if me32.szExeFile = 'calc.exe' then
            begin
              Label2.Caption := IntToStr(ProcessMemoryUsage(me32.th32ProcessID));
            end;
     
        // Il faut boucler sur toute la liste
          until not Process32Next(h, me32);
      finally
        // Et libérer la liste
        CloseHandle(h);
      end;
    end;
    A+
    Pitango
    -------------------------------------------------
    [Delphi7.1 Entreprise][MYSQL 5.0.27][SQL SERVER 7][W2000/NT4]

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 76
    Points : 53
    Points
    53
    Par défaut
    Que dire de plus que c'est exactement ça !
    Merci infiniment à toi et à tous les autres qui m'avez grandement aidé

    ps: tout ceci mériterait une petite place dans la FAQ , non ?

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    GetProcessMemoryInfo, je ne l'ai pas dans l'aide du SDK mais on le trouve dans Delphi7 (PsAPI.pas), c'est bon à savoir, ... merci de l'info Jipété
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. Comment connaître les technologies utilisées par un site?
    Par estmars dans le forum Général Conception Web
    Réponses: 4
    Dernier message: 22/07/2011, 16h43
  2. Réponses: 5
    Dernier message: 02/11/2010, 08h56
  3. [Batch] Connaitre mémoire utilisée par un processus
    Par Maglight dans le forum Scripts/Batch
    Réponses: 0
    Dernier message: 05/10/2010, 07h39
  4. Réponses: 2
    Dernier message: 01/10/2009, 11h00
  5. la mémoire utilisée par un processus
    Par LN(a) dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 22/04/2006, 14h28

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