Le serveur COM géré sans registres ne sera pas activé

J’ai commencé avec un système très sophistiqué de clients et de serveurs avec des références COM et d’autres éléments, et j’ai réduit mes capacités jusqu’à ce que je réalise que je ne parviens même pas à obtenir un exemple de code Microsoft pour une activation COM gratuite de l’enregistrement d’un serveur COM géré. écrit en C #.

Code serveur:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices.ComTypes; using System.Runtime.InteropServices; using System.ComponentModel; namespace ClassLibrary1 { [Guid("A7AC6D8C-FF17-4D2C-A3B1-2C8690A8EA04") ,ComVisible(true)] public interface IClass1 { [DispId(1)] ssortingng DummyFunction(ssortingng inputValue); } [Guid("81723475-B5E3-4FA0-A3FE-6DE66CEE211C"), ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typeof(IClass1)), ComVisible(true)] public class Class1 : IClass1 { public ssortingng DummyFunction(ssortingng inputValue) { return inputValue.Subssortingng(0, 1) + " Inserted " + inputValue.Subssortingng(1); } } } 

Code client VB6:

 Dim c As ClassLibrary1.Class1 Set c = New Class1 MsgBox c.DummyFunction("Ben") 

Code client C ++:

 #include "stdafx.h" #import  raw_interfaces_only using namespace ClassLibrary1; int _tmain(int argc, _TCHAR* argv[]) { IClass1Ptr p; HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); hr = CoCreateInstance(__uuidof(Class1), NULL, CLSCTX_INPROC_SERVER, __uuidof(IClass1), (void **)&p); if (FAILED(hr)) { _tprintf_s(_T("Error %x\n"), hr); CoUninitialize(); return 1; } _bstr_t b = _T("Bobby"); BSTR b2; p->DummyFunction(b, &b2); wprintf_s(L"%s\n", b2); p->Release(); CoUninitialize(); return 0; } 

Les deux clients fonctionnent correctement lorsque je supprime tout le code COM Reg-Free et enregistre la ClassLibrary1.dll avec regasm / codebase.

Ensuite, je désenregistre ClassLibrary1 et tente d’introduire Reg-Free COM pour le client VB6 avec le fichier Project1.exe.manifest:

          

Et ClassLibrary1.manifest:

       

Maintenant, je reçois parfois l’erreur 429 (le composant ActiveX ne peut pas créer d’object) et parfois (inexplicablement) une erreur d’automatisation:

Erreur d’exécution ‘-2146234304 (80131040)’: Erreur d’automatisation

J’essaie ensuite d’introduire l’isolation COM dans le client C ++: Bibliothèque de types COM isolés = F: \ Lib \ ClassLibrary1.tlb - Nom du fichier composant = ClassLibrary1.dll

Maintenant, quand je lance le client C ++, la sortie est simplement

Erreur 800401f9

