استرداد معلومات إصدار DLL عبر Win32 - تعطل VerqueryValue (...) بموجب Win7 x64

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

سؤال

تطبيق Wrapper مفتوح المصدر المحترم (Sharpbits) من خدمات البتات Windows يفشل في تحديد نسخة البتات الأساسية بموجب WIN7 X64.

هنا هو رمز المصدر الذي يفشل. Nativemethods هي مكالمات Win32 الأصلية ملفوفة بواسطة أساليب .NET ومزينة عبر سمة Dllimport.

private static BitsVersion GetBitsVersion()
    {
        try
        {
            string fileName = Path.Combine(
                     System.Environment.SystemDirectory, "qmgr.dll");
            int handle = 0;
            int size = NativeMethods.GetFileVersionInfoSize(fileName, 
                                                            out handle);
            if (size == 0) return BitsVersion.Bits0_0;
            byte[] buffer = new byte[size];
            if (!NativeMethods.GetFileVersionInfo(fileName, 
                                                  handle, 
                                                  size, 
                                                  buffer))
            {
                return BitsVersion.Bits0_0;
            }
            IntPtr subBlock = IntPtr.Zero;
            uint len = 0;
            if (!NativeMethods.VerQueryValue(buffer,
                              @"\VarFileInfo\Translation", 
                              out subBlock, 
                              out len))
            {
                return BitsVersion.Bits0_0;
            }

            int block1 = Marshal.ReadInt16(subBlock);
            int block2 = Marshal.ReadInt16((IntPtr)((int)subBlock + 2 ));
            string spv = string.Format(
                 @"\StringFileInfo\{0:X4}{1:X4}\ProductVersion", 
                 block1, 
                 block2);

            string versionInfo;
            if (!NativeMethods.VerQueryValue(buffer, 
                                             spv, 
                                             out versionInfo, 
                                             out len))
            {
                return BitsVersion.Bits0_0;
            }
...

يتبع التنفيذ تعليمات MSDN بالرسالة. لا يزال خلال مكالمة verqueryvalue الثانية (...) ، تعطل التطبيق و يقتل جلسة التصحيح بدون تردد. فقط المزيد من معلومات التصحيح مباشرة قبل الحادث:

  • spv => " stringfileinfo 040904B0 ProductVersion"
  • المخزن المؤقت => بايت [1900] - كامل مع البيانات الثنائية
  • block1 => 1033
  • block2 => 1200

نظرت إلى ملف "C: Windows System32 qmgr.dll" (تطبيق البتات) عبر Windows. تقول أن إصدار المنتج هو 7.5.7600.16385. بدلاً من التعطل ، يجب أن تعود هذه القيمة في سلسلة VerionInfo. اي نصيحه؟

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

المحلول 3

تشير إجابة Nobugz إلى قضية صالحة للغاية (Big Umanx لذلك!) ، لكن القاتل النهائي كان خطأ. NET: فشل الأوتار في هذا السيناريو في إطار تطبيق X64 .NET. تم إصلاح الخطأ في .NET4.0. إليكم المشكلة المبلغ عنها ، وكذلك إجابة Microsoft.

يتم استرجاع الحل البديل الموصى به من INTPTR بدلاً من السلسلة كإخراج وإلزام السلسلة يدويًا. لذلك الرمز النهائي (بما في ذلك إصلاح نوبوجز):

int block1 = Marshal.ReadInt16(subBlock);
int block2 = Marshal.ReadInt16(subBlock, 2);
string spv = string.Format(@"\StringFileInfo\{0:X4}{1:X4}\ProductVersion", 
                             block1, block2);

IntPtr versionInfoPtr;
if (!NativeMethods.VerQueryValue(buffer, spv, out versionInfoPtr, out len))
{
     return BitsVersion.Bits0_0;
}
string versionInfo = Marshal.PtrToStringAuto(versionInfoPtr);

نصائح أخرى

لا أعرف ما إذا كان هناك خطأ ما في الكود الخاص بك ، لكن هل فكرت في استخدام FileVersionInfo فئة بدلا من P/استدعاء مكالمات API؟ إنه أسهل في الاستخدام وأقل خطأ في الخطأ ...

نظرت إلى Sharpbits منذ حوالي عام. أتذكر أنني رأيت خطأ كبيرًا في ذلك الوقت مما يجعله غير مناسب على أنظمة التشغيل 64 بت. لا يمكنني تذكر الخلل الدقيق ، وربما إعلان P سيئ/استدعاء. مقتطف الرمز هذا خاطئ بالتأكيد:

int block2 = Marshal.ReadInt16((IntPtr)((int)subBlock + 2 ));

لا يمكن إلقاء intptr إلى int في وضع x64. يجب أن تبدو هكذا:

int block2 = Marshal.ReadInt16((IntPtr)((long)subBlock + 2 ));

أو أفضل بكثير:

int block2 = Marshal.ReadInt16(subBlock, 2); 

أوصي بشدة بإجبار تطبيقك على التشغيل في وضع 32 بت إذا كنت تستخدم هذه المكتبة لتجنب هذه المشكلات. Project + Properties ، Tab Build ، Target Flatuty = x86. يمكنك إخطار المؤلف هنا.

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