C# 调试.net core 2.0中动态加载程序集的代码
我有一个.net core 2.0控制台应用程序,可执行以下操作(简化): 当我调试代码时,它会按预期逐步进入C# 调试.net core 2.0中动态加载程序集的代码,c#,.net,.net-core,C#,.net,.net Core,我有一个.net core 2.0控制台应用程序,可执行以下操作(简化): 当我调试代码时,它会按预期逐步进入MyType.Execute() 但是,如果使用以下代码加载程序集: var path = new FileInfo(Assembly.GetExecutingAssembly().Location); var a = Assembly.LoadFile(Path.Combine(path.DirectoryName, "MyAssembly.dll")); 代码仍然有效,但调试时我无
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的调试\窗口菜单中找到)。在此窗口中,找到MyAssembly
assembly并验证符号状态列中的值。如果原因是缺少PDB,则值将为“找不到或无法打开PDB文件”。您还可以使用该窗口查看调试器试图在何处查找符号文件
调试器在多个位置查找PDB文件,如下所述:
根据文章,PDB文件的默认位置为:
可能还有其他原因,这与使用.NET Core的事实没有直接关系,但我认为正确的PDB加载可能值得验证。我同意Lukasz和Alexan的答案。如果您已经检查了这些,但它不起作用,那么代码示例不同的原因可能是它们没有加载相同的程序集
执行程序集和条目程序集并不总是相同的程序集,因此路径可能不同。也可能是加载了程序集的另一个版本,例如从GAC加载。使用VisualStudio中的“模块”窗口,可以查看加载了哪个dll。如果存在正确的PDB,并且仅禁用了“我的代码”,则您应该能够单步执行该操作。有一个“Assembly.Load”覆盖,它将PDB数据作为参数。您需要显式加载调试符号 查看此SO帖子: 也可以在MSDN上查看此内容:
希望这对您有所帮助如果您使用
Assembly.LoadFile
方式,代码将不会编译
我已经在Visual studio 2017社区中创建了一个示例项目,通过使用assembly.LoadFile
和assembly.Load
两种方式,我能够从动态汇编中逐步实现一个函数。我没有使用您的代码,因为它不是编译的,但我将提供一个解决方案,我认为您将解决您的问题
以下是解决方案:
完整的工作解决方案在这里
基本上我可以用下面的代码进行调试。您应该在调用方法时按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);
也许我的代码选项应该被禁用?您需要确保.pdb文件与正在加载的dll位于同一位置。VisualStudio随后将加载该数据并允许它在断点处停止。谢谢你的回答。在我的例子中,模块不幸加载。所谓“模块加载”,您是指模块窗口中显示的动态加载程序集加载的符号,对吗?是的,很抱歉,我的意思是这样的。可能尝试在程序实例的调试菜单上使用“附加到进程”,然后尝试选择所有托管代码类型?(即CoreCLR和4.x)但这仅在从字节数组加载时才需要,或者我错了吗?您可以将任何文件作为字节数组加载
System.IO.File.ReadAllBytes(字符串路径)
--对吗?@MathijsFlietstra:My posts解释了为什么这两个示例的行为可能不同。从这个意义上说,我相信我的回答除了只知道什么是错的之外是有用的,卢卡斯的回答已经涵盖了这一点。
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);