2

I have been testing out some few things with VS2013 Native Tools Command Prompt.

So far, I couldn't get my code to load dlls that I made.

Here is my dll code, written in c. (Based on msdn example)

int __declspec(dllexport) SampleMethod(int i){return i*-10;} 

And compiled it with cl /LD in VS2013 Native Tools.

Then I compiled my c# code with csc in VS2013 Native Tools.

public class MainClass
{
    static void Main(string[] args)
    {
        Assembly assembly;
        try
        {
            assembly = Assembly.Load(args[0]);
            Console.WriteLine("Loaded dll");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception caught : \n{0}.", e);
        }
    }    
}

And the exception caught goes as :

Exception caught :
System.BadImageFormatException: Could not load file or assembly 'test' or one of
 its dependencies. The module was expected to contain an assembly manifest.
File name: 'test'
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String cod
eBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&
stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntro
spection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName as
semblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMar
k& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIn
trospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evid
ence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolea
n forIntrospection)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evid
ence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at MainClass.Main(String[] args)

I have tried in both x86 and x64 tools and now I'm out of ideas.

Cœur
  • 37,241
  • 25
  • 195
  • 267
revolute
  • 33
  • 3

1 Answers1

3

Assembly.Load can only load managed (.NET) assemblies. You're trying to load a native DLL, producing the error.

Instead, you want to use P/Invoke. This will only work for plain C-style methods, if you need to work with e.g. C++ classes, you need to make an interop library first.

The signature of the P/Invoke method for your case would look something like this:

[DllImport("test.dll")]
public static extern int SampleMethod(int i);
Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Then how would I try to read other methods that I am not aware of? – revolute Oct 30 '14 at 08:46
  • *Then how would I try to read other methods that I am not aware of?* Presumably you're aware of them in some way. Otherwise you wouldn't be asking this question... – ta.speot.is Oct 30 '14 at 08:47
  • I mean to look into a dll and see what methods it contains. Some kind of dll export viewer. – revolute Oct 30 '14 at 08:49
  • @revolute Yeah, that's a lot more trickier. P/Invoking includes automatic generation of marshalling code, which you can't do easily in runtime. It might be doable by creating a dynamic class with the appropriate `DllImport`s, but I never tried that. Otherwise, you're stuck with either a C++/CLI helper library, or manually working with the various `LoadLibrary` WinAPI methods (probably a bad idea). Of course, you always need at least the method definitions - native DLLs aren't self-descriptive the way managed are. – Luaan Oct 30 '14 at 08:49
  • I suppose my journey would be a hard one. As I can find dll viewers , there must be a way. Anyhow, thanks for the answer. – revolute Oct 30 '14 at 08:53
  • @revolute To expand a bit more, C-style methods are only identified by their name - you need to know their signature to be able to call them properly. C++-style methods are a bit more descriptive, because of name mangling - so you get method names like `Foo@@YGHHH@Z`. In any case, this isn't usually enough anyway - you need to know the contract by which you should handle the parameters - most importantly, who takes care of managing the memory, what kind of pointer you need to pass etc. – Luaan Oct 30 '14 at 08:53
  • @revolute Well, making a managed DLL viewer is very simple (that's your `Assembly.Load`. You can see everything that's in the library, including private methods etc. This is not the case for native libraries. Only exports are published, and even then, with hardly any meta-data. C-style methods only really export the name and parameter length (e.g. your method would be exported as `SampleMethod@8` or something like that). C++ is better, but it still only allows you to see the types of the parameters, missing a lot of the necessary information. – Luaan Oct 30 '14 at 08:56
  • Also note that the naming scheme can and will be different for different C and C++ compilers, especially with C++. The scheme I used as a sample is used by MSVC++, but that's just one of the ways. The truth is, the information just isn't there. You can usually retrieve enough by manually decompiling bits of the library code and trying to understand what's happening, but that requires rather significant knowledge about assembly, C, C++ etc. The point is, native DLLs aren't self-descriptive enough. You need the header files, and you need API documentation. – Luaan Oct 30 '14 at 08:58
  • @Luaan I guess I can start from getting method names and make my way back. Thanks again for your explanation. – revolute Oct 30 '14 at 09:01