Après de nombreux essais utilisant différents exemples avec le support technique de Microsoft, j’ai identifié de nombreux pièges lors de la tentative d’implémentation d’un serveur COM géré avec un client COM C ++ non géré. Voici les informations essentielles dont je me souviens, qui peuvent être appliquées à l’exemple de code de la question pour s’assurer que cela fonctionne.

  1. Le client ne doit pas utiliser les parameters COM isolés dans le projet C ++. Ma mémoire s’efface, mais le support technique de Microsoft me dit que c’est pour autre chose, je pense pour le développement d’une interface COM isolée vers un serveur COM non géré à la place d’un serveur COM géré. Bien que cela ne soit pas du tout clair à partir de sa description à l’ adresse https://msdn.microsoft.com/en-us/library/zzbcs3x5(v=vs.120).aspx .
  2. Le client peut sélectionner “Oui” ou “Non” pour le paramètre “Manifest intégré”, mais si “Oui” est sélectionné, le manifeste contenant les informations d’assemblage dépendant doit être fourni sous la forme d’un fichier manifeste d’entrée. Si le manifeste incorporé ne contient pas d’informations d’assembly dépendant, alors tout fichier manifeste externe sera ignoré. Assurez-vous également que la configuration (Debug, par exemple) en cours d’édition correspond à la configuration à tester! entrez la description de l'image ici
  3. Si le serveur COM est signé avec une clé (nom fort), l’élément assemblyIdentity du manifeste du client et du manifeste du serveur doit contenir publicKeyToken, sinon l’erreur HRESULT 0x80131040 se produira lors de CoCreateInstance.
  4. L’incorporation de la ressource RT_MANIFEST en tant que ressource Win32 dans du code managé n’est pas une tâche facile avec Visual Studio 2013, car les projets C # et VB.NET ont tendance à vouloir incorporer des ressources sous la forme de ressources .NET gérées, et non de ressources Win32 (vous pouvez le vérifier en ouvrant la sortie DLL. fichier avec le visualiseur de ressources et notez que les exécutables .NET obtiennent généralement une version de ressource et pas grand chose d’autre, même si le projet contient un fichier manifeste inclus). Une façon de contourner ce problème consiste à créer un fichier RC comme celui-ci:

 #define RT_MANIFEST 24 #define MANIFEST_RESOURCE_ID 1 MANIFEST_RESOURCE_ID RT_MANIFEST ClassLibrary1.manifest 

Ajoutez ensuite une étape de pré-construction comme ceci:

 "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe" "$(ProjectDir)ClassLibrary1.rc" 

Ensuite, dans l’onglet “Application” du projet, modifiez les “Ressources” pour utiliser ClassLibrary1.res au lieu de “Icône et manifeste”. Mais cela pose des problèmes: premièrement, le chemin d’access à RC.EXE n’est pas facile à définir sans le coder en dur; Deuxièmement, les informations de version de AssemblyInfoCommon seront ignorées car les ressources du fichier RC remplacent totalement toutes les ressources Win32 générées par le compilateur .NET.

Une autre possibilité consiste simplement à séparer le fichier manifeste de la DLL COM du serveur et à ne pas l’intégrer en tant que ressource. J’ai lu que cela peut ne pas être fiable, mais cela fonctionne sur Windows 7 Enterprise 64 bits SP1.

  1. Pour s’assurer que le client non géré charge le bon runtime .NET, il a besoin d’un fichier de configuration ( ConsoleApplication1.exe.config ) qui définit le mode de chargement du fichier .NET. Pour .NET 4.5, j’ai vu ce travail:

      

