【问题标题】:How do I find out if a .NET assembly contains unmanaged code?如何确定 .NET 程序集是否包含非托管代码?
【发布时间】:2009-12-22 13:16:36
【问题描述】:

包含托管和非托管代码混合的 .NET 程序集不能与其他程序集进行 ILMerged。

如何验证给定的 .NET 程序集是包含纯托管代码,还是包含托管代码和非托管代码?

【问题讨论】:

    标签: .net assemblies unmanaged native


    【解决方案1】:

    根据 nobugz 的建议,查看 CLR 标志的更简单方法是使用 corflags 实用程序,它是 .NET 2.0 SDK 的一部分。

    如果没有指定选项,则显示给定图像的标志:

    C:\>corflags Foo.dll
    Version   : v2.0.50727
    CLR Header: 2.5
    PE        : PE32
    CorFlags  : 9
    ILONLY    : 1
    32BIT     : 0
    Signed    : 1
    

    “ILONLY”位指示这是纯托管程序集还是混合程序集。

    请注意,用户“nobugz”的评论表明这些标志不能保证是正确的,因此这种方法可能不是万无一失的。

    【讨论】:

      【解决方案2】:

      对您的程序集运行PEVerify 工具。

      PEVerify.exe 与 Visual Studio 一起安装,例如这个是 Visual Studio 2012 自带的:

      C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\PEVerify.exe

      【讨论】:

      • 运行此实用程序后,如何判断它是否是纯托管代码?我刚刚得到:“ 中的所有类和方法都已验证。”
      • @DanW:那么一切都很好。否则你会得到错误。如果从脚本或其他程序调用,您可以检查指示错误的非零退出代码。您可以使用 C# 中的“unsafe”关键字进行测试。
      【解决方案3】:

      从 Visual Studio 命令提示符运行 ildasm,如下所示:

      ildasm file.exe /headers /noil /text

      在输出结束时,您将看到以下内容:

      // ----- CLR 标头:
      // 标题大小:...
      // 主要运行时版本:...
      // 次要运行时版本:...
      // ...
      // 标志:0x00000000

      如果 Flags 设置了最低位(例如 0x00000001),则程序集是纯 CLR;如果不是(例如 0x00000000),则程序集为混合模式。请注意,可能存在其他标志,因此它只是您感兴趣的最低位(因此,如果最后一位数字是 1、3、5、7、9、b、d 或 f,那么它就是纯 CLR)。

      (编辑:您也可以以图形方式运行 ildasm,打开相关的可执行文件,然后从“查看”菜单中选择“标题”以查看相同的信息。)

      【讨论】:

      • 不是灌篮高手 afaik,即使您使用 /clr:pure 编译,C++/CLI 编译器/链接器也不会正确设置此位。 Corflags.exe 也显示了这一点。
      【解决方案4】:

      改进上面提供的答案 Wim...

      1. 找到你的“PEVerify.exe” - 如果你安装了 VS,你就拥有它。 - 将完整路径复制到 PEVerify.exe 文件,你的路径将不同 - - 这是一个示例:C:\Program文件 (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\PEVerify.exe

      2. 打开 Visual Studio 命令提示符(不要“以管理员身份运行”)

      3. 输入:cd C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools

      4. 您的命令提示符现在应该是这个长文本,而不仅仅是 C:\ 之类的......它将指向 PEVerify.exe 所在的路径。

      5. 现在输入:peverify "your full path to your dll you want to check - 然后按 Enter - 这是我的示例:peverify "G:\TestFolder\My_Managed_OR_Unmanaged.dll"

      6. 按 Enter 后,您会收到如下消息,它的 100% 托管 dll - My_Managed_OR_Unmanaged.dll 中的所有类和方法均已验证。”

      【讨论】:

        【解决方案5】:

        要从 C# 中获取 PE 标志,请使用 System.Reflection API:http://www.example8.com/category/view/id/6027

        ...

        Assembly a = Assembly.GetExecutingAssembly();
        Module m = a.ManifestModule;
        
        PortableExecutableKinds peKinds;
        ImageFileMachine imageFileMachine;
        m.GetPEKind(out peKinds, out imageFileMachine);
        
        if ((peKinds & PortableExecutableKinds.ILOnly) != 0)
        

        ...

        【讨论】:

          【解决方案6】:

          我必须仔细检查一下,但我很确定您可以通过 redgate 使用 Reflector 找到它。

          【讨论】:

          • 这似乎不是一个好主意 - 挖掘程序集的所有方法需要大量工作
          • 怎么样?我在 Reflector 5.1.6.0 中找不到与此相关的任何内容。
          【解决方案7】:

          ILMerge 仅合并托管程序集,here,引用他们的下载页面,“ILMerge 是用于将多个 .NET 程序集合并为单个 .NET 程序集的实用程序”。

          我还没有看到托管程序集与本机二进制文件合并。从技术上讲,您可以将它们本身合并,通过将非托管二进制文件包含为嵌入式资源,但是将嵌入式资源作为二进制代码加载到内存中 - 我以前从未见过这种情况。我已经尝试过使用内存映射的技术,但失败了。

          另一种检查方法是查看二进制文件本身,如果它在数据目录中有第 15 个条目,并且不为零,那么它是一个 .NET 二进制文件,本机二进制文件没有这个。请参阅 here 我在其中发布了类似问题的答案。

          希望这会有所帮助, 最好的祝福, 汤姆。

          【讨论】:

            【解决方案8】:

            我认为你应该使用 .NET 反射来遍历程序集中的所有类型和方法。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-05
              • 1970-01-01
              相关资源
              最近更新 更多