views:

248

answers:

3

Having a .NET assembly, how can I detect whether it was built for .NET CF or a full framework?

+1  A: 

The best bet would be to grab the C's include file header called winnt.h, found in your standard VS Professional (usually C:\Program Files\Microsoft Visual Studio 9.0\VC\include) and from there, load the .EXE into a PE Dumper of some sort, or use a Hex Dumper. 1. Look at the DOS HEader from offset 0x0. 2. The NT Header would immediately follow after the DOS header. 3. The Machine ID is what you are looking for. The machine ID for CF (ARM/MIPS) would be 0x010C/0x0169, respectively. If you wish to invest more time in poking around.. read on, 4. Then you have the Data directory immediately following after NT Header. It is the 15th data directory entry is the indication of whether the .EXE is .NET or not. If it is 0, then it is a native .EXE.

Combined together you can then tell if the executable is .NET and for the CF.

Look here for more details.

Hope this helps, Best regards, Tom.

tommieb75
I have checked two .NET libraries built for CF and both had Machine ID set to 0x014C (IMAGE_FILE_MACHINE_I386). I suppose it is because .NET files are not really device-specific -- there is not point in writing 'ARM' when they can transparently support MIPS/SH3/x86/etc.
Andrey Shchekin
@Andrey Shchekin: That is interesting as it seems that VS Pro would create an exe targetting the CF (arm/mips/sh3) and yet place Machine ID to the 386..Would that be a bug I wonder? Thanks for the interesting reply, that's surprised me because I didn't think that would happen! :)
tommieb75
I do not think it is a bug, since .NET CF exe files work on the x86/x64 as long as they do not use device-specific APIs.
Andrey Shchekin
+1  A: 

I rather use CCI or Cecil to parse its metadata and check out which set of references it depends on.

http://ccimetadata.codeplex.com/

http://www.mono-project.com/Cecil

Lex Li
There is mono.cecil tag on my question, for a purpose. :) But what should I look for? Assemblies I have looked at reference mscorlib and System.dll. Should I check for some specific version numbers? Are they definitely distinct between .NET and .NET CF?
Andrey Shchekin
Version number can be a significant indication, http://en.wikipedia.org/wiki/.NET_Compact_Framework http://en.wikipedia.org/wiki/.NET_Framework
Lex Li
+2  A: 

It's quite simple:

public enum AssemblyType
{
    CompactFramework,
    FullFramework,
    NativeBinary
}

public AssemblyType GetAssemblyType(string pathToAssembly)
{
    try
    {
        Assembly asm = Assembly.LoadFrom(pathToAssembly);
        var mscorlib = asm.GetReferencedAssemblies().FirstOrDefault(a => string.Compare(a.Name, "mscorlib", true) == 0);
        ulong token = BitConverter.ToUInt64(mscorlib.GetPublicKeyToken(), 0);

        switch (token)
        {
            case 0xac22333d05b89d96:
                return AssemblyType.CompactFramework;
            case 0x89e03419565c7ab7:
                return AssemblyType.FullFramework;
            default:
                throw new NotSupportedException();
        }
    }
    catch (BadImageFormatException)
    {
        return AssemblyType.NativeBinary;
    }
}
ctacke
Thanks. I thought about this solution, but I was worried whether public keys are same for all versions of CF. But knowing your knowledge of CF, I assume they are, so I'll use this.
Andrey Shchekin
They are all the same. We use similar techniques in code for the control designer. If we're creating against the full framework key, we know we're in design time (or being created on teh desktop anyway).
ctacke