Alors que pour .NET 3.5, il semble que useLegacyV2RuntimeActivationPolicy doive être commuté:

      
  1. Il est important de vérifier que toutes les versions du framework et du CLR sont synchronisées. Et il est important de comprendre que les versions CLR ne sont pas les mêmes que celles du framework. Par exemple, si vous souhaitez créer un serveur COM géré sur .NET 3.5, la version CLR (runtimeVersion) doit être “2.0.50727”, mais la version .NET (supportedRuntime) doit être “v3.5”.

  2. Assurez-vous que la version cible du .NET Framework du serveur COM correspond à la version de supportedRuntime du client. S’il est créé à partir de la ligne de commande, il se peut que la version du framework ne soit pas extraite du fichier de projet Visual Studio (par exemple, si vous exécutez directement le compilateur C # de VB.NET au lieu d’appeler MSBuild), assurez-vous que la construction cible la bonne version du framework.

Je n’ai pas encore validé tout ce qui précède, mais j’ai l’intention de passer rapidement en revue tout ce processus pour vérifier que j’ai tout attrapé. Voici ce que j’ai fini avec ce que je n’ai pas encore mentionné:

ConsoleApplication1.exe.manifest (dans le répertoire source, est copié ou incorporé dans le répertoire de sortie au moment de la construction)

          

ClassLibrary1.manifest

      

MODIFIER:

Maintenant, passez en revue et validez chaque détail avec les informations complètes du message d’erreur, etc.

Je commence par créer une solution unique contenant deux projets avec toutes les valeurs par défaut et le code indiqué dans la question. Je commence par aucun fichier de manifeste ni aucun des parameters de projet mentionnés dans la question, et j’appellerai explicitement lorsque je modifie le processus ci-dessous. Ce sont les étapes et les erreurs qui sont sur le chemin pour faire fonctionner ce projet.

  1. Erreur: “Classe1: Identificateur non déclaré”. Vous devez exécuter une invite de commande du développeur et exécuter la ligne de commande suivante pour obtenir un fichier TLB que le code C ++ peut importer: tlbexp ClassLibrary1.dll
  2. Déplacez le fichier TLB dans le répertoire du projet ConsoleApplication1 et reconstruisez-le. Même erreur.
  3. Remplacez les #import raw_interfaces_only sur #import raw_interfaces_only par des guillemets. Le texte est donc lu #import "ClassLibrary1.tlb" raw_interfaces_only . Reconstruire: le succès.
  4. À ce stade, si nous courons, nous obtenons l’ Error 80040154 (classe non enregistrée) car nous n’avons pas enregistré le composant ni configuré COM sans inscription.
  5. En sachant qu’essayer de mettre en place Isolated COM dans le client présenterait une Error 800401f9 nous l’ Error 800401f9 et essayerons simplement de créer un manifeste client. Créez un nouveau fichier texte avec le contenu suivant et enregistrez-le sous le nom ConsoleApplication1.exe dans le répertoire du projet ConsoleApplication1:

          
  1. À ce stade, il apparaît que les étapes mentionnées précédemment dans cette solution sont un peu trop compliquées. Vous pouvez simplement inclure le fichier manifeste dans le projet en affichant les fichiers cachés et en utilisant la commande “Inclure dans le projet” sur le fichier manifeste.
  2. Si vous démarrez à ce stade, le message d’erreur “L’application n’a pas pu démarrer car sa configuration côte à côte est incorrecte. Consultez le journal des événements de l’application ou utilisez l’outil de ligne de commande sxstrace.exe pour plus de détails.” Ceci est en partie dû au fait que nous n’avons mis ClassLibrary1.dll nulle part où ConsoleApplication1.exe peut le trouver. La sortie sxstrace analysée à ce stade ressemble à ceci:

 INFO: Parsing Manifest File C:\Users\bmarty\Documents\Visual Studio 2013\Projects\RegFreeCOM\Debug\ConsoleApplication1.exe. INFO: Manifest Definition Identity is ConsoleApplication1,type="win32",version="1.0.0.0". INFO: Reference: ClassLibrary1,version="1.0.0.0" INFO: Resolving reference ClassLibrary1,version="1.0.0.0". INFO: Resolving reference for ProcessorArchitecture ClassLibrary1,version="1.0.0.0". INFO: Resolving reference for culture Neutral. INFO: Applying Binding Policy. INFO: No binding policy redirect found. INFO: Begin assembly probing. INFO: Did not find the assembly in WinSxS. INFO: Attempt to probe manifest at C:\Users\bmarty\Documents\Visual Studio 2013\Projects\RegFreeCOM\Debug\ClassLibrary1.DLL. INFO: Attempt to probe manifest at C:\Users\bmarty\Documents\Visual Studio 2013\Projects\RegFreeCOM\Debug\ClassLibrary1.MANIFEST. INFO: Attempt to probe manifest at C:\Users\bmarty\Documents\Visual Studio 2013\Projects\RegFreeCOM\Debug\ClassLibrary1\ClassLibrary1.DLL. INFO: Attempt to probe manifest at C:\Users\bmarty\Documents\Visual Studio 2013\Projects\RegFreeCOM\Debug\ClassLibrary1\ClassLibrary1.MANIFEST. INFO: Did not find manifest for culture Neutral. INFO: End assembly probing. ERROR: Cannot resolve reference ClassLibrary1,version="1.0.0.0". ERROR: Activation Context generation failed. End Activation Context Generation. 
  1. La copie du fichier ClassLibrary1.dll dans le même répertoire que ConsoleApplication1.exe ne change rien car nous n’avons pas fourni de manifeste pour le fichier permettant d’identifier la dépendance COM. La prochaine étape consiste donc à créer un manifeste pour ClassLibrary1. Une version de ClassLibrary1.manifest est déjà présente dans la question. Essayons cela en créant un fichier texte avec ce contenu et en l’enregistrant dans le répertoire du projet ClassLibrary1 sous le nom ClassLibrary1.manifest. Pour l’inclure dans le projet, essayons la même commande simple “Inclure dans le projet” (encore une fois, activer la visibilité des fichiers cachés pour rendre cela possible). Que se passe-t-il maintenant lors de la copie du nouveau ClassLibrary1.dll dans le répertoire avec ConsoleApplication1.exe et de son exécution?
  2. La même erreur et les mêmes résultats sxstrace se produisent car un fichier manifeste dans une DLL gérée n’est pas incorporé en tant que ressource Win32, comme vous pouvez le vérifier en ouvrant le fichier DLL avec Visual Studio, qui affiche les ressources Win32 du fichier. Il montre la ressource de version et rien d’autre. Excluons donc le manifeste de ClassLibrary1 et copions simplement le fichier manifeste dans l’emplacement de ConsoleApplication1.exe en tant que fichier externe.
  3. Succès! Le programme s’exécute et se termine normalement. Mais que se passe-t-il si nous voulons utiliser un composant construit avec une version différente du framework .NET. Ou peut-être que votre test ne fonctionne pas à ce stade parce que votre Visual Studio est par défaut sur une version différente? À l’heure actuelle, je constate que mon projet ClassLibrary1 est configuré par défaut sur .NET 3.5. Que se passe-t-il si je le change en 4.0, reconstruis, copie et lance à nouveau?
  4. L’erreur 8013101b se produit. Cela correspond (selon une recherche Google) à COR_E_NEWER_RUNTIME, ce qui signifie également “Un module spécifié dans le manifeste n’a pas été trouvé”. Cela se produit lorsque, par exemple, un fichier EXE chargé. NET 2.0 tente de référencer une DLL créée avec .NET 4.0. Nous devons donc maintenant indiquer au fichier EXE client non géré la version du framework .NET à charger pour résoudre sa référence COM. Ceci est fait avec un fichier de configuration nommé ConsoleApplication1.exe.config. Créez simplement un nouveau fichier texte et enregistrez-le sous ce nom dans le répertoire ConsoleApplication1.exe. Il a le contenu suivant:

      

La même erreur se produirait quand même si useLegacyV2RuntimeActivationPolicy était exclu dans ce cas. Malheureusement, je ne comprends pas tout à fait pourquoi, mais je suppose que cela a quelque chose à voir avec la nouvelle stratégie d’activation d’exécution v4.0 qui charge par défaut le chargement de CLR v2.0 si l’exécutable chargé ne fait pas explicitement référence à .NET 4.0 le code managé ne le fait pas car il ne fait pas explicitement référence à la période .NET).

  1. Encore du succès! Mais attendez, il y a plus. Que se passe-t-il si votre dll COM est signée avec une clé (a un nom fort)? Ajoutons une clé à ClassLibrary1, configurons-la pour la signature de la DLL dans l’onglet “Signature” du projet et voyons ce qui se passe lorsque nous copions la DLL mise à jour dans le répertoire de ConsoleApplication1.exe.
  2. Nous avons maintenant l’erreur 80131040 (“La définition du manifeste de l’assembly localisé ne correspond pas à la référence de l’assembly”). Et sxstrace, et fuslogvw ne fournissent aucune information frustrante sur ce qui se passe. Heureusement, je sais maintenant que dans ce scénario particulier reg-free-com, cela est dû à l’absence de l’atsortingbut publicKeyToken sur les éléments assemblyIdentity décrivant ClassLibrary1 (dans les deux fichiers manifest). Mais comment obtenez-vous la valeur publicKeyToken? Exécutez sn -T ClassLibrary1.dll partir d’une invite de commande du développeur. Après avoir mis à jour ClassLibrary1.manifest et ConsoleApplication1.exe.manifest, n’oubliez pas de reconstruire ConsoleApplication1.exe si le manifeste est incorporé et de copier ClassLibrary1.manifest dans le répertoire ConsoleApplication1.exe. Courir à nouveau et?
  3. Je suis passé par quelques autres mouvements de résolution d’erreurs à l’aide de sxstrace, mais c’était dû à des erreurs stupides. Si vous avez des erreurs sxstrace, voici quelques points à prendre en compte pour aider ceux qui font des erreurs stupides: a) assurez-vous d’utiliser l’atsortingbut publicKeyToken et non un autre nom ridicule, comme privateKeyToken ; b) Assurez-vous que tous les atsortingbuts que vous avez spécifiés dans l’assemblyIdentity du manifeste côté serveur correspondent à ceux du manifeste côté client et que le type="win32" n’est pas spécifié sur l’un mais pas sur l’autre.
  4. Succès! La sortie est B Inserted obby

