从.net core 2.0中的动态加载程序集调试代码

我有一个.net核心2.0控制台应用程序,它执行以下操作(简化):

var a = Assembly.Load(Assembly.GetEntryAssembly() .GetReferencedAssemblies() .First(i => i.Name == "MyAssembly")); var t = a.GetType("MyType"); var i = (MyBaseType)Activator.CreateInstance(t); i.Execute(); 

当我通过代码调试时,它按预期进入MyType.Execute()

但是,如果我使用以下代码加载程序集:

 var path = new FileInfo(Assembly.GetExecutingAssembly().Location); var a = Assembly.LoadFile(Path.Combine(path.DirectoryName, "MyAssembly.dll")); 

代码仍然有效,但我无法在调试时进入MyType.Execute()

任何想法为什么/什么是错的?

这可能是由于应用程序无法找到与MyAssembly程序集关联的PDB文件引起的,如其中一条评论中所述。 但是,似乎PDB文件不需要与程序集相同的文件夹以进行调试工作。

为了检查是否加载了符号,请在调用Assembly.LoadFile()之后在行中放置一个断点并打开Modules窗口(可以在Visual Studio的Debug \ Windows菜单中找到它)。 在此窗口中,找到MyAssembly组件并validation符号状态列中的值。 如果缺少PDB是原因,则值将为“ 无法找到或打开PDB文件 ”。 您还可以使用该窗口查看调试器尝试查找符号文件的位置。

调试器在多个位置查找PDB文件,如下所述: 在Visual Studio调试器中指定符号(.pdb)和源文件 。

根据该文章,PDB文件的默认位置是:

  1. 在程序集本身内指定的位置(在编译程序集时由链接器放置)
  2. 动态加载的程序集所在的文件夹
  3. 本地符号缓存文件夹
  4. Internet,网络或本地符号服务器

我想在你的情况下,应该考虑提到的第一个或第二个位置。

另一个需要注意的重要事项是PDB必须与程序集完全匹配,因此在重新编译程序集后,还应更新PDB文件以匹配新版本。

如果PDB文件与程序集匹配并位于上述某个位置,则应该能够调试代码。

可能还有其他原因,这与使用.NET Core的事实没有直接关系,但我认为正确的PDB加载可能值得validation。

你选择了我的代码吗?

在此处输入图像描述

启用我的代码

(仅限“我的代码”),忽略系统代码和其他优化的代码或没有调试符号的代码。调试器显示并进入用户代码

也许它应该不受限制?

我同意Lukasz和Alexan的答案。 如果您已经检查过这些并且它不起作用,那么您的代码示例之所以不同,可能是因为它们没有加载相同的程序集。

执行的组件和入口组件并不总是相同的组件,因此路径可以不同。 也可能是加载了另一个版本的程序集,例如从GAC加载。 使用Visual Studio中的模块窗口,您可以看到加载了哪个DLL。 如果存在正确的PDB并且Just My Code已关闭,您应该能够进入它。

有一个’Assembly.Load’覆盖,它将PDB数据作为参数。 您需要显式加载调试符号。

检查这个SOpost: 调试动态加载的程序集

另请参阅MSDN: https : //msdn.microsoft.com/en-us/library/twt16z2x(v = vs.110) .aspx

希望这可以帮助

如果使用Assembly.LoadFile方法,则代码将无法编译。

我已经在Visual Studio 2017社区中创建了一个示例项目,并且我能够通过使用Assembly.LoadFileAssembly.Load方式从动态程序集中进入函数。 我没有和你一起使用代码,因为它没有编译,但我会提供一个解决方案,我认为你将解决你的问题。

以下是解决方案:完整的解决方案在这里https://github.com/beyazc/.netcore-dynamic-assembly-debug

基本上我能用以下代码进行调试。 你应该在调用方法上按f11

 var assemlies = Assembly.GetEntryAssembly().GetReferencedAssemblies(); var assemblyName = ""; foreach (var item in assemlies) { if (item.Name == "RefProj") assemblyName = item.Name; } var path = new FileInfo(Assembly.GetExecutingAssembly().Location); var a = Assembly.LoadFile(Path.Combine($@"{path}\..\..\..\..\..\RefProj\bin\Debug\netstandard2.0", "RefProj.dll")); var t = a.GetType("RefProj.Class1"); var i = Activator.CreateInstance(t); MethodInfo mi = t.GetMethod("get1"); mi.Invoke(i, null);