【问题标题】:does .net dll have an entry point like dll in c++ dll.net dll 有没有像 c++ dll 中的 dll 这样的入口点
【发布时间】:2015-02-14 04:28:55
【问题描述】:

我真的不确定 .net dll 是否也有像 c++ dll 通常有的入口点。 如何查看 .net dll 是否有入口点。

我在某处读到 WIN32 dll 可以有入口点,点网类库没有。

谢谢,

【问题讨论】:

  • 使用静态构造函数。

标签: c# c++ .net dll


【解决方案1】:

这是一个晦涩难懂的主题,我会以惊人的速度完成它。每个 .NET 程序集都有一个 unmanaged 入口点,5 个字节的机器代码(如果为 x64 构建,则为 9 个字节)用作 PE32 可执行文件头中标记的入口点。只有一条 JMP 指令,一个 EXE 跳转到 _CorExeMain(),一个 DLL 跳转到 _CorDllMain()。这些函数位于 mscoree.dll 中,并确保 CLR 已加载和初始化,以便它可以执行托管代码。

这些入口点有助于运行托管程序,而无需显式启动 VM 主机。避免需要mono.exe 或java.exe。它们实际上不再在现代 Windows 版本上使用,操作系统知道包含 .NET 清单的可执行文件,并且加载程序再次将作业传递给加载程序 shim,mscoree.dll。这种意识对于实现considerable trick 建立一个包含 32 位 PE32 标头的 EXE 的 64 位进程是必要的。 Mscoree.dll 修补内部加载程序数据结构来完成这一壮举。

每个 .NET 程序集还包含一个 托管 入口点,在清单标头中列出。由 CLR 在加载程序集后立即调用。一个 EXE 总是有一个,它指向 Main() 方法,编译器确保你不会忘记写一个。一个 DLL 可能有一个,例如,混合模式程序集总是有一个。指向位于<Module> 类中的module initializer,C++/CLI 编译器使用它来确保在任何托管代码可以执行之前初始化 CRT(C 运行时库)。

【讨论】:

  • 我查看了一些 .NET exe 清单(使用 ILDASM),但没有发现其中任何一个对托管入口点的引用???
  • 这不是 ildasm.exe 显示的东西,程序员很少遇到 Main() 方法的问题。 Corhdr.h SDK 头文件可能对逆向工程更有用,它注释了许多低级清单细节,例如 IMAGE_COR20_HEADER.EntryPointToken 字段。
【解决方案2】:

不,.NET DLL 程序集没有DllMain,就像非托管 DLL 那样。但是,在DllMain 中实现的所有行为通常都可以使用各种 .NET 结构来实现。例如:

  • 类静态构造函数让您有机会在使用类型之前初始化静态成员
  • 实例初始化(构造函数、字段初始化器)允许您在使用实例之前初始化实例数据
  • 实现IDisposable 接口可为您提供确定性清理。实现终结器为您提供了非确定性清理的可能性(但不是保证)(即在对象被垃圾收集之前)
  • AppDomain 具有 DomainUnloadProcessExit 事件,可让您在应用域或进程关闭时运行清理代码。

【讨论】:

  • .NET DLL 程序集确实有一个与 DllMain 类似的构造 Module Initializers 但是你不能在 C# 中创建它们,你必须在 IL 或一些允许你编写 C# 并发出初始化器中的等效 IL(如 Fody/ModuleInit
  • @ScottChamberlain:是的,我没有提到模块初始化器,因为它们对于典型的 C# 程序员来说并不实用(与 DllMain() 形成对比,它是 C/C++ 代码中的标准构造)。
猜你喜欢
  • 2019-07-02
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多