Je dois également noter que le client VB6 fonctionne également en utilisant les fichiers suivants avec le client VB6:

Project1.exe.config:

      

Project1.exe.manifest:

          

Cependant, il semble y avoir une tendance à signaler “Impossible pour le composant de créer un object ActiveX” (erreur d’exécution 429) dans de rares cas lorsque l’exécutable est créé et exécuté avant la création des fichiers de configuration et des fichiers manifestes. La reconstruction du fichier EXE semble résoudre le problème, mais je ne parviens pas à résoudre le problème. Il est donc difficile d’identifier une cause spécifique.

Je pensais résoudre assez bien les problèmes, mais quelque chose au sujet des nombreuses pièces mobiles et des nombreux codes d’erreur et messages d’erreur inefficaces signalés dans les problèmes de configuration de com-reg-free rend cette tâche presque impossible à comprendre sans une expérience solide, des connaissances internes ou une source Microsoft. code. Espérons que cette réponse aidera les autres à acquérir une expérience similaire. Veuillez prolonger cette réponse si vous en apprenez plus!

Addendum 1

Le manifeste du serveur COM géré peut être correctement et facilement intégré si vous utilisez la commande “Ajouter” -> “Nouvel élément …” du projet pour append un “fichier de manifeste d’application”. Cela ajoute un fichier appelé app.manifest au projet. Mais ce qui est vraiment difficile, c’est qu’il ne peut pas être reproduit autrement via l’interface utilisateur de Visual Studio, si ce n’est par le biais d’une solution de contournement. Etant donné que le champ “Manifest” de l’onglet “Application” de la fenêtre de configuration du projet est désactivé pour les projets de type “Bibliothèque de classes”, le manifeste, qui serait normalement défini ici, ne peut pas être défini pour une bibliothèque de classes. Mais vous pouvez modifier temporairement le projet en une application Windows, modifier la sélection Manifest ici, puis le restaurer dans une bibliothèque de classes. Le paramètre va restr pour que le manifeste sélectionné soit correctement incorporé. Vous pouvez vérifier le réglage dans un éditeur de texte en affichant le fichier de projet. Chercher:

  app.manifest  

