2

I'm trying to write a C# application that should:

  • run on .NET Framework (4.0 ideally)
  • run on DirectX 9 on as much computers as possible (everyone that have DirectX 9 installed)
  • be a single EXE file (without DLLs)
  • do not force the end user to install anything (especially to download)

I have tried Managed DirectX, SharpDX and I didn't succeed. (I don't care if they are obsolete, I don't need much from DirectX, only the basics, it's relatively simple app). For hiding the DLLs I'm embedding them into resources and loading them by AppDomain.AssemblyResolve event.

Here are my problems:

Managed DirectX. Generally works, on most BUT NOT ALL computers. There was a case that it wasn't working despite of that there were even 3D games installed (which install and run on DirectX, at least 9). The MS Managed DirectX was just NOT INSTALLED with the DirectX. Anyone knows why? Why some people have it and some don't? When I added the DLLs I needed into the folder with the app it was working fine, but when I've embedded them as resources, they couldn't load (even when I've extracted them to temp folder and tried to load from there). I've got an idea of how to resolve that, which may work, but my quesion is: will my Managed DirectX DLLs work on every CPU? (32/64 bit?). I had problems of this type before.

SharpDX. Doesn't work on most computers, even the modern ones. It requires a specific version of DirectX Runtime (June 2010) to be installed! If it's not, it's throwing exception about missing d3dx9_43.dll. Everyone have d3dx9.dll, but almost noone d3dx9_43.dll. Installing the specific version is their official solution for this problem... I don't know what were they thinking, but it's just not usable. Also there was a problem to load them from resources but I've managed to resolve that. When I've embedded the d3dx9_43.dll from my 32 bit system it was throwing a BadImageFormatException on 64 bit system, so I can't even put that file next to the app, not to mention embedding it or installing to SYSTEM32 directory where it should be (which would require Full Trust). There is another problem. Even if I would want to attach the DirectX June 2010 End-User Runtime, it's taking 95MB, which is MUCH too much (not to mention asking the user to download it...). Oh, and I also can't reset the device in SharpDX to go fullscreen (the same code worked just fine on Managed DirectX!) but I assume it CAN be fixed somehow...

SlimDX. Didn't even try this because on its official homepage it is said that it requires a "SlimDX Runtime" to be installed on end-user computer. As i said at the beginning, the app should JUST WORK and not force the user to install anything (except the DirectX itself, which is already installed on most, even old computers).

Any suggestions? Please don't give me the tumbleweed award again... :] I'm open to everything except going into unmanaged code and writing my own wrapper.

P.W.
  • 657
  • 8
  • 15
  • Do like everyone does, install the necessary runtimes for your program to work at the last installation step. – aybe Nov 24 '14 at 03:38
  • Your basic problem is that you can't count on .NET to be "on every version of Windows". Windows XP doesn't come with any version of .NET by default. Windows 8 only has .NET 4.0 by default which is not compatible with legacy Managed DirectX 1.1. And of course, all DirectX interop from .NET needs assemblies added to the GAC since this is not part of core .NET. In short: To have a DirectX app without any installation requirements means writing it in something other than C#. – Chuck Walbourn Nov 24 '14 at 06:11
  • Also, ``D3DX9.DLL`` isn't a Microsoft DLL. They are all number versioned, and no version of D3DX is included with any Windows OS by default. If you use D3DX, you have to use the legacy DirectX REDIST as that's the only way to deploy it. – Chuck Walbourn Nov 24 '14 at 06:12
  • @Chuck Walbourn: 1. I'm not worried about the .NET Framework on XP. These days it's hard to NOT have ANY .NET application installed and even if so, it's a painless and almost automatic process as you are asked and guided to install it without any setup for the app. 2. But you've got a point with the Win 8, although it's hard to believe it's not backward compatible and you are left with .NET 4.0 ONLY and you don't have 3.5. Seriously?? Is that true?? 3. You CAN run Managed DirectX on 4.0: http://stackoverflow.com/questions/26324181/ (tested, works) 4. It doesn't need to be in GAC. (...) – P.W. Nov 24 '14 at 23:02
  • 4. It doesn't need to be in GAC. It worked when just copied next to my app on the Win 8 computer with no Managed DirectX installed at all. 5. I just can't load it from resources (`Assembly.Load(byte[])`) - and that would fix all my problems at once. The same dll file loads automatically but can't be loaded from stream! Anyone knows why?? Thanks for help. – P.W. Nov 24 '14 at 23:06
  • Windows 8.x by default only has .NET 4.0 enabled. You can enable the .NET 3.5 runtime as a Windows Feature, and many appcompat things will cause it to turn on such as trying to run the .NET 3.x REDIST. W.r.t. to Windows XP, you can't count on a particular version of .NET to be present... It could have just .NET 4.0, or it could have .NET 2 - 3.5. – Chuck Walbourn Nov 25 '14 at 01:24
  • I thought that when you install .NET 3.5, you've got all earlier versions installed with it for backward compatibility... Isn't it true? That just doesn't make sense - you can't assume that all applications are written for the newest version! It MUST be backward compatible! Also when you install ANY .NET version, the next ones comes automatically in Windows Updates. Am I wrong? – P.W. Nov 25 '14 at 10:28

2 Answers2

1

I actually have a solution for this. Or rather, I am closing in on one.

If you use SharpDX.Direct3D9 or SharpDX.Direct3D10 it's likely you need D3DX9_43.dll and D3DX10_43.dll respectively.

You are right that these DLLs are located in the C:\Windows\System32 and C:\Windows\SysWow64 directories after installing the DirectX10 June 2010 Runtime.

However, your users don't want a 100MByte download (too right)...

EDIT: Update. I now have this working

  1. Include the libraries you need as dependencies as embedded resources in your Managed DLL.

    • Make sure you include the x86 and x64 versions of the library in separate folders.
    • e.g. D3DX9_43.dll from C:\Windows\System32 is the 64bit version on x64 machines, should be included as an embedded resource in \Resources\Dependencies\x64
    • D3DX9_43.dll from C:\Windows\SysWow64 is the 32bit version (go figure!) on x64 machines and should be included as an embedded resource in \Resources\Dependencies\x86
  2. Now create a DLL loader using this technique to selectively write out the correct (x86 or x64) DLLs to file, using the UAC save AppData\Local\YourApp\Dependencies\x64 or \x86 folders as targets

  3. Finally, call the Kernel32 LoadLibrary function via P/Invoke on the dependencies. IMPORTANT! Only ever load x86 unmanaged DLLs when the Environment.Is64BitProcess flag is false. Vice versa for x64 unmanaged DLLs

Finally, sip margarita and watch your SharpDX application in all its glory on a machine with no DirectX Runtime installed!

EDIT 2: The above breaks the licensing agreement for the DirectX Runtime

As Xoof points out in the comments, the above breaks the licensing agreement for the DirectX Runtime. Good he let us know really as I was about to package these DLLs into commercial software.

Instead, we're going to go down the route of pre-packaging a subset of the *cab files found under C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Redist\ with our installer. We will use this to create our own mini DirectX Runtime (about 4.7MBytes) with just the files we need.

enter image description here

Hopefully the above info is useful to anyone who wants to know how to dynamically load platform-specific unmanaged DLLs with a managed application, and how to pre-package a subset of DirectX DLLs with your application!

Dr. Andrew Burnett-Thompson
  • 20,980
  • 8
  • 88
  • 178
  • 1
    Afaik, the license agreement don't permit to redistribute DirectX DLL runtime in your application like this. You need to redistribute them using official cabs. Also you don't need to have 100Mbyte of install. You just have to pickup the cab files from the DirectX SDK and package them in your installer. It is usually just a few Mo for an up-to-date DirectX runtime, including audio and d3d. – xoofx Feb 13 '15 at 14:42
  • Thanks for the heads up... I'm leaving my answer above as its a useful reference for dynamically loading x86/x64 unmanaged DLLs within a .NET application. I'm developing a commercial component so I need to think of a way to not only slip the DirectX Runtime into the installer but also make it easy for my users to do the same into their installers. I managed to get the list down to just 4.7MBytes with the necessary CABs. Thanks again – Dr. Andrew Burnett-Thompson Feb 13 '15 at 18:54
  • Thank you guys for the help. I really appreciate it. So if I understand you right, the only legal solution for this is to include a folder with those few files of DirectX Redist and just launch DXSetup when the d3dx9_43.dll file is missing? I'm not including an installer (the app should just WORK), so the worst acceptable thing I can do is to check for the dll and if it's not installed (and I can't install it silently) to show an error message and run the DXSetup from the folder next to my app,to make user install the required dll. Is this the only legal option? – P.W. Feb 22 '15 at 00:03
  • And any embedding of DX redist parts is illegal, right? – P.W. Feb 22 '15 at 00:06
  • And what about Managed DirectX? Is it legal to have it embedded or at least dropped (just few files) next to my app? Because it's working with MDX on most of the computers and - with the files dropped - on the rest (so far I know). I even made it work with .NET 4.0 (which is theoretically not possible). And with the native LoadLibrary technique you mentioned I even may be able to embed it in my app! (It's not working via Assembly.Load method). So if this would be legal, all my (our) problems would have been solved! What do you think? – P.W. Feb 22 '15 at 00:20
  • Yeah it looks like it. SharpDX itself is MIT licensed so you can redistribute it freely. Is just the D3dx10checkversion libraries that need an installer. Big shame but that's the way it is. Hope the above info helped you. – Dr. Andrew Burnett-Thompson Feb 22 '15 at 09:18
  • For Managed DirectX, not sure, you'll have to check the licensing agreements. Wasn't sure that still existed? Which is why SlimDX, SharpDX do exist. – Dr. Andrew Burnett-Thompson Feb 22 '15 at 19:28
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'.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81