c# - 托管 DirectX/SharpDX/SlimDX 在没有安装程序的情况下工作?

标签 c# directx sharpdx slimdx managed-directx

我正在尝试编写一个 C# 应用程序,它应该:

  • 在 .NET Framework 上运行(最好是 4.0)
  • 在尽可能多的计算机上运行 DirectX 9(所有安装了 DirectX 9 的人)
  • 是单个 EXE 文件(没有 DLL)
  • 不要强制最终用户安装任何东西(尤其是下载)

我尝试过 Managed DirectX、SharpDX,但没有成功。 (我不在乎它们是否过时,我对 DirectX 的需求不多,只需要基础知识,它是相对简单的应用程序)。为了隐藏 DLL,我将它们嵌入到资源中并通过 AppDomain.AssemblyResolve 事件加载它们。

这是我的问题:

Managed DirectX。 通常适用于大多数但不是所有计算机。尽管安装了 3D 游戏(在 DirectX 上安装和运行,至少有 9 个),但它仍然无法正常工作。 MS Managed DirectX 只是没有安装 DirectX。任何人都知道为什么?为什么有的人有,有的人没有?当我将我需要的 DLL 添加到应用程序的文件夹中时,它工作正常,但是当我将它们作为资源嵌入时,它们无法加载(即使我将它们提取到临时文件夹并尝试从那里加载).我知道如何解决这个问题,这可能会奏效,但我的问题是:我的托管 DirectX DLL 能否在每个 CPU 上运行? (32/64 位?)。我以前遇到过这种类型的问题。

SharpDX。不适用于大多数计算机,即使是现代计算机。它需要安装特定版本的 DirectX Runtime(2010 年 6 月)!如果不是,它会抛出关于缺少 d3dx9_43.dll 的异常。每个人都有 d3dx9.dll,但几乎没有 d3dx9_43.dll。安装特定版本是他们针对这个问题的官方解决方案......我不知道他们在想什么,但它就是不能用。从资源加载它们也有问题,但我已经设法解决了。当我从我的 32 位系统嵌入 d3dx9_43.dll 时,它在 64 位系统上抛出 BadImageFormatException,所以我什至不能将该文件放在应用程序旁边,更不用说嵌入它或安装到它所在的 SYSTEM32 目录应该是(这需要完全信任)。还有一个问题。即使我想要附加 DirectX 2010 年 6 月最终用户运行时,它也需要 95MB,这太多了(更不用说要求用户下载它了......)。哦,我也无法在 SharpDX 中重置设备以进入全屏(相同的代码在 Managed DirectX 上工作得很好!)但我认为它可以以某种方式修复......

SlimDX。甚至没有尝试这个,因为在其官方主页上据说它需要在最终用户计算机上安装“SlimDX Runtime”。正如我在开头所说,该应用程序应该正常工作,而不是强制用户安装任何东西(除了 DirectX 本身,它已经安装在大多数甚至旧计算机上)。

有什么建议吗?请不要再给我风滚草奖了...:] 除了进入非托管代码和编写我自己的包装器之外,我对所有事情都持开放态度。

最佳答案

我实际上有一个解决方案。或者更确切地说,我正在接近一个。

如果您使用 SharpDX.Direct3D9 或 SharpDX.Direct3D10,您可能分别需要 D3DX9_43.dll 和 D3DX10_43.dll。

您是对的,这些 DLL 位于 C:\Windows\System32 和 C:\Windows\SysWow64 目录安装 DirectX10 June 2010 Runtime 之后

但是,您的用户不想要 100MByte 的下载(太正确了)...

编辑:更新。我现在可以正常工作了

  1. 将您需要的库作为依赖项作为嵌入式资源包含在您的托管 DLL 中。

    • 确保将库的 x86 和 x64 版本包含在不同的文件夹中。
    • 例如C:\Windows\System32 中的 D3DX9_43.dll 是 x64 机器上的 64 位版本,应作为嵌入式资源包含在\Resources\Dependencies\x64 中
    • C:\Windows\SysWow64 中的 D3DX9_43.dll 是 x64 机器上的 32 位版本(看图!),应作为嵌入式资源包含在\Resources\Dependencies\x86 中
  2. 现在使用 this technique 创建一个 DLL 加载器选择性地将正确的(x86 或 x64)DLL 写入文件,使用 UAC 将 AppData\Local\YourApp\Dependencies\x64 或\x86 文件夹保存为目标

  3. 最后,通过 P/Invoke 对依赖项调用 Kernel32 LoadLibrary 函数。 重要! 只有在 Environment.Is64BitProcess 标志为 false 时才加载 x86 非托管 DLL。 x64 非托管 DLL 反之亦然

最后,啜饮玛格丽塔酒并在未安装 DirectX 运行时的机器上观看您的 SharpDX 应用程序的所有荣耀!

编辑 2:以上内容违反了 DirectX 运行时的许可协议(protocol)

正如 Xoof 在评论中指出的那样,上述内容违反了 DirectX Runtime 的许可协议(protocol)。很好,当我准备将这些 DLL 打包到商业软件中时,他让我们知道了。

相反,我们将使用我们的安装程序预先打包位于 C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Redist\下的 *cab 文件子集。我们将使用它来创建我们自己的迷你 DirectX 运行时(大约 4.7MBytes),其中只包含我们需要的文件。

enter image description here

希望以上信息对任何想要了解如何使用托管应用程序动态加载特定于平台的非托管 DLL,以及如何使用您的应用程序预打包 DirectX DLL 子集的任何人都有用!

关于c# - 托管 DirectX/SharpDX/SlimDX 在没有安装程序的情况下工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27096103/

相关文章:

c# - 在具有多个航路点的 IOS 中启动谷歌地图

asp.net - 通过 SharpDX 渲染 Direct2D 图像时如何使用内存流而不是文件?

c# - 修改wpf中任何矩形的高度后如何重新排列 Canvas 上的矩形?

c# - 如何批量远程调用数据库或服务?

c++ - 如何在 DirectX11 中正确创建聚光灯?

c# - 是否有任何 C# 或 C++ 框架可以帮助录制桌面应用程序的视频?

c++ - 如何防止direct2d “stretching”窗口大小改变时的 View ?

c# - 通过 sharpdx API 绘制和填充具有 4 个顶点(二维位置)的多边形

c# - 当数据库架构在运行时之前未知时,是否可以使用 EF 4.1 及更高版本的代码优先功能?

c++ - DirectX11 - 几何着色器流输出流未定义