views:

455

answers:

3

Hey everyone,

I have a .Net app that's compiled as "Any CPU". I am running it on a x64 OS so it's running as 64bit. The application loads other assemblies that the user provides. It uses reflection of course to read types from the user provided assembly. Everything works fine if the user assembly is compiled as "Any CPU". But if the assembly is compiled as x86, I get the "this is not a Win32 application" exception at reflection time. It's obviously due to the fact that the host app is running 64bit.

My question is, how can I work around this? Any thoughts/ideas?

Thanks

A: 

You could copy the file and change the bit.

Joshua
A: 

If you only need to load it for reflective purposes you can use the Mono.Cecil which I think should be fine with it.

Alternatively grab a copy of the dll, run corflags against the file to flip the 32bit only flag and then load the copy.

The first is much better and faster for just reflecting, never wanting to actually instantiate a type but inherently more effort. The second is error prone (the dll may have dependencies on unmanaged code which, when triggered via the reflection scan, will fail no matter what.

As a third, alternate option to sidestep the issue. Just force your app to run as 32bit only, then it should load everything just fine. Do you really have to run 64bit?

ShuggyCoUk
If I run 32bit, I will run into issues with assemblies that are 64bit which are a case I have as well. I might try loading with ReflectionOnly and see if that works. All I need to do is just reflect over the assembly to read types. I don't actually execute anything. Well...I do need to look up attributes, so that may be an issue since looking it up executes it :/
Nazeeh
A 64bit only .Net assembly is incredibly rare in my experience, they are almost always mixed mode. You may be doing work that uses them but consider if you need to bother. Reading types/attributes is something Cecil will do for you so I suggest you go that route...
ShuggyCoUk
+2  A: 

Ok. I figured it out. For my purposes, which were just a simple type discovery for an assembly but no instantiation, using Assembly.ReflectionOnlyLoad works if the assembly is 32bit.

You load the assembly with Assembly.ReflectionOnlyLoad and you are allowed to reflect on the types. You should hook to the AppDomain.CurrentDomain.ReflectionOnlyLoadResolve as well.

To get Attribute names, you need to use CustomAttributeData.GetCustomAttributes on a type, method or module.

 static void Main(string[] args)
    {
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
        Assembly assm = Assembly.ReflectionOnlyLoadFrom("TestProject1.dll");

        Type t = assm.GetType("TestProject1.ProgramTest");
        MethodInfo m = t.GetMethod("MainTest");

        IList<CustomAttributeData> data = CustomAttributeData.GetCustomAttributes(t);


    }

    static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
    {
        return Assembly.ReflectionOnlyLoad(args.Name);
    }
Nazeeh
That's good to know
ShuggyCoUk