تحقق مما إذا كان DLL غير المدارة هو 32 بت أو 64 بت؟

StackOverflow https://stackoverflow.com/questions/1001404

  •  05-07-2019
  •  | 
  •  

سؤال

وكيف يمكنني معرفة برمجيا في C # إذا كان <م> غير المدارة ملف DLL هو إلى x86 أو إلى x64؟

هل كانت مفيدة؟

المحلول

المواصفات . وهنا تنفيذ الأساسي:

public static MachineType GetDllMachineType(string dllPath)
{
    // See http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
    // Offset to PE header is always at 0x3C.
    // The PE header starts with "PE\0\0" =  0x50 0x45 0x00 0x00,
    // followed by a 2-byte machine type field (see the document above for the enum).
    //
    FileStream fs = new FileStream(dllPath, FileMode.Open, 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");

    MachineType machineType = (MachineType) br.ReadUInt16();
    br.Close();
    fs.Close();
    return machineType;
}

ويتم تعريف التعداد MachineType على النحو التالي:

public enum MachineType : ushort
{
    IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
    IMAGE_FILE_MACHINE_AM33 = 0x1d3,
    IMAGE_FILE_MACHINE_AMD64 = 0x8664,
    IMAGE_FILE_MACHINE_ARM = 0x1c0,
    IMAGE_FILE_MACHINE_EBC = 0xebc,
    IMAGE_FILE_MACHINE_I386 = 0x14c,
    IMAGE_FILE_MACHINE_IA64 = 0x200,
    IMAGE_FILE_MACHINE_M32R = 0x9041,
    IMAGE_FILE_MACHINE_MIPS16 = 0x266,
    IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
    IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
    IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
    IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
    IMAGE_FILE_MACHINE_R4000 = 0x166,
    IMAGE_FILE_MACHINE_SH3 = 0x1a2,
    IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
    IMAGE_FILE_MACHINE_SH4 = 0x1a6,
    IMAGE_FILE_MACHINE_SH5 = 0x1a8,
    IMAGE_FILE_MACHINE_THUMB = 0x1c2,
    IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
}

وأنا في حاجة فقط ثلاثة من هذه، لكنني شملت كل منهم للتأكد من اكتمالها. النهائي الاختيار 64-بت:

// Returns true if the dll is 64-bit, false if 32-bit, and null if unknown
public static bool? UnmanagedDllIs64Bit(string dllPath)
{
    switch (GetDllMachineType(dllPath))
    {
        case MachineType.IMAGE_FILE_MACHINE_AMD64:
        case MachineType.IMAGE_FILE_MACHINE_IA64:
            return true;
        case MachineType.IMAGE_FILE_MACHINE_I386:
            return false;
        default:
            return null;
    }
}

نصائح أخرى

وباستخدام الأوامر Visual Studio موجه، DUMPBIN / رؤوس dllname.dll يعمل أيضا. على الجهاز الخاص بي بداية الانتاج وقالت:

FILE HEADER VALUES
8664 machine (x64)
5 number of sections
47591774 time date stamp Fri Dec 07 03:50:44 2007

وحتى أسهل: تحقق من الطبقة System.Reflection.Module. ويشمل طريقة GetPEKind، والتي ترجع 2 تتضمن التعدادات التي تصف نوع من رمز والهدف وحدة المعالجة المركزية. لا مزيد من عرافة!

و(تم نسخ بقية هذا المنصب مفيدة للغاية دون خجل من HTTP : //www.developersdex.com/vb/message.asp ع = 2924 & R = 6413567 )

ونموذج التعليمات البرمجية:

Assembly assembly = Assembly.ReflectionOnlyLoadFrom(@"<assembly Path>");
PortableExecutableKinds kinds;
ImageFileMachine imgFileMachine;
assembly.ManifestModule.GetPEKind(out kinds, out imgFileMachine);

وPortableExecutableKinds يمكن استخدامها للتحقق من أي نوع من التجمع. هذا لديها 5 القيم:

وILOnly: القابل للتنفيذ يحتوي فقط على مايكروسوفت لغة وسيطة (MSIL)، وبالتالي فهي محايدة فيما يتعلق 32 بت أو 64 بت المنصات.

وNotAPortableExecutableImage: الملف ليس في تنفيذ المحمولة (PE) تنسيق الملف.

وPE32Plus: القابل للتنفيذ يتطلب منصة 64 بت

.

وRequired32Bit: يمكن تشغيل قابل للتنفيذ على منصة 32 بت، أو في ويندوز 32 بت على نظام التشغيل Windows (WOW) البيئة على منصة 64 بت.

وUnmanaged32Bit: القابل للتنفيذ يحتوي على التعليمات البرمجية غير المدارة النقي

.

وفيما يلي الروابط:

وModule.GetPEKind الطريقة: http://msdn.microsoft.com/en- لنا / مكتبة / system.reflection.module.getpekind.aspx

وPortableExecutableKinds التعداد: http://msdn.microsoft.com /en-us/library/system.reflection.portableexecutablekinds(VS.80).aspx

وImageFileMachine التعداد: http://msdn.microsoft.com/en-us/ مكتبة / system.reflection.imagefilemachine.aspx

وبدلا من Assembly.LoadFile، واستخدام Assembly.ReflectionOnlyLoadFrom. هذا وسوف تتيح لك العمل حول الاستثناءات "تنسيق صورة سيئة".

وأنا أعلم أنها كانت منذ بعض الوقت تم تحديث هذا. وكنت قادرا على الابتعاد مع استثناءات "تنسيق صورة سيئة" عن طريق تحميل الملف إلى انها AppDomain الخاص.

        private static (string pkName, string imName) FindPEKind(string filename)
    {
        // some files, especially if loaded into memory
        // can cause errors. Thus, load into their own appdomain
        AppDomain tempDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
        PEWorkerClass remoteWorker =
            (PEWorkerClass)tempDomain.CreateInstanceAndUnwrap(
                typeof(PEWorkerClass).Assembly.FullName,
                typeof(PEWorkerClass).FullName);

        (string pkName, string imName) = remoteWorker.TryReflectionOnlyLoadFrom_GetManagedType(filename);

        AppDomain.Unload(tempDomain);
        return (pkName, imName);
    }

وعند هذه النقطة، I القيام بما يلي:

        public (string pkName, string imName) TryReflectionOnlyLoadFrom_GetManagedType(string fileName)
    {
        string pkName;
        string imName;
        try
        {
            Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFile: fileName);
            assembly.ManifestModule.GetPEKind(
                peKind: out PortableExecutableKinds peKind,
                machine: out ImageFileMachine imageFileMachine);

            // Any CPU builds are reported as 32bit.
            // 32bit builds will have more value for PortableExecutableKinds
            if (peKind == PortableExecutableKinds.ILOnly && imageFileMachine == ImageFileMachine.I386)
            {
                pkName = "AnyCPU";
                imName = "";
            }
            else
            {
                PortableExecutableKindsNames.TryGetValue(
                    key: peKind,
                    value: out pkName);
                if (string.IsNullOrEmpty(value: pkName))
                {
                    pkName = "*** ERROR ***";
                }

                ImageFileMachineNames.TryGetValue(
                    key: imageFileMachine,
                    value: out imName);
                if (string.IsNullOrEmpty(value: pkName))
                {
                    imName = "*** ERROR ***";
                }
            }

            return (pkName, imName);
        }
        catch (Exception ex)
        {
            return (ExceptionHelper(ex), "");
        }
    }

وتشغيل هذا ضد بلدي الأرامل \ دليل الجمعية يعطيني أخطاء الصفر مع أكثر من 3600 الملفات المعالجة. ملاحظة: يمكنني استخدام القاموس لتحميل القيم التي يتم إرجاعها

وآمل أن يساعد. YMMV

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top