从.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文件的默认位置是:
- 在程序集本身内指定的位置(在编译程序集时由链接器放置)
- 动态加载的程序集所在的文件夹
- 本地符号缓存文件夹
- 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.LoadFile
和Assembly.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);