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 :

Connaître le chemin du dossier qui sera ouvert par le composant TOpenDialog


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre habitué
    Homme Profil pro
    Chef de projets
    Inscrit en
    Août 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 127
    Points : 195
    Points
    195
    Par défaut Connaître le chemin du dossier qui sera ouvert par le composant TOpenDialog
    Bonjour,

    J'utilise le composant "TOpenDialog" pour aller chercher des fichiers. Mon appli est installée sur de nombreux PC's et serveurs. Et de temps en temps cette instruction fige et ne redonne pas la main à l'utilisateur (attente > 10 minutes avant kill).
    Je pense que cela est dû à un chemin qui n'existe plus dans le système, puisque si on ne renseigne pas le "InitialDir" Windows détermine le dernier dossier auquel il a donné accès.

    Ma question est la suivante, auriez-vous une commande pour obtenir la chemin que Windows va mettre dans le "InitialDir" du TOpenDialog ? Ceci de me permettrait de tester l'existence du dossier avant.

    Ps : je ne souhaite pas gérer le "initialdir" à la main.

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par joc02 Voir le message
    Je pense que cela est dû à un chemin qui n'existe plus dans le système, puisque si on ne renseigne pas le "InitialDir" Windows détermine le dernier dossier auquel il a donné accès.
    Intéressant. Si quelqu'un pouvait confirmer et expliquer exactement comment cela fonctionne, je serais curieux de le savoir. Où est-il conservé, ce chemin du dernier dossier ouvert ?

    Par contre j'ai du mal à croire que ce soit la cause du plantage de l'application.

    P.-S. Je viens de faire le test de supprimer le dernier dossier ouvert et de relancer le dialogue d'ouverture de fichier : c'est le dossier "documents" qui s'ouvre.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  3. #3
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Dans le cas où le dernier dossier est un dossier partagé qui n'est plus accessible, il y a ce problème.
    Mais c'est un fonctionnement dû à Windows. Pour savoir si le dossier existe, il essaie d'abord de joindre la machine hébergeant le dossier, il rend la main une fois qu'il a un time-out.
    Je pense que le seul moyen est de préciser InitialDir.

    Le dernier dossier ouvert, je ne sais pas où il est sauvegardé.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  4. #4
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    J'ai consulté le lien proposé par Papy214 et essayé de comprendre un peu les choses. Quelle est la règle à suivre pour convertir en texte les données de ce genre ?

    Windows Registry Editor Version 5.00

    [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU]
    "MRUListEx"=hex:02,00,00,00,0d,00,00,00,0c,00,00,00,0b,00,00,00,08,00,00,00,07,\
    00,00,00,00,00,00,00,04,00,00,00,0a,00,00,00,09,00,00,00,03,00,00,00,06,00,\
    00,00,05,00,00,00,01,00,00,00,ff,ff,ff,ff
    "1"=hex:76,00,62,00,73,00,65,00,64,00,69,00,74,00,2e,00,65,00,78,00,65,00,00,\
    00,14,00,1f,50,e0,4f,d0,20,ea,3a,69,10,a2,d8,08,00,2b,30,30,9d,19,00,2f,45,\
    3a,5c,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  6. #6
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    Pardon de poster un code un peu m***, mais c'est pour essayer de comprendre.

    La chaîne de départ a été obtenue au moyen de la commande suivante :

    Code BATCH : Sélectionner tout - Visualiser dans une fenêtre à part
    reg query HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU

    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
    program HexToText;
     
    {$APPTYPE CONSOLE}
     
    uses
      SysUtils, Windows;
     
    const
      SAMPLE = '76006200730065006400690074002E00650078006500000014001F50E04FD020EA3A6910A2D808002B30309D19002F453A5C000000000000000000000000000000000000000000';
     
    var
      i: integer;
      b: byte;
      s: string;
     
    begin
      s := '';
      for i := 1 to Length(SAMPLE) div 2 do
      begin
        b := StrToInt('$' + Copy(SAMPLE, 2 * i - 1, 2));
        if b <> 0 then
          s := s + Chr(b);
      end;
      MessageBox(0, pansichar(s), '', 0);
    end.
    J'obtiens une chaîne en partie lisible, contenant le nom d'une application ("vbsedit.exe"), un chemin ("E:\") et entre les deux des hiéroglyphes.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  7. #7
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    en fait, pour récupérer le contenu, il faut passer par un truc du style :

    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
     
    var
      reg: TRegistry;
      S: string;
      InputBuffer: TBytes;
      D: TRegDataInfo;
    begin
      reg := TRegistry.Create;
      reg.RootKey := HKEY_CURRENT_USER;
      if reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\txt', False) then
      begin
     
        reg.GetDataInfo('0', D);
        SetLength(InputBuffer, D.DataSize);
     
        reg.ReadBinaryData('0', pointer(InputBuffer)^, D.DataSize);
     
        // Décrypter selon le format
     
        reg.CloseKey;
      end;
      Reg.Free;
    Après, le problème est décrypter le contenu selon le format interne. Et là, j'avoue ne rien avoir trouvé de vraiment correct.

    Mais ça pourra peut-être t'aider quand même ....


    Complément: les clés n'existent pas forcément. Il faut tester l'existence avant lecture

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    @Papy214

    Merci pour ton code, testé avec succès (XE2).

    Autrement, la discussion n'intéresse plus personne ? Comment est-ce qu'il fait, Windows, pour déchiffrer ces fameuses données binaires ? Ou alors n'y a-t-il pas moyen de le savoir ?

    J'ai joué un peu avec la fonction de nettoyage de registre du logiciel CCleaner. J'ai observé qu'il était capable de détecter correctement les lignes faisant référence à des applications désinstallées (dans mon cas vbsedit.exe, voir ci-dessus). On peut en déduire qu'il sait déchiffrer les données. Ou alors est-ce qu'il se contente d'ignorer les parties illisibles ? Qui servent à quoi d'ailleurs ?
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  9. #9
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999

  10. #10
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    930
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 930
    Points : 1 959
    Points
    1 959
    Par défaut
    Oui, c'est surement possible et la réponse pour delphi est donnée par Remy Lebeau sur ce lien

    J'ai pas testé mais il explique la structure de longueur variable pour la clé OpenSavePidlMRU et l'utilisation de la fonction SHGetPathFromIDList pour en extraire les données.

    En espérant que cela puisse aider...

  11. #11
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    @free07

    Merci pour le lien. Une fois corrigées deux ou trois petites fautes de frappe dans le code en question, il fonctionne. On progresse !

    J'ai trouvé un autre exemple (que j'ai également testé) d'emploi de la fonction SHGetPathFromIDList() :

    Obtenir le chemin des dossiers spéciaux (bureau, favoris, etc.)

    Je ne me souviens plus si l'équivalent de ce code est déjà dans la FAQ. Dans le cas contraire, il mériterait d'y être ajouté.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  12. #12
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Si tu arrives au bout, j'espère que tu nous en fera tous profiter

  13. #13
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 457
    Points
    15 457
    Billets dans le blog
    9
    Par défaut
    @Papy214

    En ce qui me concerne, je crois que sur ce point j'aurais plutôt tendance à pécher par excès que par défaut, je veux dire à partager des choses qui ne mériteraient pas de l'être. Je crois que le code que j'ai posté plus haut en est un bon exemple.

    Mais revenons au sujet : j'ai essayé le code de Remy Lebeau, qui fonctionne parfaitement, mais lorsque je l'essaie avec la clé qui m'intéresse, ça ne donne plus rien, sans que je sache pourquoi.

    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
    program pbinarydata;
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    uses
      SysUtils, Windows, Registry, ShlObj, ComObj, ActiveX;
     
    (* http://codeverge.com/embarcadero.delphi.win32/a-little-help-with-registry-readbina/1052124 *)
     
    var
      reg: TRegistry;
     
    function ReadBinary(const AName: string; var VBuf: TBytes): Integer;
    begin
      SetLength(VBuf, 0);
      Result := reg.GetDataSize(AName);
      if Result > 0 then
      begin
        SetLength(VBuf, Result);
        Result := reg.ReadBinaryData(AName, VBuf[0], Result);
        SetLength(VBuf, Result);
      end;
    end;
     
    var
      i, j: Integer;
      MruListBuf, PidlBuf: TBytes;
      CurrentMru: PInteger;
      Pidl: PItemIDList;
      FileName: array[0..MAX_PATH] of char;
     
    const
      //KEY = '\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\*';
      KEY = '\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU'; // <-- Ne donne rien
     
    begin
      reg := TRegistry.Create;
     
      reg.RootKey := HKEY_CURRENT_USER;
      if reg.OpenKeyReadOnly(KEY) then
      begin
        if ReadBinary('MRUListEx', MruListBuf) >= SizeOf(Integer) then
        begin
          CurrentMru := PInteger(@MruListBuf[0]);
          for i := 0 to (Length(MruListBuf) div SizeOf(Integer)) - 1 do
          begin
            j := CurrentMru^;
            Inc(CurrentMru);
            if j >= 0 then
            begin
              if ReadBinary(IntToStr(j), PidlBuf) > 0 then
              begin
                Pidl := PItemIDList(@PidlBuf[0]);
                if SHGetPathFromIDList(Pidl, FileName) then
                begin
                  WriteLn(FileName);
                end;
              end;
            end;
          end;
        end;
      end;
     
      ReadLn;
    end.
    Voilà où j'en suis, et où je pense en rester, vu que je ne me suis intéressé à ce problème que par pure curiosité.

    Une dernière observation quand même : j'ai remarqué qu'il est possible de supprimer la clé ComDlg32 (c'est ce que fait CCleaner). Elle est automatiquement recréée dès qu'on ouvre un fichier avec une application quelconque.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  14. #14
    Membre habitué
    Homme Profil pro
    Chef de projets
    Inscrit en
    Août 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 127
    Points : 195
    Points
    195
    Par défaut
    Juste une petite parenthèse sur le poste de départ, qui m'a conduit à chercher le dernier chemin utilisé.
    Mon souci d'origine est que Windows fige lorsque je fais appel à un OpenDialog et ce, sur des Serveur en bureau à distance.
    Après quelques recherches, plus coté Windows, je me suis aperçu que si je m'étais mon application dans le DEP ( Data Execution Prevention - Prévention d'exécution des données), le OpenDialog fonctionnait de nouveau.

    Je pense qu'une mise à jour de Windows à renforcer la sécurité des serveurs et engendrer le souci.

  15. #15
    Membre habitué
    Homme Profil pro
    Chef de projets
    Inscrit en
    Août 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 127
    Points : 195
    Points
    195
    Par défaut
    J'ai enfin trouvé une solution à mon problème de base qui était le plantage "sans erreur" (application figée) lorsque l'on appelait un TOpenDialog.

    En fait le problème venait de la fonction DEP (Data Execution Prevention => Prévention d'exécution des données) qui verrouillait l'appel.
    En ajoutant mon programme dans la liste d’exception, je n'ai plus de souci avec l'appel à un TOpenDialog.

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

Discussions similaires

  1. probleme pour recuperer le chemin du dossier courant
    Par HoB dans le forum API standards et tierces
    Réponses: 8
    Dernier message: 11/08/2007, 11h22
  2. recuperer le chemin du dossier selectionné ds un JFileChoose
    Par dimitrimm972 dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 08/04/2006, 15h57
  3. Le dossier qui stock les mots de passe
    Par cartonis dans le forum Sécurité
    Réponses: 21
    Dernier message: 17/08/2005, 12h49
  4. Qui sera le client ? Serveur ?
    Par nesquik dans le forum Web & réseau
    Réponses: 8
    Dernier message: 07/07/2005, 13h33
  5. Réponses: 2
    Dernier message: 05/06/2004, 11h56

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