【问题标题】:Why GetEntryAssembly returns null?为什么 GetEntryAssembly 返回 null?
【发布时间】:2017-03-06 03:49:59
【问题描述】:

GetEntryAssembly 在 C# 中的底层实现是什么?为什么从非托管应用程序加载 dll 时返回 null?

MSDN 文档说:

从非托管应用程序加载托管程序集时,GetEntryAssembly 方法可以返回 null。例如,如果非托管应用程序创建用 C# 编写的 COM 组件的实例,则从 C# 组件调用 GetEntryAssembly 方法将返回 null,因为进程的入口点是非托管代码而不是托管程序集。

我有以下设置:

本机可执行文件 (C++) -> 混合模式程序集 (C++/cli) -> 托管 程序集 (C#)

托管程序集是可选的,在混合模式程序集下,可以调用 GetEntryAssembly 并获取 null。

在调试时,我们在 C# source code 中跟踪到此调用:

[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
private static extern void GetEntryAssembly(ObjectHandleOnStack retAssembly);

我们可以看到入口程序集应该是本机可执行文件。但是,它不会被检索。我想知道这是什么原因?本机到托管转换不应该解决这个问题吗?

编辑

GetEntryAssembly 在 .NET 内部使用。当它返回null 时,我们只是遇到了副作用。 可在托管程序集中用一行重现:

System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain ();

这将引发以下异常:System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain. 此异常的根本原因似乎是条目程序集为空。

【问题讨论】:

  • 在CLR中实现。当然,同样的情况,它不能返回一个程序集对象引用,您的本机 C++ 可执行文件不是程序集。考虑改用 Process.GetCurrentProcess()。
  • 我没有在我的代码中直接使用 GetEntryAssembly。这在 C# 内部使用。并且由于它返回 null,因此其他一些代码行为不端。例如。如果有人调用System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain 将得到System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain.
  • 您当然必须修复“其他代码”,它不能依赖独立存储工作。顺便说一句,从您的问题中隐藏此信息毫无意义,它无助于我们帮助您。
  • 我想提出一个一般性问题,抱歉。为了提供完整的图片,我们正在使用 Open XML SDK,对于大文件,它开始使用独立存储而不是主内存。并且由于上述异常而无法执行操作。因此,关于入口组件的问题。

标签: c# .net c++-cli


【解决方案1】:

在我的例子中,GetEntryAssembly() 在被单元测试框架调用时返回了null。对我来说,切换到GetCallingAssembly() 就足够了。可能不会在所有情况下都有效,但对某些情况来说会。

一个 F# 示例:

let getEntryAssembly() =
    match Assembly.GetEntryAssembly() with
    | null -> Assembly.GetCallingAssembly()
    | entryAsm -> entryAsm

【讨论】:

  • 也在我的 C# 测试项目中工作过。显然,它没有理由不工作,只是想确认一下。
  • C#:var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();。显然有些单元测试框架不提供入口程序集。
【解决方案2】:

Assembly 是 .NET 特定的类。正如您提到的,您从非托管代码调用托管方法,GetEntryAssembly 将返回 null,因为根本没有理由返回任何内容!

程序集中的所有方法都绑定到 .NET 架构,并且对于 C++、Java 或任何其他外部编译源没有可能的实现。

如果你仍然不明白 - 试着想象在这种“程序集”中使用反射:获取一些经过核心优化的 C++ 方法名称,或者获取变量类型……这仅适用于 C++ ,更不用说其他语言了。

【讨论】:

  • GetEntryAssembly 在 .NET 实现中被调用。由于 GetEntryAssembly 之前返回了 null ,因此该行失败并出现异常。 .NET 似乎并不支持所有 Native -> Mixed mode -> Managed 工作流。
猜你喜欢
  • 2012-04-25
  • 2022-12-26
  • 2016-12-28
  • 2015-11-25
  • 2015-07-04
  • 2019-09-29
  • 2015-02-25
  • 2015-10-21
  • 2021-08-12
相关资源
最近更新 更多