如何确定.net exe的平台标签

时间:2010-10-01 23:25:45

标签: .net

当我编译一个.net程序时,我可以告诉它为/ platform编译:anycpu或/ platform:x86等。有什么办法可以确定.net exe / dll编译的平台值是什么?

请参阅下面的答案,了解确定平台标志的程序。或者使用corflags.exe。

3 个答案:

答案 0 :(得分:4)

看看CorFlags.exe。它允许您查看.NET程序集的PE和32BIT标志。

编辑:this page有关于如何解释CorFlags输出的更多信息。

答案 1 :(得分:2)

这可能有助于可执行文件:

http://www.mitec.cz/exe.html

如果您需要以编程方式检查.net dll,那么有以下帖子:

How to find if a native DLL file is compiled as x64 or x86?

Check if unmanaged DLL is 32-bit or 64-bit?

答案 2 :(得分:1)

使用Luke和Marty的答案中的信息我能够做到这一点。这是我编写的控制台程序,它检查程序集是否使用指定的平台进行编译。它很乱,因为我还没有清理它,但它确实有用。

using System;
using System.IO;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace MyApp
{
    static class App
    {
        [STAThread]
        static void Main(string[] args)
        {
            if (args.GetUpperBound(0) != 1)
            {
                Console.WriteLine("Usage:");
                Console.WriteLine("  checkPlatform [anycpu|x86|x64] filename");
                return;
            }
            CheckPlatform(args[0], args[1]);
        }

        public static bool CheckPlatform(string targetPlatform, string filename)
        {
            //see http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
            //offset to PE header is always at 0x3C
            //PE header starts with "PE\0\0" =  0x50 0x45 0x00 0x00
            //followed by 2-byte machine type field (see document above for enum)
            FileStream fs = new FileStream(filename, FileMode.Open, System.IO.FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            fs.Seek(0x3c, SeekOrigin.Begin);
            Int32 peOffset = br.ReadInt32();
            fs.Seek(peOffset, SeekOrigin.Begin);
            UInt32 peHead = br.ReadUInt32();

            if(peHead!=0x00004550) // "PE\0\0", little-endian
                throw new Exception("Can't find PE header");
            int machineType = (int) br.ReadUInt16(); // The number that identifies the type of target machine.
            int numberOfSections = (int)br.ReadUInt16(); // The number of sections. This indicates the size of the section table, which immediately follows the headers.
            int timeDateStamp = (int)br.ReadUInt32(); // The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created.
            int pointerToSymbolTable = (int)br.ReadUInt32(); // The file offset of the COFF symbol table, or zero if no COFF symbol table is present. This value should be zero for an image because COFF debugging information is deprecated.
            int numberOfSymbols = (int)br.ReadUInt32(); // The number of entries in the symbol table. This data can be used to locate the string table, which immediately follows the symbol table. This value should be zero for an image because COFF debugging information is deprecated.
            int sizeOfOptionalHeader = (int)br.ReadUInt16(); // The size of the optional header, which is required for executable files but not for object files. This value should be zero for an object file. For a description of the header format, see section 3.4, “Optional Header (Image Only).”
            int characteristics = (int)br.ReadUInt16(); // The flags that indicate the attributes of the file. For specific flag values, see section 3.3.2, “Characteristics.”
            int sectionoffset = (int)fs.Position + sizeOfOptionalHeader;
            int magic = (int)br.ReadUInt16();

        /*
Now we are at the end of the PE Header and from here, the
            PE Optional Headers starts...
    To go directly to the datadictionary, we'll increase the
    stream’s current position to with 96 (0x60). 96 because,
            28 for Standard fields
            68 for NT-specific fields
From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total,
doing simple maths 128/16 = 8.
So each directory is of 8 bytes.
            In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size.

btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :)
            */
            ushort dataDictionaryStart;
            uint[] dataDictionaryRVA = new uint[16];
            uint[] dataDictionarySize = new uint[16];

            dataDictionaryStart = Convert.ToUInt16 (Convert.ToUInt16(fs.Position) + 0x60);
            fs.Position = dataDictionaryStart - 2;
            for (int i = 0; i < 15; i++)
            {
                dataDictionaryRVA[i] = br.ReadUInt32();
                dataDictionarySize[i] = br.ReadUInt32();
            }
            if (dataDictionaryRVA[14] == 0)
            {
                MessageBox.Show("This is NOT a valid CLR File!!");
                return false;
            }

            fs.Position = sectionoffset;

            int[] SVirtualAddress = new int[numberOfSections];
            int[] SSizeOfRawData = new int[numberOfSections];
            int[] SPointerToRawData = new int[numberOfSections];

            for ( int i = 0 ; i <numberOfSections; i++)
            {
                br.ReadBytes(12);
                SVirtualAddress[i] = br.ReadInt32();
                SSizeOfRawData[i] = br.ReadInt32();
                SPointerToRawData[i] = br.ReadInt32();
                br.ReadBytes(16);
            }

            fs.Position = ConvertRVA(numberOfSections, SVirtualAddress, SSizeOfRawData, SPointerToRawData, dataDictionaryRVA[14]);
            int size = br.ReadInt32();
            int majorruntimeversion = br.ReadInt16();
            int minorruntimeversion = br.ReadInt16();
            int metadatarva = br.ReadInt32();
            int metadatasize = br.ReadInt32();
            int corflags = br.ReadInt32();
            br.Close();
            fs.Close();

            bool is32bit = false;
            if ((characteristics & 0x0100) == (0x0100)) is32bit = true;
            string s = "";
            if (magic == 0x10b) s += "Magic=PE\r\n"; else
            if (magic == 0x20b) s += "Magic=PE+\r\n"; else
            s += "Magic=" + magic.ToString("X") + "\r\n";
            s += "machineType=" + machineType.ToString() + "\r\n";
            s += "is32bit=" + is32bit.ToString() + "\r\n";
            s += "numberOfSections=" + numberOfSections.ToString() + "\r\n";
            s += "sizeOfOptionalHeader=" + sizeOfOptionalHeader.ToString() + "\r\n";
            s += "Characteristics=" + characteristics.ToString() + "\r\n";
            s += "corflags=" + corflags.ToString("X") + "\r\n";

//·         anycpu: PE = PE32    and  32BIT = 0
//·         x86:      PE = PE32    and  32BIT = 1
//·         64-bit:  PE = PE32+  and  32BIT = 0
            if ((corflags & 2) == 2) is32bit = true; else is32bit = false;
            string platform = "Unknown";
            if (magic == 0x10b)
            {
                // PE32
                if (is32bit) platform = "x86"; else platform = "anycpu";
            } else
            if (magic == 0x20b)
            {
                // PE32+
                if (is32bit == false) platform = "x64";
            }

            if (platform.ToUpper() != targetPlatform.ToUpper())
            {
                MessageBox.Show(filename + " is " + platform + ", not " + targetPlatform + ".\r\n" + s);
                return false;
            }

            return true;
        }

        public static long ConvertRVA(int numberOfSections, int[] SVirtualAddress, int[] SSizeOfRawData, int[] SPointerToRawData, long rva)
        {
            int i;
            for ( i = 0 ; i <numberOfSections; i++)
            {
                if ( rva >= SVirtualAddress [i]  && ( rva <  SVirtualAddress[i] + SSizeOfRawData [i] ))
                break ;
            }
            return SPointerToRawData [i] + ( rva - SVirtualAddress[i] );
        }
    }
}