Addendum 2

Erreur 0x80131040 peut toujours se produire avec toutes les précautions sockets ci-dessus. Pour vous aider à en déterminer l’origine, il est utile d’utiliser le visualiseur de journal de fusion pour obtenir plus d’informations sur ce qui se passe lorsque les assemblys sont chargés et résolus. Google “Fuslogvw” pour plus d’informations sur la façon d’afficher ce journal (fuslogvw.exe est un utilitaire fourni lorsque Visual Studio est installé). Il est également important de réaliser que cette application, par défaut, ne montre apparemment aucune information jusqu’à ce que vous la configuriez pour enregistrer les informations dans des fichiers, reproduire le problème, puis redémarrer l’application pour lire les fichiers journaux une fois qu’ils ont été générés. Et, selon la documentation MSDN, il est également important de vous rappeler d’exécuter cet utilitaire en tant qu’administrateur.

Une fois que vous avez passé tous les obstacles à l’exécution de fuslogvw.exe, il est possible que quelque chose comme ce soit affiché dans le journal:

 WRN: Comparing the assembly name resulted in the mismatch: Major Version ERR: The assembly reference did not match the assembly definition found. ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated. 

Bien que le fichier de manifeste du serveur COM ait répertorié la version 1.0.0.0, il ne s’agit pas de la version (seule) utilisée lors de la liaison d’une référence client COM au serveur. Mon fichier EXE client essayait de référencer 1.0.0.0, ce qui correspondait exactement à la version du fichier manifeste du serveur COM, mais ne correspondait pas à la version .NET de la DLL. Après avoir corrigé les fichiers manifestes du client et du serveur afin de refléter la version actuelle dans la DLL du serveur .NET, l’erreur 0x80131040 a disparu et fuslogvw.exe a été la clé pour l’identifier en tant que source du problème.

