comment appeler une DLL C # à partir de c ++ non géré en utilisant IDispatch?

J'ai un c # dll que je dois appeler à partir de C ++ non managé. Le problème principal que j'ai est que mon code c ++ correspond à un complément excel, qui peut être installé pour Excel 2003 et excel 2007, lorsque j'installe mon complément dans Excel 2007 et j'essaie d'appeler mon c # dll, cela fonctionne très bien, mais pour une raison quelconque que je n'ai toujours pas pu find, dans Excel 2003, il se bloque, Excel me montre un message d'erreur d'exécution et, lors du debugging de mon code c ++, je vois que le code échoue lors de la tentative de créez une instance de ma c # dll, il dit que la class n'est pas enregistrée même si je me suis enregistré avec un regasm.

C'est mon code C #:

namespace ManagedDLL { [ Guid("3C80EE60-D9B8-4daf-89BE-6C7B748F613C"), InterfaceType( ComInterfaceType.InterfaceIsDual), ComVisible(true) ] public interface ICalculator { [DispId(1)] int main(ssortingng args, IntPtr _handle); }; [ Guid("5134F342-5B7F-4db2-94F0-F450610419CF"), ProgId("myapp.CCOMEntryPoint"), ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typeof(ICalculator)), ComVisible(true) ] public class COMEntryPoint : ICalculator { public int main(ssortingng args, IntPtr _handle) { ssortingng[] _args = args.Split(new char[] { ':' }); Program.handle = _handle; return Program.Main(_args); } } } 

et en C ++, ce que je fais, c'est importer le file .tlb qui est généré lorsque j'utilise le regasm pour save ma c # dll, comme ceci:

 \#import "..\bin\release\ManagedDLL.tlb" raw_interfaces_only using namespace ManagedDLL; . . . int callMyDll() { long handle = 0, result = 0; BSTR args; HRESULT hr = CoInitialize(NULL); ICalculatorPtr pICalc(__uuidof(COMEntryPoint)); pICalc->main(bstrStr, handle, &result); return result; } . \#import "..\bin\release\ManagedDLL.tlb" raw_interfaces_only using namespace ManagedDLL; . . . int callMyDll() { long handle = 0, result = 0; BSTR args; HRESULT hr = CoInitialize(NULL); ICalculatorPtr pICalc(__uuidof(COMEntryPoint)); pICalc->main(bstrStr, handle, &result); return result; } . \#import "..\bin\release\ManagedDLL.tlb" raw_interfaces_only using namespace ManagedDLL; . . . int callMyDll() { long handle = 0, result = 0; BSTR args; HRESULT hr = CoInitialize(NULL); ICalculatorPtr pICalc(__uuidof(COMEntryPoint)); pICalc->main(bstrStr, handle, &result); return result; } . \#import "..\bin\release\ManagedDLL.tlb" raw_interfaces_only using namespace ManagedDLL; . . . int callMyDll() { long handle = 0, result = 0; BSTR args; HRESULT hr = CoInitialize(NULL); ICalculatorPtr pICalc(__uuidof(COMEntryPoint)); pICalc->main(bstrStr, handle, &result); return result; } 

Mais comme je l'ai déjà mentionné, ce code ne fonctionne pas pour Excel 2003, alors mes questions sont les suivantes:

  1. Je fais quelque chose de mal dans la façon dont je déclare mon C # dll qui me cause des problèmes dans Excel 2003?
  2. Tout comme il est maintenant, mon C # peut-il être considéré comme un object ActiveX?
  3. Comment puis-je appeler mon c # dll d'une autre manière à partir de c ++? comme utiliser IDIspatch par exemple

Merci

J'ai eu un problème similaire auparavant. Je n'appelais pas C # depuis C ++, mais le concept est le même.

J'ai dû charger une dll .NET dans une application hôte via COM, qui ressemble à ce que vous essayez de faire. Le problème était que l'application hôte (dans votre cas excel) était en train de charger l'exécution .NET 1.1. Notre dll a été compilé pour .NET 2.0.

Il pourrait être que Excel 2003 charge le 1.1 runtime et 2007 charge une version plus récente. Découvrez ce forum: Excel sélectionne le mauvais time d'exécution .NET .

Vous pouvez également tester cela en utilisant MSBee pour cibler le 1.1 time d'exécution, puis essayez de charger votre dll dans Excel 2003.

Je ne suis pas un codeur C ++, donc je ne peux pas commenter cette partie, mais pour y répondre du côté C #:

"Je fais quelque chose de mal dans la façon dont je déclare mon C # dll qui me cause des problèmes dans Excel 2003?"

Non, votre utilisation d'atsortingbut est exactement correcte. Bien joué.

"Tout comme c'est le cas maintenant, mon C # peut-il être considéré comme un object ActiveX?"

En compilant avec les attributes que vous montrez et puis vous enregistrez via RegAsm, vous avez créé et correctement exposé votre assemblage à COM, ce que vous voulez. (Le terme "ActiveX" est généralement utilisé en reference aux controls COM, et votre class n'est pas un contrôle.)

"Comment puis-je appeler mon c # dll d'une autre manière à partir de c ++? J'aime utiliser IDIspatch par exemple".

Vous utilisez l'atsortingbut [InterfaceType(ComInterfaceType.InterfaceIsDual)] , ce qui signifie que l'interface est exposée à la binding anticipée et à la binding tardive via IDispatch.

En bref, je ne sais pas ce qui ne va pas ici, alors j'essaierais de l'idée de dequadin de vérifier que la version .NET Framework chargée soit au-dessus ou au-dessus du cadre sur lequel vous construisez.

Si ce n'est pas le cas, la seule autre chose que je peux penser, c'est que vous obtenez un crash direct, sans erreur recouvrable, me suggère qu'il pourrait y avoir une sorte de mal alignment entre l'interface enregistrée vs l'interface sur laquelle l'appelant a été compilé. Cela peut se produire car le GUID ne change pas si vous changez l'interface – vous avez explicitement configuré le GUID via un atsortingbut – alors, si l'interface change du tout sans que tout soit reconstruit et enregistré de bas en haut , tous l'enfer se déstring. Par conséquent, si vous avez changé votre interface de quelque façon que ce soit, vous devez rebuild l'assemblage C #, vous save à nouveau avec RegAsm, puis recopiner votre complément C ++ qui le fait reference.

C'est tout à fait la meilleure idée. Et n'explique pas le problème Excel 2003 vs 2007 si vous utilisez le même assemblage exact pour chacun. En bref, il est difficile de savoir ce qui ne va pas, car votre code C # a l'air 100% propre.

— Mike