将非托管 EXE 作为资源合并到托管 C# 代码中

Posted

技术标签:

【中文标题】将非托管 EXE 作为资源合并到托管 C# 代码中【英文标题】:Incorporate an unmanaged EXE as resource in a managed C# code 【发布时间】:2012-03-05 16:43:36 【问题描述】:

我有一个用非托管 C++ 编写的给定代码,我将其作为资源添加到 C# 程序中。

当尝试使用 Assembly.Load 加载非托管 EXE 时,我得到一个 BadImageFormatException,其 InnerException 显示“IL 格式不正确”(显然)。

我怎样才能做到这一点?

我知道将代码用作 DLL 会更好,但由于某种原因,dll 调用的行为与我使用 System.Diagnostics.Process.Start 运行非托管 exe 时的行为不同。

而且我不想有两个单独的 EXE 文件。有什么想法吗?


编辑:好的,我不再需要这样做了。我的 dll 表现不同,因为我在不同的上下文中使用它(winform 而不是控制台);因此导致问题的函数SetThreadDesktop 无法按预期工作。现在要关闭帖子了,感谢所有回答的人。

【问题讨论】:

你想用这个非托管的可执行文件做什么?运行?您必须保存嵌入式 EXE,可能保存到 %TEMP% 路径,并使用 Process.Start 来启动它。然后使用WaitForExit,并删除EXE进行清理。 这确实是个好主意,但我宁愿在不生成嵌入式 EXE 的情况下完成这项工作 您应该能够使用 C++/CLI 编译器将 C++ 编译为混合模式程序集,并将其与您的 C# 代码链接到单个文件中。 【参考方案1】:

您不能使用Assembly.Load() 加载非托管的 exe/dll,它仅适用于托管的。如果您需要在该非托管文件上 PInvoke,并且您想要单个 exe 的原因只是部署,您可以将其打包为嵌入式资源(如您当前所做的那样)并在目标计算机上解压到一个文件中,并将其用作通常。

【讨论】:

好的,但也许有人可以给我一个提示,让我在没有 Assembly.Load 的情况下完成这项工作 @GianT971 我想你在尝试打包单个 exe 之前已经尝试过游戏。按照 Alexei (+1) 的建议遵循一些 PInvoke 教程 看看这个,明天给反馈【参考方案2】:

如果您将非托管 DLL 作为资源 - 基本步骤:

Save resource to disk 在运行时 使用 LoadLibrary(Win32 调用 LoadLibrary using PInvoke) 通过调用方法annotated for PInvoke 或manually via GetProcAddress 使用此库中的方法。

【讨论】:

“在运行时将资源保存到磁盘”是什么意思?我该怎么做?* 我们有搜索引擎 :) - bing.com/search?q=Save+resource+to+disk+at+run-time ,但这里有一个 ***.com/questions/864140/… 好的,您认为这样的结果可能与仅将 dll 导入项目不同? 不确定“不同”是什么意思 - 您不能将本机 DLL“导入”到托管项目。 @AlexeiLevenkov 正如 Ramhound 所发现的,可以使用 dllimport,这就是我正在做的,因此“不同”【参考方案3】:

可以自动化的稍微不同的方法是使用所谓的“组装编织” Costura.Fody - https://github.com/Fody/Costura - 是“织布工”之一。嵌入过程(带有测试自动化)用于合并非托管资源并在运行时透明地加载它们而无需太多努力 -

Install-Package Fody.Costura

然后默认情况下,所有嵌入、解包、程序集定位和加载都是自动化的,并通过添加到您的项目中的“FodyWeavers.xml”配置来控制。

<Costura> <Unmanaged32Assemblies> Foo32 Bar32 </Unmanaged32Assemblies> <Unmanaged64Assemblies> Foo64 Bar64 </Unmanaged64Assemblies> </Costura>

方法背后的概念是静态&lt;Module&gt; 类加载器,即在项目程序集成功构建后由 Fody 项目任务更改的二进制文件。在内部,Mono.Cecil 用于静态 '&lt;Module&gt;' 加载程序注入,它自动解包资源,将它们保存到临时目录,告诉在程序集加载事件中从该位置加载 dll 等等。

【讨论】:

以上是关于将非托管 EXE 作为资源合并到托管 C# 代码中的主要内容,如果未能解决你的问题,请参考以下文章

将非托管方法作为回调传递给托管 C++/CLI 类

将非托管 dll 的 Delphi 代码转换为 C#

将非托管数据复制到托管数组中

将非托管 C++ dll 添加到托管 C++ dll

如何将非托管 dll 和托管程序集合并到一个文件中?

在 C# 沙箱中运行非托管 EXE