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

  1. #1
    Membre émérite
    [D7] Base de registre - Windows 10 - 64 bits
    Bonjour,

    j'ai un petit soucis avec la base de registre :

    Selon la FAQ, j'essaye de lister tous les programmes installés.

    Je fais donc ceci :

    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
    { ============================================================================== }
    procedure TF_Princ.Btn_LogicielsClick(Sender: TObject);
    const
      REGKEYAPPS = '\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
    var
      reg    : TRegistry;
      List1  : TStringList;
      List2  : TStringList;
      i, n   : integer;
      j : Integer ;
     
    begin
      reg    := TRegistry.Create;
      List1  := TStringList.Create;
      List2  := TStringList.Create;
      ListBox1.Clear ;
      {Charge toutes les sous-clés}
      with reg do
      begin
        RootKey := HKEY_LOCAL_MACHINE;
        OpenKey(REGKEYAPPS, false);
        GetKeyNames(List1);
      end;
      ShowMessage('Nombre de sous-clefs : '+ IntToStr(List1.Count)) ;
      ...


    Cela me renvoie 366 sous-clefs, alors qu'avec Regedit, je n'en affiche que 60 ?

    Comment expliquer cette bizarrerie ?

    Merci

    A+
    Charly

  2. #2
    Membre expérimenté
    as-tu tenté de les afficher pour voir ce qu'il y a dans ton résultat ?

  3. #3
    Rédacteur/Modérateur

    Citation Envoyé par Charly910 Voir le message
    Comment expliquer cette bizarrerie ?
    Par Regedit, ce chemin mène aux apps 64 bits alors que ton app D7 énumère les 32 bits.

    Pour lister tous les programmes installés, tu vas devoir énumérer ces deux clés en redirigeant une fois la lecture sur la clé 64 bits :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    reg := TRegistry.Create(KEY_READ);                     // apps 32 bits
    reg := TRegistry.Create(KEY_READ or KEY_WOW64_64KEY);  // apps 64 bits (KEY_WOW64_64KEY = $0100<img src="images/smilies/icon_wink.gif" border="0" alt="" title=";)" class="inlineimg" />

  4. #4
    Membre habitué
    Bonjour

    en fonction de la compilation 32 ou 64 bits
    lors de la lecture de la BDD sur HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall on va taper soit dans
    HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall en 32Bits
    soit dans
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall en 64Bits
    d’où la différence du nombres de clé remonté

  5. #5
    Membre émérite
    Merci,
    je me doutait bien que c'était une histoire de 32 et 64 bits.

    avec

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const
      REGKEYAPPS = '\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
    ...
    reg := TRegistry.Create(KEY_READ or KEY_WOW64_64KEY);
      with reg do
      begin
        RootKey := HKEY_LOCAL_MACHINE;
        OpenKey(REGKEYAPPS, false);
        GetKeyNames(List1);
      end;


    j'obtiens 60 sous-clefs ce qui parait normal par rapport à Regedit

    avec :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
       reg := TRegistry.Create(KEY_READ);


    j'obtiens 366 sous-clefs, ce qui correspond à \SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall

    Mais même avec lze premier code, je ne retrouve pas les DisplayNames de la clef \SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

    A+
    Charly

  6. ###raw>post.musername###
    Rédacteur/Modérateur
    Il ne faut pas utiliser OpenKeyReadOnly sous D7 si tu veux accéder à la clé 64 bits. Cette méthode force le flag KEY_READ uniquement, KEY_WOW64_64KEY est perdu (à noter que ce flag est préservé sur les Delphi récents). N'utilise que OpenKey.

    Lit également directement DisplayName par ReadString, énumérer les valeurs n'a aucun intérêt ici.

    Et le dernier point ; si on ouvre plusieurs clés à la suite, OpenKey doit toujours être suivi d'un CloseKey sous peine de handle leak.

    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
    const
      REGKEYAPPS = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
    var
      KeyList :TStringList;
      s       :string;
      i       :integer;
     
    begin
      with TRegistry.Create(KEY_READ or KEY_WOW64_64KEY) do
      try
        RootKey := HKEY_LOCAL_MACHINE;
     
        if OpenKey(REGKEYAPPS, FALSE) then
        begin
          KeyList := TStringList.Create;
     
          try
            GetKeyNames(KeyList);
            CloseKey;
     
            for i := 0 to KeyList.Count -1 do
              if OpenKey(REGKEYAPPS +'\' +KeyList[i], FALSE) then
              begin
                s := ReadString('DisplayName');
     
                if s <> '' then
                  Memo1.Lines.Add(KeyList[i] +' -> ' +s);
     
                CloseKey;
              end;
     
          finally
            KeyList.Free;
          end;
        end;
     
      finally
        Free;
      end;
    end;
      0  0

  7. ###raw>post.musername###
    Membre émérite
    Merci Andnotor
    En attendant j'avais bricolé ceci qui me donne satisfaction :

    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
    procedure TF_Princ.Button4Click(Sender: TObject);
    const
      REGKEYAPPS = '\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
    //  REGKEYAPPS2 = '\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' ;
      KEY_WOW64_64KEY = $0100;
    var
      reg    : TRegistry;
      List1  : TStringList;
      List2  : TStringList;
      i, n   : integer;
    //  j   : Integer ;
    //  Value: TRegDataInfo ;
    begin
    //   reg := TRegistry.Create(KEY_READ);                     // apps 32 bits                           ==> 366 Apps
       reg := TRegistry.Create(KEY_READ or KEY_WOW64_64KEY);  // apps 64 bits (KEY_WOW64_64KEY = $0100<img src="images/smilies/icon_wink.gif" border="0" alt="" title=";)" class="inlineimg" />  ==> 60 Apps
      List1  := TStringList.Create;
      List2  := TStringList.Create;
      ListBox1.Clear ;
      {Charge toutes les sous-clés}
      Reg.RootKey := HKEY_LOCAL_MACHINE;
      Reg.OpenKey(REGKEYAPPS, false);
      Reg.GetKeyNames(List1);
     
      For i := 0 To List1.Count-1 Do
        Begin
          Reg.CloseKey ;
          Reg.OpenKey(REGKEYAPPS+ '\'+List1.Strings[i], false);
          List2.Clear ;
          Reg.GetValueNames(List2) ;     
     
          ListBox1.Items.add(IntToStr(i)+' - Clef : '+ List1.Strings[i]) ;
          n := List2.IndexOf('DisplayName');
          If (n >= 0)  Then
             ListBox1.Items.Add('    DisplayName : '+ reg.ReadString(List2.Strings[n]));
          n := List2.IndexOf('Publisher');
          If (n >= 0)  Then
             ListBox1.Items.Add('    Publisher   : '+ reg.ReadString(List2.Strings[n]));
          ListBox1.Items.add(' ') ;
          Reg.CloseKey ;
        End ;
      {Libération des ressources}
      List1.Free;
      List2.Free;
      reg.CloseKey;
      reg.Destroy;
    end;


    Avec ce code je retrouve le contenu de la clef Uninstall de Regedit (32 ou 64 bits ??)

    je vais tester ton code qui me parait plus simple et plus propre que le mien

    A+
    Charly
      0  0

  8. ###raw>post.musername###
    Membre émérite
    Finalement, voici la solution que j'ai adoptée (mix des 2 codes). J'ai ajouté un RadioButton pour passer du 32 au 64 bits. Le résultat s'affiche dans un TListBox :

    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    procedure TF_Princ.Button4Click(Sender: TObject);
    const
      REGKEYAPPS64 = '\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
      REGKEYAPPS32 = '\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' ;
      KEY_WOW64_64KEY = $0100;
    var
      Reg    : TRegistry;
      List1  : TStringList;
      List2  : TStringList;
      i, n   : integer;
      s      : String ;
      Valeur : String ;
      Clef   : String ;
      DateInst : TDateTime ;
    begin
      Reg := TRegistry.Create(KEY_READ or KEY_WOW64_64KEY);
      Try
        { Logiciels 64 ou 32 bits }
        If RD1.ItemIndex = 1 Then Clef := REGKEYAPPS64
                             Else Clef := REGKEYAPPS32 ;
     
        List1  := TStringList.Create;
        List2  := TStringList.Create;
     
        Try
          ListBox1.Clear ;
          {Chargement de toutes les sous-clés}
          Reg.RootKey := HKEY_LOCAL_MACHINE;
     
          If Reg.OpenKey(Clef, false) Then
            Begin
              Reg.GetKeyNames(List1);
     
             { Affichage des valeurs }
              For i := 0 To List1.Count-1 Do
                Begin
                  Reg.CloseKey ;
                  Reg.OpenKey(Clef+ '\'+List1.Strings[i], false);
                  List2.Clear ;
                  Reg.GetValueNames(List2) ;
     
                  ListBox1.Items.add(IntToStr(i)+' - Clef : '+ List1.Strings[i]) ;
     
                  Valeur := 'DisplayName' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
                  Valeur := 'DisplayVersion' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
                  Valeur := 'Publisher' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
                  Valeur := 'DisplayIcon' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
                  Valeur := 'InstallLocation' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
                  Valeur := 'InstallDate' ;
                  s := Reg.ReadString(Valeur);
                  if s <> '' then ListBox1.Items.Add('    '+Valeur+' : ' +s);
     
                  ListBox1.Items.add(' ') ;
                  Reg.CloseKey ;
                End ;
             End ;
        Finally
          {Libération des ressources}
          List1.Free;
          List2.Free;
        End ;
      Finally
        Reg.Free;
      End ;
    end;


    Sous réserve de vérification, ce code pourrait compléter celui de la FAQ (qui ne marchait pas bien chez moi)

    Merci à tous ceux qui m'ont aidé et particulièrement AndNotOr !

    A+
    Charly
      0  0

  9. ###raw>post.musername###
    Rédacteur/Modérateur
    Inutile de dire que ce code ne fonctionnerait pas sur un Windows 32 bits (pas de nœud WOW6432Node).

    Le chemin doit toujours être identique et la sélection se faire par KEY_WOW64_64KEY et KEY_WOW64_32KEY.

    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
    procedure ListInstalledApps(aList :TStrings; aApp64 :boolean);
    const
      KEY_WOW64_64KEY = $0100;
      KEY_WOW64_32KEY = $0200;
     
      REGKEYAPPS = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall';
      Flags      : array[boolean] of word = (KEY_WOW64_32KEY, KEY_WOW64_64KEY);
      Values     : array[0..5] of string = ('DisplayName', 'DisplayVersion', 'Publisher', 'DisplayIcon', 'InstallLocation', 'InstallDate');
     
    var
      List1  : TStringList;
      i, j   : integer;
      s      : String;
     
    begin
      with TRegistry.Create(KEY_READ or Flags[aApp64]) do
      try
        RootKey := HKEY_LOCAL_MACHINE;
     
        If OpenKey(REGKEYAPPS, false) Then
        Begin
          List1 := TStringList.Create;
     
          try
            GetKeyNames(List1);
            CloseKey;
     
            for i := 0 to List1.Count -1 do
              if OpenKey(REGKEYAPPS+ '\'+List1[i], false) then
              begin
                aList.add(IntToStr(i)+' - Clef : '+ List1[i]);
     
                for j := 0 to high(Values) do
                begin
                  s := ReadString(Values[j]);
                  if s <> '' then aList.Add('    '+Values[j]+' : ' +s);
                end;
     
                aList.add('');
                CloseKey;
              end;
     
          finally
            List1.Free;
          end;
        end;
     
      Finally
        Free;
      end ;
    end;
     
    procedure TF_Princ.Button4Click(Sender: TObject);
    begin
      ListBox1.Items.Clear;
     
      ListBox1.Items.Add('********** Applications 32 bits **********');
      ListInstalledApps(ListBox1.Items, FALSE);
     
      ListBox1.Items.Add('********** Applications 64 bits **********');
      ListInstalledApps(ListBox1.Items, TRUE);
    end;
      1  0

  10. #10
    Membre émérite
    Merci AndNotOr, c'est bien plus concis comme cela.

    Mon code fonctionnait bien sur mon poste. C'est le code de la FAQ qui ne me donnait pas satisfaction.

    Est ce que l'on peut mettre ton code dans la FAQ ?

    A+
    Charly

###raw>template_hook.ano_emploi###