2016-11-09 1 views
6

Je travaille sur un projet d'API Web qui utilise un cadre interne de simulation qui permet d'intercepter et de modifier les réponses des contrôleurs. Il utilise MEF pour charger un assembly qui contient du code qui est exécuté si certaines conditions préalables sont reconnues.Pourquoi suis-je incapable de déboguer un assembly chargé dynamiquement?

Je sais que cela fonctionne correctement, car je peux voir dans la réponse que le simulacre a été exécuté, mais pour une raison quelconque, je suis incapable de déboguer le code dans l'assembly chargé dynamiquement. Bien que les points d'arrêt semblent actifs, l'exécution ne s'arrête jamais là.

The breakpoint is active

J'ai essayé d'appeler Debugger.Break(); et il rompt en effet, mais la pile d'appel apparaît vide et Visual Studio montre que ce message:

The application is in break mode

je peux voir que l'assemblage et la les symboles sont chargés dans la fenêtre des modules:

Modules window shows that symbols were loaded correctly

Je suis en mesure de briser juste avant l'appel à l'assemblée chargée dynamiquement (paramètre behavior), qui ressemble à ceci:

private HttpResponseMessage ApplyBehavior(
    IMockBehavior behavior, 
    string controller, string action, 
    HttpRequestMessage request, 
    HttpResponseMessage mockedResponse) 
{ 
    return behavior.Apply(controller, action, request, mockedResponse); 
} 

Si je tente de inspectent la variable behavior dans la fenêtre immédiate, montre Visual Studio l'exception suivante:

behavior.GetType() 
'behavior.GetType()' threw an exception of type 'System.IO.FileNotFoundException' 
    Data: {System.Collections.ListDictionaryInternal} 
    FileName: null 
    FusionLog: null 
    HResult: -2147024894 
    HelpLink: null 
    InnerException: null 
    Message: "Cannot load assembly 'SuperMam.WebAPI.Mocking'." 
    Source: null 
    StackTrace: null 
    TargetSite: null 

Cela fait partie d'une assez grande application, et je suis incapable d'extraire les parties pertinentes. J'ai essayé de rassembler autant d'informations que possible, mais je n'ai toujours aucune idée de la raison pour laquelle cela se produit.

Que puis-je faire pour résoudre ce problème?

EDIT 1

Juste pour être sûr, si j'appelle le code de mon contrôleur, je suis en mesure d'intervenir dans normalement:

var behaviourType = AppDomain.CurrentDomain.GetAssemblies() 
    .First(a => a.FullName.Contains("SuperMam.WebAPI.Mocking")) 
    .GetType("SuperMam.WebAPI.Mocking.MyBehaviour"); 

var behavior = (IMockBehavior)Activator.CreateInstance(behaviourType); 
// I can step into this, and view the behaviour variable in the watch 
behavior.Apply("dummy", "dummy", Request, null); 

mais même quand je le fais, quand même méthode est appelée par le cadre moqueur, je ne peux pas y entrer.

EDIT 2

I a également remarqué que le même ensemble (FullName est identique) est chargé à deux reprises. La différence entre les deux cas est leur CodeBase et Location propriétés:

  • L'un d'eux a CodeBase égal à mon répertoire bin applications et l'emplacement égal à C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
  • l'autre d'entre eux a CodeBase égal au premier son emplacement (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...), et l'emplacement est une chaîne vide.

Est-ce que cela pourrait être la cause du problème?

+0

Qu'en est-il de ce problème? Pouvez-vous partager les dernières informations de votre côté? –

+0

Ça se passe toujours. Je crois que cela est dû au fait que l'assemblage est chargé deux fois, mais je n'ai aucune idée de comment l'empêcher. –

Répondre

0

Il s'avère que la raison en était que l'assemblage n'était pas chargé par MEF comme je le pensais. Il était chargé en utilisant Assembly.Load(File.ReadAllBytes(mockDllPath)). Étant donné que l'assembly a été chargé à partir d'un tableau d'octets, aucune information de débogage n'était disponible pour le débogueur.

3

L'assembly que vous essayez de charger dynamiquement est compilé sur votre système?

Pour déboguer des assemblys chargés dynamiquement, vous avez besoin d'un fichier PDB à côté de la DLL. Ce fichier contient des informations de débogage sur votre assembly requises par Visual Studio. Lorsque vous compilez un assembly en mode débogage, le PDB est automatiquement créé dans le dossier ./bin/Debug/ de votre projet. Si vous avez déplacé votre DLL vers un autre emplacement, essayez de déplacer la PDB au même emplacement.

+0

Le PDB est présent à côté de la DLL, comme démontré par Visual Studio pouvant charger les symboles de débogage (voir la capture d'écran de la fenêtre "modules"). –

+0

Les deux projets visent la même version du framework? – sc3w

+0

Oui, ils ciblent tous le framework 4.5 –

-1

Le problème devrait être dû à la méthode utilisée pour charger l'ensemble.

Je suppose que vous utilisez:

Assembly.LoadFrom ...

essayez d'utiliser

Assembly.Load

+0

Peu importe la méthode que vous utilisez pour le chargement (sauf ReflectionOnly). La seule chose nécessaire est le fichier .pdb et le démarrage de l'application en mode débogage. – Oliver

+0

'Load From' n'autorise pas le bon chargement de pdb, contrairement à la méthode 'load'. –

+0

L'assembly est chargé par MEF (en utilisant '[ImportMany]'). Je ne sais pas comment MEF est implémenté, mais je suppose qu'il devrait être possible de déboguer le code. –

2

Votre application est entré dans un état de rupture, mais aucun code en cours d'exécution n'est pris en charge par le moteur de débogage sélectionné.

J'ai aussi rencontré ce message d'erreur avant:

https://social.msdn.microsoft.com/Forums/en-US/99b43950-6c82-4945-ba16-04355abf9612/vs2015-breakpoints-dont-work?forum=vsdebug

Si possible, vous pouvez vérifier que si elle est liée aux options de débogage/paramètres ou la configuration VS.

(1) La dernière mise à jour pour VS2015 est la mise à jour 3.

(2) Activer l'utilisation du mode de compatibilité Managed serait un répertoire pour cette question.

+0

Votre deuxième suggestion s'est avérée très utile. * Futurs visiteurs * - Veuillez vous référer à la capture d'écran dans [ce] (https://stackoverflow.com/q/42158547/465053) poste pour une référence visuelle rapide pour voir où se trouve l'option 'Managed Compatibility Mode' . – RBT