2009-09-26 18 views
0

J'ai un morceau de code .NET qui, pour diverses raisons (fiabilité, déploiement) doit s'exécuter dans un AppDomain distinct. J'ai créé un objet proxy dérivé de MBR qui délègue les appels aux vrais pour qu'ils ne se chargent pas dans l'AppDomain actuel. Je crée le proxy via l'habituel CreateInstanceAndUnwrap. Cela fonctionne très bien lorsque je l'utilise à partir d'un client .NET, mais lorsqu'il est chargé à partir d'un client COM, la conversion échoue. Je reçois un échec à partir d'un proxy transparent. J'ai validé que le type requis est créé sur l'AppDomain désiré et que le Unwrap réussit, juste la distribution échoue. Fait intéressant, cela fonctionne lorsque les deux AppDomain ont le même répertoire de base, ce qui pointe vers des échecs de liaison d'assembly. Mais la visionneuse de journaux Fusion ne mentionne aucun problème.Impossible d'utiliser AppDomain à partir de COM interop

Il existe deux questions quelque peu similaires here et here, mais elles ne fournissent aucune réponse. Des idées sur ce qui ne va pas, ou comment puis-je le déboguer davantage?

Répondre

1

J'ai rencontré ce problème il y a quelques années. IIRC, le problème était que la pile d'appels croise deux frontières d'appdomain, ce qui amène le proxy à l'obejct géré à être marshalé deux fois (COM-> default-> yours: nouvel objet: -> yours-> default). Normalement ce n'est pas un problème, mais il y a une interface spéciale que les QI du marshaler .NET COM pour ça dit "salut, je suis un objet managé et ai besoin d'un comportement spécial de marshaling" (désolé, je ne me souviens pas du IID-try ComTrace propre IDispatch impl et le marshal à travers le CLR pour voir). C'est là que vous êtes arrosé - lorsque cela s'exécute dans le domaine par défaut, il sait que vous êtes géré puis demande et tente de charger votre type géré, qui ne réussira que lorsque la base de votre nouveau domaine est la même que celle par défaut. Cela va évidemment à l'encontre de tout le but.

Il y a plusieurs façons dont j'ai traité cela. Une façon est de rendre la création d'objet asynchrone afin que je puisse envoyer directement le proxy géré au code non géré du nouveau domaine (par exemple, enregistrer un rappel non géré et l'appeler directement depuis le nouveau domaine, en ignorant le domaine par défaut). Ceci est évidemment délicat dans un scénario addin où vous ne contrôlez pas tout de bout en bout.

L'autre était d'avoir une petite tranche de code non managé qui roulait un proxy muet qui n'a pas répondu quand le marshaleur .NET a demandé "êtes-vous vraiment un objet géré?" mais passerait par tous les autres QIs et tout sur IDispatch ne serait pas molester (j'ai limité mon hack à IDispatch seulement, aussi, ce qui m'a facilité la tâche). Ainsi, la nouvelle séquence va: COM-> default-> yours: nouvel objet-> nouveau wrapper proxy-> default-> COM. Major PITA - J'ai trouvé un article de blog d'un gars de l'équipe d'interopérabilité de CLR qui faisait des corrections à ce sujet dans une future version de CLR, mais c'était il y a plusieurs années et je ne me souviens pas qui était (désolé, je ne fais plus d'interop pour vivre, Dieu merci!)