【问题标题】:Debugging code from dynamically loaded assembly in .net core 2.0在 .net core 2.0 中从动态加载的程序集中调试代码
【发布时间】:2023-04-04 13:58:01
【问题描述】:

我有一个 .net core 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()。

知道为什么/出了什么问题吗?

【问题讨论】:

  • 也许只是我的代码选项应该被禁用? blogs.msdn.microsoft.com/zainnab/2010/10/25/…
  • 您需要确保 .pdb 文件与您正在加载的 dll 位于同一位置。然后,Visual Studio 将加载该数据并允许它在断点处停止。

标签: c# .net .net-core


【解决方案1】:

这可能是由于应用程序无法找到与MyAssembly 程序集关联的 PDB 文件,如 cmets 之一所述。但是,似乎不需要 PDB 文件与程序集位于同一文件夹中即可进行调试。

为了检查符号是否加载,请在调用Assembly.LoadFile()之后的行中设置断点并打开Modules窗口(可以在Debug\Windows 菜单)。在此窗口中,找到 MyAssembly 程序集并验证 Symbol Status 列中的值。如果缺少 PDB 是原因,则值为“无法找到或打开 PDB 文件。”。您还可以使用该窗口查看调试器尝试在哪里找到符号文件。

调试器在多个位置查找 PDB 文件,如下所述: Specify Symbol (.pdb) and Source Files in the Visual Studio Debugger.

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

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

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

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

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

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

【讨论】:

  • 嗨卢卡斯。感谢您的回答。就我而言,不幸的是,模块已加载。
  • 通过“加载模块”,您的意思是加载的符号显示在此动态加载的程序集的模块窗口中,我正确吗?
  • 是的,对不起,我就是这个意思。
  • 也许尝试在程序实例的调试菜单中使用“附加到进程”,并尝试选择所有托管代码类型? (即 CoreCLR 和 4.x)
【解决方案2】:

你检查选项just my code了吗?

启用仅我的代码

("My Code") 仅,忽略系统代码和其他代码 优化或没有调试符号。调试器显示并进入用户代码

也许应该取消选中?

【讨论】:

    【解决方案3】:

    我同意 Lukasz 和 Alexan 的回答。如果您检查了这些并且它不起作用,那么您的代码示例不同的原因可能是它们没有加载相同的程序集。

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

    【讨论】:

    • @MathijsFlietstra:我的帖子解释了为什么两个示例的行为可能不同。从这个意义上说,我相信我的回答除了知道什么是错误的之外可能很有用,这已经在 Lukasz 的回答中涵盖了。
    【解决方案4】:

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

    查看此 SO 帖子:Debug dynamically loaded assembly

    也可以在 MSDN 上查看:https://msdn.microsoft.com/en-us/library/twt16z2x(v=vs.110).aspx

    希望对你有帮助

    【讨论】:

    • 但这仅在我从字节数组加载时才需要,还是我错了?
    • 您可以将任何文件加载为字节数组。 System.IO.File.ReadAllBytes(string path) -- 对吗?
    【解决方案5】:

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

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

    解决方法如下: 完整的工作解决方案在这里 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多