2

I have a given code written in unmanaged C++ that I added as a resource in a C# program.

When trying to load the unmanaged EXE using Assembly.Load, I get a BadImageFormatException whose InnerException says that "the IL Format is incorrect" (obviously).

How can I make this work?

I know that using the code as a DLL would be better, but for some reason, the dll call does not behave the same way as when I run the unmanaged exe with System.Diagnostics.Process.Start.

And I don't want to have two separates EXE files. Any idea?


EDIT: OK, I no longer need to do that. My dll behaved a different way because I was using it in a different context (winform instead of console); therefore the function causing the problem, SetThreadDesktop, couldn't work as expected. Gonna close post now, thanks for all those who answered.

GianT971
  • 4,385
  • 7
  • 34
  • 46
  • What are you trying to use this unmanaged executable? Run it? You'd have to save the embedded EXE, maybe to the %TEMP% path, and use `Process.Start` to get it going. Then use `WaitForExit`, and delete the EXE to clean up. – vcsjones Mar 05 '12 at 16:51
  • That's a good idea indeed, but I'd rather have this work without generating the embedded EXE – GianT971 Mar 05 '12 at 17:00
  • 2
    You should be able to compile the C++ into a mixed-mode assembly, using the C++/CLI compiler, and link it with your C# code into a single file. – Ben Voigt Mar 05 '12 at 17:20

3 Answers3

3

You can't load an unmanaged exe/dll with Assembly.Load(), it works only with managed ones. if you need to PInvoke on that unmanaged file, and the reason you want a single exe is just deploy, you can pack it as an embedded resource (as you currently did ) and unpack on the target machine in a file, and use it as usual.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
2

If you have unmanaged DLL as resource - basic steps:

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • What do you mean by "Save resource to disk at run-time"? How do I do that?* – GianT971 Mar 05 '12 at 17:06
  • We have search engine for it :) - http://www.bing.com/search?q=Save+resource+to+disk+at+run-time , but here is one http://stackoverflow.com/questions/864140/write-file-from-assembly-resource-stream-to-disk – Alexei Levenkov Mar 05 '12 at 17:09
  • Ok and you think that this way the result could be different as just importing the dll to the project? – GianT971 Mar 05 '12 at 17:15
  • Not sure what do you mean "different" - you can't "import" native DLL to managed project. – Alexei Levenkov Mar 05 '12 at 17:26
  • @AlexeiLevenkov As spotted by Ramhound, it is possible to use dllimport, and that's what I was doing, thus the "different" – GianT971 Mar 06 '12 at 09:13
1

Slightly different approach, that could be automated, is using the so-called "assembly weaving" Costura.Fody - https://github.com/Fody/Costura - is the one of the 'weavers'. The embedding process (with tests automation) for incorporating unmanaged resources and transparently loading them at runtime without much of effort -

Install-Package Fody.Costura

Then all of embedding, unpacking, assembly locating and loading is automated by default, and controlled by including 'FodyWeavers.xml' config, added to your project.

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

The concept behind approach, is static <Module> class loader, that is binary changed by Fody project tasks, after your project assembly was successfully built. Internally Mono.Cecil is used for the static '<Module>' loader injection that unpacks resources automatically, saves them to temporary directory, telling to load dll's from that location, etc. at assembly load event.

valerysntx
  • 506
  • 3
  • 7