Partage
  • Partager sur Facebook
  • Partager sur Twitter

Créer une DLL C++ utilisable depuis VBA

Sujet résolu
    15 novembre 2018 à 11:05:43

    Bonjour,

    J'essaye de créer une DLL sous Visual Studio qui peut être utilisée depuis un script VBA (excel).

    J'ai créé un projet "Bibliothèques de liens dynamiques" sous VS. J'ai 3 fonctions, DllRegisterServer(),DllUnregisterServer(),runApp().

    Quand j'execute "regsvr32 DLL1.dll" (DLL1 est le nom de ma DLL), la commande marche correctement.

    Lorsque que j'essaye d'appeller la fonction runApp() depuis Excel, j'ai l'erreur suivante:

    Voici le code "Dll1.cpp":

    #include "stdafx.h"
    #include "Dll1.h"
    
    DWORD __stdcall DllRegisterServer() {
    	int msgboxID = MessageBox(
    		NULL, (LPCWSTR)L"Dans DLLRegisterServer", (LPCWSTR)L"Test",MB_OK |  MB_ICONWARNING);
    
    	return 0;
    }
    
    DWORD __stdcall DllUnregisterServer() {
    	return 0;
    }
    
    DWORD __stdcall runApp() {
    	int msgboxID = MessageBox(
    		NULL,
    		(LPCWSTR)L"Fonction runApp", (LPCWSTR)L"Test_App",
    		MB_OK | MB_ICONWARNING
    	);
    	return 0;
    }

    Mon code "Dll1.h":

    #pragma once
    
    #include <windows.h>
    
    extern "C" DWORD __stdcall DllRegisterServer();
    extern "C" DWORD __stdcall DllUnregisterServer();
    extern "C" DWORD __stdcall runApp();

    Le fichier .def (Source.def):

    LIBRARY
    
    EXPORTS
      DllRegisterServer PRIVATE
      DllUnregisterServer PRIVATE
      runApp

    Ma DLL se compile bien avec aucune erreur et aucun warning. J'ai placé ma DLL dans le même dossier que mon fichier Excel (VBA).

    Mon script VBA:

    Option Explicit
    
    Public Declare PtrSafe Function runApp Lib "Dll1.dll" () As LongPtr
    
    Public Sub testRunApp()
        Dim lRetCode As LongPtr
        lRetCode = runApp
        MsgBox "runApp a retourné le code " & lRetCode, vbOKOnly Or vbSystemModal Or vbInformation, "test de DLL"
    End Sub

    Comment je peux faire ?

    Si vous avez des idées et des solutions ?

    Merci d'avance pour votre aide.





    • Partager sur Facebook
    • Partager sur Twitter
      15 novembre 2018 à 11:15:25

      Salut,

      Le fait qu'une DLL existe sur ton système ne suffit pas à la rendre utilisable, il faut qu'elle soit enregistrée. Et malheureusement, VBA n'enregistre pas les DLLs, il se contente d'utiliser celles qui le sont déjà.

      Tu peux enregistrer une DLL via la commande regsvr32.

      -
      Edité par Deedolith 15 novembre 2018 à 11:16:19

      • Partager sur Facebook
      • Partager sur Twitter
        15 novembre 2018 à 11:18:50

        Deedolith a écrit:

        Tu peux charger une DLL via la commande regsvr32.

        Tu as lu ce que j'ai écrit ? J'ai marqué: "Quand j'execute "regsvr32 DLL1.dll" (DLL1 est le nom de ma DLL), la commande marche correctement." 


        Donc oui je l'ai chargé, mais ça ne résout pas mon problème...

        • Partager sur Facebook
        • Partager sur Twitter
          15 novembre 2018 à 11:40:17


          Ops, reponse trop rapide de ma part.

          As-tu déplacé la DLL entre son enregistrement et son utilisation ?

          Autre source potentielle:

          thebastien007 a écrit:

          J'ai placé ma DLL dans le même dossier que mon fichier Excel (VBA).

          Option Explicit
           
          Public Declare PtrSafe Function runApp Lib "Dll1.dll" () As LongPtr
           
          Public Sub testRunApp()
              Dim lRetCode As LongPtr
              lRetCode = runApp
              MsgBox "runApp a retourné le code " & lRetCode, vbOKOnly Or vbSystemModal Or vbInformation, "test de DLL"
          End Sub

          Garde bien en tête que le code VBA n'est pas éxécuté par le classeur, mais par Excel.
          Et la mécanique de recherche des DLLs entre en jeux:
          Recherche via le chemin absolu.
          Sinon recherche via la variable d'environnement PATH.
          Sinon recherche dans le dossier de l'application.
          Sinon recherche dans les dossiers système.

          L'emplacement de ta DLL ne répond à aucun de ces critère, donc elle n'est pas trouvée.
          Indique un chemin absolu ?

          • Partager sur Facebook
          • Partager sur Twitter
            15 novembre 2018 à 11:59:06

            Ok merci ça marche,

            A la base ma DLL été dans le même chemin que mon fichier excel, mais visiblement ça ne marchait pas.

            J'ai mis un chemin absolue et c'est good.

            Merci !

            • Partager sur Facebook
            • Partager sur Twitter
              15 novembre 2018 à 13:59:16

              Houlà, beaucoup beaucoup de bêtises dans ce sujet. :-°

              On mélange allègrement un peu tout.

              En VBA, il y a 2 manières très différentes de travailler avec une Dll : soit via une API native C (et pas C++) soit via des composants COM.

              Les fonctions "DllRegisterServer" et "DllUnregisterServer" sont des fonctions nécessaires à l'utilisation de la Dll comme conteneur de composants COM, donc inutile dans le cadre de l'usage d'un API native C.

              Votre implémentation de ces 2 fonctions est "folklorique" et ne correspond pas du tout à ce qu'elles doivent faire : enregistrer et dés-enregistrer les types de composants COM qu'héberge la Dll. Ici, c'est pas trop grave car vous en n'avez pas mais cela a un impact sur la compréhension des actions que vous faites.

              La fonction "runApp" est exporté comme un point d'entré accessible via une API native C, avec toutes les limitations que cela impliquent comme le simple usage d'une MessageBox qui est casse-gueule avec la gestion des évènements de l'application hôte comme Excel.

              Votre code VBA utilise une déclaration d'une API native C, rendant "DllRegisterServer" et "DllUnregisterServer" superfaitatoire mais aussi vos acrobatie avec "regsvr32" car cela ne sert qu'à appeler ces 2 fonctions de manières plus ergonomique.

              "regsvr32" ne sert à rien dans le cadre de l'usage d'une API native C.

              Après, dans le cadre de l'usage d'une API native C, comme l'indique @Deedolith, le mécanisme de recherche d'une Dll dans le système est un vrai sac de nœud.

              Outre les blagues sur le répertoire de travail que mentionne indirectement @Deedolith, il est de plus en plus rare qu'il fasse partie des endroits recherchés pour trouver les Dll, pour des raisons évidentes de sécurité.

              Si vous voulez voir sur votre machine l'ordre de recherche des répertoires des dll, sans vous noyer dans la base de registre, utilisez un outil comme ProcessMonitor (https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) qui indique où le système recherche les Dll.

              Le chemin absolu, c'est vraiment pas une solution pérenne. Vous devriez voir des solutions plus fiables en utilisant des mécanismes liés aux installeurs d'applications qui gèrent souvent ce type de dépendance.

              L'usage de COM à la place d'une API native C simplifie grandement cette gestion grâce à l'enregistrement des composants.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                15 novembre 2018 à 14:20:30

                bacelar a écrit:

                il est de plus en plus rare qu'il fasse partie des endroits recherchés pour trouver les Dll, pour des raisons évidentes de sécurité.

                A ma connaissance, c'est toujours d'actualité.
                • Partager sur Facebook
                • Partager sur Twitter
                  15 novembre 2018 à 14:54:41

                  C'est le genre de truc qui saute au premier "durcissement" du système.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                  Créer une DLL C++ utilisable depuis VBA

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown