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 :

Utilisation d'une Dll dans une ressource avec D6 et Windows 10 64bits


Sujet :

Delphi

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut Utilisation d'une Dll dans une ressource avec D6 et Windows 10 64bits
    Bonjour à toutes et à tous,

    Dans mon application, la Dll est dans le même dossier et à l'ouverture de cette application elle est donc chargée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    const
      DirDll = 'DirOpenDlg.Dll';
     
     function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
     external DirDll name{$IFDEF UNICODE} 'DirOpenDialogW'{$ELSE} 'DirOpenDialogA'{$ENDIF};
    Si je veux communiquer cette application, je dois aussi communiquer la Dll.

    Avec InnoSetup pas de problème mais si j'utilise une ressource, l'extraire puis la sauver dans le dossier puis la charger, cela ne fonctionne pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    {$R Fichdll.res}
     
     const
      DirDll = 'DirOpenDlg.Dll';
     
     function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
     external DirDll name{$IFDEF UNICODE} 'DirOpenDialogW'{$ELSE} 'DirOpenDialogA'{$ENDIF};
    Et dans le Oncreate :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Stream := TResourceStream.Create(HInstance, 'Fd', RT_RCDATA);
    try
      Stream.SaveToFile(chappli +'DirOpenDlg.dll');
    finally
      Stream.Free;
    end;
    Cela ne fonctionne pas mais je sais pourquoi car la Dll n'est pas encore sauvée dans le dossier alors quelle est chargée à l'exécution de l'application.

    Ma question peus t'on mettre une temporisation entre la sauvegarde et l'appel de cette Dll ?

    Ou modifier

    external DirDll name{$IFDEF UNICODE} 'DirOpenDialogW'{$ELSE} 'DirOpenDialogA'{$ENDIF};
    En vous remerciant.

    @+,

    cincap

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    La liaison statique (fonctions déclarées dans ton code comme externes, liées dès l'ouverture de ton application en cherchant la librairie) ne peut s'appliquer dans ton cas.
    Il faut une liaison dynamique qui ne chargera les fonctions que lorsque tu le demanderas, donc après l'extraction de la librairie fournie en ressource. C'est un peu plus complexe à mettre en œuvre.
    Au lieu de définir les fonctions comme externes, tu dois définir des variables de type fonction de x paramètres retournant tel type, et dans un code déclenché au moment voulu (ici, après l'extraction de la ressource, par exemple), faire un Library_Handle := LoadLibrary( chappli + 'DirOpenDlg.dll' ) puis affecter l'adresse de la fonction à la variable grâce à un MyFunctionVar := GetProcAddress( Library_Handle, 'DirOpenDialogW').
    Ceci est du pseudocode ; tu trouveras les syntaxes exactes et plus de précisions dans la FAQ.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    je ne sais plus si Delphi 6 support le mot clé "delayed" qu'il suffit d'ajouter à déclaration de la fonction pour résoudre ton problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    const
      DirDll = 'DirOpenDlg.Dll';
     
     function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
     external DirDll name{$IFDEF UNICODE} 'DirOpenDialogW'{$ELSE} 'DirOpenDialogA'{$ENDIF}  {$IFDEF MSWINDOWS}delayed{$ENDIF};
    NB: cela ne fonctionne que sous Windows
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut
    Bonjour à toutes et à tous,

    @ Paul TOTH, merci de ta suggestion malheureusement D6 ne connait pas "{$IFDEF MSWINDOWS}delayed{$ENDIF}", je suis certain que c'était une bonne piste ayant lu tous tes articles.

    @ tourlourou, merci aussi de ta suggestion, cela devient trop hard pour moi mais je n'ai pas compris, dans un premier temps, la dll est dans le dossier et l'appel se fait correctement.

    J'inclus cette dll dans ma ressource, je l'efface de mon dossier et je l'extrait de ma ressource et je la sauve dans mon dossier, l'appel devrai être le même non.

    Sauf si l'appel se fait avant que la dll ne soit dans le dossier.

    Je pense a faire une 1ère fiche qui extrait puis sauve et lance la 2ième fiche ou le reste de code se trouve.

    Je vais tester et vous tiendrai au courant.

    @+,

    cincap

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 452
    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 452
    Points : 24 863
    Points
    24 863
    Par défaut
    Citation Envoyé par cincap Voir le message
    @ tourlourou, merci aussi de ta suggestion, cela devient trop hard pour moi mais je n'ai pas compris, dans un premier temps, la dll est dans le dossier et l'appel se fait correctement.
    Tu peux tout essayer, si ton programme requiert une DLL en lien statique, ça ne fonctionnera pas de dehors de faire un Exe de lancement qui extrait DLL et lance l'Exe principal (et non pas au niveau de la fiche)
    la seule approche est le lien dynamique qui est extrêmement simple

    Voici une façon pour encapsuler un appel et que cela reste transparent dans le reste du code

    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
      //--------------------------------------------------------------------------
      function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean;
      var
        DllHandle: THandle;
        _DirOpenDialog: function(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
      begin
        DllHandle := LoadLibrary('DirOpenDlg.dll');
        Result := DllHandle > 0;
        if Result then
        begin
          @_DirOpenDialog := GetProcAddress(DllHandle, 'DirOpenDialogA');
          Result := Assigned(@_DirOpenDialog);
          if Result then
            Result := _DirOpenDialog(aDir, aHandle);
     
          FreeLibrary(DllHandle);
        end;
      end;
    et ça remplace intégralement ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const
      DirDll = 'DirOpenDlg.Dll';
     
     function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
     external DirDll name{$IFDEF UNICODE} 'DirOpenDialogW'{$ELSE} 'DirOpenDialogA'{$ENDIF};



    Sinon "var aDir: PChar" c'est TRES étrange, ça revient à un Char** !
    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 expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut
    @ ShaiLeTroll, merci de ta suggestion, j'avais donc tester de coder une fiche extérieure qui extrait de la ressource puis sauve la Dll et ensuite qui execute l'application, cela fonctionne telquel mais quelle lourdeur de code à préférer InnoSetup.

    Ta fonction est superbe et très rapide, dès que la sauvegarde est correcte, je sais ouvrir la boite de dialogue pour choisir mes photos.

    Je peus fermer ce topic haut la main.

    En vous remerciant tous, j'ai presque fini de remanier certaines applications en essayant de les améliorer.

    @+,

    cincap

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut
    Oups, après test et en ouvrant le répertoire pour choisir mes photos j'obtiens une erreur.

    Il faut préciser que dans l'unité j'ai mis 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
    26
    27
    28
     
    program ConvertToPDF;
     
    uses
     Windows,
      Forms,
      UConvertMain in 'UConvertMain.pas' {Form5};
     
    {$R *.res}
    var
    	H : THandle;
    	Erreur: Integer;
     
    begin
      SetLastError(NO_ERROR);
      H := CreateMutex (nil, False, 'ConvertToPDF.exe');
      Erreur := GetLastError;
      if ( Erreur = ERROR_ALREADY_EXISTS ) or ( Erreur = ERROR_ACCESS_DENIED )
        then Exit;
     
      Application.Initialize;
     
      Application.CreateForm(TForm5, Form5);
     
      Application.Run;
     
      CloseHandle(H); //Erreur ici à l'ouverture du dossier
    end.
    Et j'ai donc deux Handles.

    @+,

    cincap

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 452
    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 452
    Points : 24 863
    Points
    24 863
    Par défaut
    Citation Envoyé par cincap Voir le message
    Et j'ai donc deux Handles.
    Euh oui ... et surement plus encapsulé par la VCL
    Quelle est le sens de cette remarque ?

    Peut-être vérifier H <> 0

    Citation Envoyé par cincap Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      CloseHandle(H); //Erreur ici à l'ouverture du dossier
    end.
    Euh encore un commentaire bien obscur, là c'est à la fermeture du programme et non l'ouverture d'un dossier, c'est la FAQ tel quel
    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

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    si je puis me permettre je ferais plutô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
     
      var
        DllHandle: THandle = 0;
        _DirOpenDialog: function(var aDir: PChar; const aHandle: THandle): Boolean; stdcall;
     
     function DirOpenDialog(var aDir: PChar; const aHandle: THandle): Boolean;
      begin
         Result := False;
        if DllHandle = 0 then
        begin
          DllHandle := LoadLibrary('DirOpenDlg.dll');
          if DLLHandle = 0 then
            Exit;
          @_DirOpenDialog := GetProcAddress(DllHandle, 'DirOpenDialogA');
          if @_DirOpenDialog = nil then
            Exit;
        end;
        Result := _DirOpenDialog(aDir, aHandle);
      end;
    ce qui évite de charger/décharger la DLL à chaque appel...Et elle sera libérée à la fermeture de l'application

    idem pour le Mutex, sa libération en fin de programme n'a que peu d'intérêt...et ça n'a pas de rapport avec la DLL
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 452
    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 452
    Points : 24 863
    Points
    24 863
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    ce qui évite de charger/décharger la DLL à chaque appel...Et elle sera libérée à la fermeture de l'application
    Cela peut améliorer les performances
    Cela peut être nécessaire pour certaines DLL complexe
    Cependant, je recommande une encapsulation via une petite classe pour éviter des variables globales (même si en D6, pour faire un équivalent de class var, faut en faire une mais déclarée dans la section implementation dans une unité dédiée, cela masque sa visibilité au maximum)
    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

  11. #11
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut
    @ ShaiLeTroll, avec ta suggestion, quand j'ouvrai l'application et que je choisis d'ouvrir la fiche dialogue pour le choix du dossier contenant les photos, j'avais bien deux messages d'erreur dont une erreur qui se situait dans l'unité à la ligne indiquée (voir photos) alors que je ne fermai pas l'application.

    @ Paul TOTH, ta fonction est correcte plus d'erreur et l'application fonctionne mais quand je ferme l'application avant je testais si la Dll était présente dans le dossier pour la deleter, maintenant je ne sais plus la deleter.

    Je cherche le pourquoi, vous m'avez déjà bien aidé et éclairé sur la ressource contenant une "dll".

    Encore merci de votre patience.

    P.s j'ai rajouter ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm5.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    
    FreeLibrary(DllHandle);
    
     if not deletefile(ExtractFilePath(Application.ExeName) + 'DirOpenDlg.dll' ) then
      showmessage('Une erreur est survenue lors de la fermeture');
    end;
    Et tout fonctionne, la dll est extraite, le choix du dossier photos est ok, la dll est effacée à la fermeture de l'application.

    @+,

    cincap
    Images attachées Images attachées   

  12. #12
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    pour finir, il est possible de charger la DLL directement en mémoire

    ce code que je n'ai pas testé doit correspondre à ça

    https://github.com/DSPlayer/memorymodule

    d'un point de vue technique c'est tout à fait faisable vu que les DLL sont chargées dans l'espace mémoire de l'exe, par contre il faut faire les résolutions d'adresses. En effet, les EXE et DLL sont conçus au départ pour ce charger à une adresse mémoire donnée, mais comme on peut charger plusieurs DLL on finit forcément par tomber sur deux DLL qui sont prévues pour le même espace mémoire... du coup il y a une table de réallocation qui indique tous les emplacements qui font référence à une adresse mémoire et qu'il faut mettre à jour en fonction de l'adresse réelle de chargement de la DLL en mémoire... c'est ce que fait le projet ci-dessus... quand on charge la DLL depuis le disque, c'est Windows qui fait ce boulot.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  13. #13
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 421
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 421
    Points : 1 325
    Points
    1 325
    Par défaut
    Bonjour à toutes et à tous,

    @ Paul TOTH, merci pour ton commentaire, avant de poster ma question, j'avais été voir ce lien mais pas habitué avec un chargement d'une Dll donc j'ai posté.

    Mais avec les experts de ce site, la question est souvent résolue avec plusieures solutions, je te remercie vivement ainsi que ceux qui ont pris la peine de s'intéresser au topic.

    @+,

    cincap

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 18/02/2010, 09h15
  2. utilisation d'une ressource
    Par kor6k dans le forum SDL
    Réponses: 8
    Dernier message: 16/10/2006, 16h15
  3. [JNI]Execution d'une dll dans un jar avec package
    Par osopardo dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 01/09/2006, 11h50
  4. [C#] utilisation d'une webcam avec DirectShow
    Par legillou dans le forum Windows Forms
    Réponses: 2
    Dernier message: 16/06/2006, 15h39
  5. Utilisation d'une variable avec l'instruction 'USE'
    Par florantanplan dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 10/11/2005, 10h39

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