2

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

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

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

这是我的问题:

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

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

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

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

4

2 回答 2

1

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

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

没错,安装 DirectX10 June 2010 Runtime 后,这些 DLL 位于 C:\Windows\System32 和 C:\Windows\SysWow64 目录中。

但是,您的用户不想要 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. 现在使用此技术创建一个 DLL 加载程序,以选择性地将正确的(x86 或 x64)DLL 写入文件,使用 UAC 保存 AppData\Local\YourApp\Dependencies\x64 或 \x86 文件夹作为目标

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

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

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

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

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

在此处输入图像描述

希望以上信息对任何想知道如何使用托管应用程序动态加载特定于平台的非托管 DLL 以及如何将 DirectX DLL 的子集与您的应用程序一起打包的人有用!

于 2015-02-13T13:03:51.910 回答
0

Note that the DirectX SDK REDIST EULA doesn't allow you to redistribute the files any way other than to use DXSETUP or DXWSETUP. You can only redistribute the CABs and then invoke DXSETUP for any version of D3DX. You do not, however, need to include all 150+ CAB files. You can include only those you actually use, but you still admin rights to launch DXSETUP. See MSDN.

Be sure to read Not So DirectSetup.

BTW, with the Windows 8.x SDK, you are allowed to redistribute the D3DCompiler_46.DLL, D3DCompiler_47.DLL, D3DCSX11_46.DLL, and/or D3DCSX11_47.DLL by just copying the file around. This is called 'application local deployment'.

于 2015-02-18T17:33:02.157 回答