Si le manifeste du client est synchronisé avec la version réelle de la DLL .NET, mais que le fichier de manifeste de la DLL du serveur ne reflète pas cette version, une erreur différente se produira:

L’application n’a pas pu démarrer car sa configuration côte à côte est incorrecte. Consultez le journal des événements de l’application ou utilisez l’outil sxstrace.exe de la ligne de commande pour plus de détails.

Addendum 3

Erreur 0xc0150002 ou le message suivant peut être signalé:

L’application n’a pas pu démarrer correctement (0xc0150002). Cliquez sur OK pour fermer l’application.

J’ai vu cela se produire dans un cas où le manifeste du client était incorporé dans une DLL non gérée plutôt que dans un fichier EXE non géré et où l’élément assemblyIdentity du manifeste ne correspondait pas exactement à l’ assemblyIdentity du serveur. Le client contenait un processorArchitecture="x86" supplémentaire processorArchitecture="x86" que le serveur n’a pas spécifié, ce qui a provoqué une non-concordance. Malheureusement, je ne sais pas comment apprendre cela sans penser heureusement à vérifier les fichiers manifestes pour voir s’ils correspondent (ou à lire cet article). Cette erreur n’indique pas clairement que le fichier manifeste est la source du problème. Vous devez donc être conscient qu’il existe une corrélation possible entre ce message d’erreur et cette cause.

Addendum 4

J’ai vu des fichiers de manifestes externes complètement ignorés, ce qui donnait un journal sxstrace complètement vide, même lorsque les exécutables impliqués n’avaient aucun manifeste. Cela peut apparemment se produire du fait du cache de contexte d’activation (un problème décrit à l’ adresse http://csi-windows.com/blog/all/27-csi-news-general/245-find-out-why-your-external). -manifest-is-being-ignored ). Pour contourner ce problème, vous pouvez utiliser la commande suivante pour toucher l’horodatage du fichier dont le manifeste est ignoré:

 copy /b myfile.exe+,, 

Addendum 5

J’ai constaté une autre erreur difficile à expliquer, classe non enregistrée ( 0x80040154REGDB_E_CLASSNOTREG ), lors de l’appel de CoCreateInstance dans les conditions suivantes:

  1. Un fichier CPP contient un constructeur pour une classe instanciée dans une étendue globale. L’initialisation dynamic appelle donc le constructeur pendant DllMain si le commutateur /clr n’est pas appliqué au fichier CPP ou lors de .cctor si le commutateur /clr est appliqué à la fichier.
  2. La DLL comporte un manifeste incorporé lui permettant de référencer la classe COM créée via COM sans registre.
  3. La DLL COM est implémentée dans du code managé (avec un wrapper COM-Callable appelé CCW) dans .NET 2.0.
  4. Le fichier EXE qui a chargé la DLL ne comporte pas de manifeste sans registre référençant la classe COM créée.
  5. La DLL COM n’est pas enregistrée avec regasm .
  6. Dans le fichier CPP appelant CoCreateInstance le commutateur /clr est appliqué aux parameters du compilateur C ++.

Si l’une des 3 dernières conditions est modifiée, le problème disparaît. (En outre, si la dernière condition est modifiée, vous pouvez obtenir un locking du chargeur en raison de la position n ° 1 – pour en savoir plus sur le locking du chargeur et sa relation avec CLR lors de l’ initialisation d’assemblages mixtes ). Par conséquent, si vous rencontrez une erreur de classe non enregistrée dans des circonstances similaires, demandez-vous si vous pouvez modifier l’une ou l’autre de ces 3 conditions pour résoudre l’erreur. Note: J’ai du mal à comprendre le comportement de # 6. Il semble que l’effet de changer cela dépend aussi de l’état de # 1. Cela ressemble à l’appel du constructeur (y compris de son CoCreateInstance ) après le chargement complet de la DLL, mais non de la classe, mais l’appel du constructeur lors de l’initialisation de la DLL aboutira si le commutateur /clr n’est pas spécifié. Ma solution pour le moment consiste à recoder le fichier CPP client en C ++ géré, car il s’agissait d’une classe d’interface relativement simple entre le composant COM et le rest du code non géré. Alors maintenant, il n’y a plus de COM dans ce client, juste une référence .NET.

À toutes mes frustrations, l’explication de BlueMonkMN était vraiment utile mais j’ai quand même rencontré le message Class not registered .

J’ai un .NET 4.6 COM interop Dll et un client C ++ qui utilise Registration Free COM au moyen de la technologie Windows SxS. Le manifeste d’assembly a été intégré à la DLL COM et le manifeste d’application a été placé à l’extérieur, sous la forme d’un fichier .manifest distinct.

Tout fonctionnait comme annoncé, mais le message Class not registered commencé à CreateInstance lors de la création de CreateInstance lorsque l’un des CreateInstance suivants se produit.

  • Copiez la DLL COM interop avec l’exécutable client C ++ et le fichier manifeste dans un autre répertoire.
  • Apportez des modifications non liées au COM au client C ++, puis régénérez l’application.

Dans cette situation, le journal sxstrace était vide, le journal des événements de l’application ( eventvwr ) ne signalait aucune erreur SideBySide et le visualiseur de journal de liaison d’assemblage ( FUSLOGVW.exe ) ne montrait rien à partir de l’application client C ++.

Permettez-moi d’append un autre addendum à la réponse de BlueMonkMN.

Addendum 6

Ce que je comprends de mes expériences jusqu’à présent, c’est que, dans un tel cas, le contexte d’activation de l’application client C ++ n’est pas créé.

Dans une telle situation, il est nécessaire de créer le contexte d’activation par eux-mêmes.

Le code suivant est placé dans l’application cliente C ++, après un appel à CoInitialize(0); et avant de faire un appel à CreateInstance .

 ACTCTX context; memset(&context, 0, sizeof(context)); context.cbSize = sizeof(context); context.lpSource = L"CPPClient.exe.manifest"; context.lpAssemblyDirectory = L"D:\\code\\vs2017\\CPPClient\\Debug"; context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; HANDLE hActCtx = CreateActCtx(&context); ULONG_PTR cookie = 0; BOOL result = ActivateActCtx(hActCtx, &cookie); //Rest of the code goes here. 

En tant que mesure de nettoyage, le morceau de code suivant est placé juste avant un appel à CoUninitialize();

 DeactivateActCtx(0, cookie); ReleaseActCtx(hActCtx); 

Maintenant ça sonne bien. Côte à côte fonctionne très bien. En cas de problème, vous pouvez le voir dans sxstrace, dans le journal des événements de l’application ou dans la visionneuse de journal d’assemblage.