لا يعمل التطبيق مع VS 2008 SP1 DLLs، الإصدار السابق يعمل مع إصدارات RTM

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

  •  09-06-2019
  •  | 
  •  

سؤال

منذ تحولنا من Visual Studio 6 إلى Visual Studio 2008، كنا نستخدم MFC90.dll وmsvc[pr]90.dlls بالإضافة إلى ملفات البيان في تكوين خاص جنبًا إلى جنب حتى لا تقلق بشأن الإصدارات أو تثبيتها على النظام.

قبل الإصدار SP1، كان هذا يعمل بشكل جيد (ولا يزال يعمل بشكل جيد على أجهزة المطورين لدينا).الآن وبعد أن قمنا ببعض الاختبارات بعد SP1، فقد قمت بسحب شعري منذ صباح الأمس.

أولاً، يقوم برنامج التثبيت NSIS الخاص بنا بسحب ملفات dlls وملفات البيان من مجلد redist.لم تعد هذه صحيحة، حيث لا يزال التطبيق يرتبط بإصدار RTM.

لذلك أضفت التعريف لـ _BIND_TO_CURRENT_VCLIBS_VERSION=1 لجميع مشاريعنا حتى يتمكنوا من استخدام ملفات SP1 DLL الموجودة في مجلد redist (أو تلك اللاحقة عند ظهور حزم الخدمة الجديدة).استغرق الأمر مني ساعات للعثور على هذا.

لقد قمت بالتحقق مرة أخرى من ملفات البيان التي تم إنشاؤها في مجلد الملفات الوسيطة من التجميع، وقد قامت بإدراج إصدارات 9.0.30729.1 SP1 بشكل صحيح.لقد قمت بإجراء فحص مزدوج وثلاثي يعتمد على جهاز نظيف:كل ذلك يرتبط بملفات dll المحلية دون أي أخطاء.

لا يزال تشغيل التطبيق يحصل على الخطأ التالي:

فشل التطبيق في التهيئة بشكل صحيح (0xc0150002).انقر على موافق لإنهاء التطبيق.

لم تتوصل أي من عمليات البحث التي أجريتها على Google أو Microsoft إلى أي شيء يتعلق بمشكلاتي المحددة (ولكن هناك نتائج تعود إلى عام 2005 مع رسالة الخطأ هذه).

هل كان لدى أحد أي مشكلة مماثلة مع SP1؟

خيارات:

  • ابحث عن المشكلة وقم بإصلاحها حتى تعمل كما ينبغي (مفضل)
  • تثبيت ريديست
  • استخرج ملفات RTM dlls وملفات البيان القديمة وقم بإزالة #define لاستخدام الملفات الحالية.(لقد حصلت عليها في إصدار سابق من برنامج التثبيت، حيث قامت Microsoft بإزالتها من مجلد redist الخاص بك!)

يحرر: لقد حاولت إعادة البناء مع إيقاف تشغيل التعريف (رابط إلى ملفات RTM dlls)، ويعمل ذلك طالما تم تثبيت ملفات RTM dlls في المجلد.إذا تم إسقاط ملفات dll الخاصة بحزمة الخدمة SP1، فسيحصل على الخطأ التالي:

c:\ملفات البرنامج\...\...\X.exe

فشل هذا التطبيق في البدء لأن تكوين التطبيق غير صحيح.إعادة تثبيت التطبيق قد حل هذه المشكلة.

هل لم يكن على أي شخص آخر التعامل مع هذه المشكلة؟

يحرر: فقط للابتسامات، قمت بتنزيل vcredist_x86.exe لـ VS2008SP1 وتشغيله على جهاز الاختبار الخاص بي. هو - هي يعمل.مع مكتبات الارتباط الحيوي (DLL) SP1.وتطبيقي المرتبط بـ RTM.لكن لا في توزيع خاص جنبًا إلى جنب كان يعمل قبل حزمة الخدمة SP1.

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

المحلول

لقد واجهت هذه المشكلة بنفسي الأسبوع الماضي وأعتبر نفسي خبيرًا إلى حد ما الآن؛)

أنا متأكد بنسبة 99% من أنه لم تتم إعادة ترجمة كافة ملفات dll والمكتبات الثابتة باستخدام إصدار SP1.تحتاج إلى وضع

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

داخل كل المشروع الذي تستخدمه.بالنسبة لكل مشروع ذي حجم حقيقي، من السهل جدًا أن تنسى بعض الـ lib الصغيرة التي لم تتم إعادة ترجمتها.

هناك المزيد من العلامات التي تحدد الإصدارات التي يجب الارتباط بها؛تم توثيقه على http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx .كبديل للأسطر أعلاه، يمكنك أيضا وضع

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

والتي سيتم ربطها بأحدث إصدار من جميع VC libs (CRT، MFC، ATL، OpenMP).

ثم تحقق مما يقوله البيان المضمن.تنزيل محرر موارد XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.افتح كل ملف dll وexe في الحل الخاص بك.انظر ضمن "بيان سمة XP".تأكد من أن سمة "الإصدار" الموجودة على الجانب الأيمن هي "9.0.30729.1".إذا كان "9.0.21022"، فإن بعض المكتبات الثابتة تقوم بسحب البيان الخاص بالإصدار القديم.

ما وجدته هو أنه في كثير من الحالات، كلاهما تم تضمين الإصدارات في البيان.وهذا يعني أن بعض المكتبات تستخدم إصدار sp1 والبعض الآخر لا يستخدمه.

طريقة رائعة لتصحيح المكتبات التي لا تحتوي على مجموعة توجيهات المعالج المسبق:قم بتعديل رؤوس النظام الأساسي الخاص بك مؤقتًا بحيث يتوقف التجميع عندما يحاول تضمين البيان القديم.افتح C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.ابحث عن السلسلة "21022".في هذا التعريف، ضع شيئًا غير صالح (قم بتغيير "تعريف" إلى "blehbleh" أو نحو ذلك).بهذه الطريقة، عندما تقوم بتجميع مشروع حيث يكون ملف _BIND_TO_CURRENT_CRT_VERSION لم يتم تعيين علامة المعالج المسبق، وسيتوقف التجميع الخاص بك وستعرف أنك بحاجة إلى إضافتها أو التأكد من تطبيقها في كل مكان.

تأكد أيضًا من استخدام Dependency Walker حتى تعرف ما هي ملفات dll التي يتم سحبها.من الأسهل تثبيت نسخة جديدة من Windows XP بدون تحديثات (فقط SP2) على جهاز ظاهري.بهذه الطريقة ستعرف على وجه اليقين أنه لا يوجد شيء في مجلد SxS يتم استخدامه بدلاً من ملفات dll التي قدمتها جنبًا إلى جنب.

نصائح أخرى

لفهم المشكلة، أعتقد أنه من المهم أن ندرك أن هناك أربعة أرقام الإصدار المعنية:

  • (أ) إصدار ملفات رأس VC التي تم تجميع الملف exe.
  • (ب) إصدار ملف البيان المضمن في قسم الموارد في ملف exe.افتراضيًا، يتم إنشاء ملف البيان هذا تلقائيًا بواسطة Visual Studio.
  • (ج) إصدار ملفات VC .DLL (جزء من التجميع جنبًا إلى جنب) الذي تنسخه في نفس الدليل مثل ملف .exe.
  • (د) إصدار ملفات بيان VC (جزء من التجميع جنبًا إلى جنب) الذي تنسخه في نفس الدليل مثل ملف exe.

يوجد إصداران من ملفات VC 2008 DLL قيد التشغيل:

  • الإصدار 1:9.0.21022.8
  • الإصدار الثاني:9.0.30729.4148

من أجل الوضوح، سأستخدم تدوين v1/v2.ويبين الجدول التالي عددا من الحالات المحتملة:

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

نتائج هذه المواقف عند تشغيل ملف .exe على تثبيت نظيف لنظام التشغيل Vista SP1 هي:

  • الوضع 1:تظهر نافذة منبثقة تقول:"تعذر تحديد موقع نقطة إدخال الإجراء XYZXYZ في مكتبة الارتباط الديناميكي".

  • الوضع 2:لا يبدو أن شيئًا يحدث عند تشغيل ملف exe.، ولكن يتم تسجيل الحدث التالي في "سجل الأحداث/التطبيقات" الخاص بنظام التشغيل Windows:

    فشل إنشاء سياق التنشيط لـ "C:\Path\file.exe". حدث خطأ في ملف البيان أو ملف السياسة "C:\Path\Microsoft.VC90.CRT.MANIFEST" في السطر 4.هوية المكون الموجودة في البيان لا تتطابق مع هوية المكون المطلوب.المرجع هو Microsoft.VC90.CRT،processorArchitecture = "x86"، publicKeyToken = "1fc8b3b9a1e18e3b"، type = "win32"، الإصدار = "9.0.21022.8".التعريف هو مايكروسوفت

  • الوضع 3:يبدو أن كل شيء يعمل بشكل جيد.هذا هو حل remicles2.

  • الوضع 4:هذا هو كيف ينبغي أن يتم ذلك.ولكن من المؤسف، كما يشير رويل، أنه قد يكون من الصعب تنفيذه إلى حد ما.

الآن، وضعي (وأعتقد أنه هو نفسه Crashmstr's) هو رقم 1.المشكلة هي أن Visual Studio لسبب أو لآخر يقوم بإنشاء رمز العميل (A) للإصدار 2، ولكن لسبب أو لآخر، يقوم بإنشاء ملف البيان v1 (B).ليس لدي أي فكرة عن المكان الذي يمكن تكوين الإصدار (A).

ملحوظة أن هذا التفسير كله لا يزال في سياق التجمعات الخاصة.

تحديث:أخيرًا بدأت أفهم ما يحدث.فيما يبدو، يقوم Visual Studio بإنشاء رمز العميل (A) للإصدار 2 بشكل افتراضي, على عكس ما قرأته في بعض مدونات مايكروسوفت.تحدد علامة _BIND_TO_CURRENT_VCLIBS_VERSION فقط الإصدار الموجود في ملف البيان الذي تم إنشاؤه (B)، ولكن سيتم تجاهل هذا الإصدار عند تشغيل التطبيق.

خاتمة

يرتبط ملف .exe الذي تم تجميعه بواسطة Visual Studio 2008 بالإصدارات الأحدث من ملفات VC90 DLL بشكل افتراضي.أنت تستطيع استخدم علامة _BIND_TO_CURRENT_VCLIBS_VERSION للتحكم في إصدار مكتبات VC90 الذي سيتم إنشاؤه في ملف البيان.يؤدي هذا بالفعل إلى تجنب الموقف 2 حيث تتلقى رسالة الخطأ "البيان لا يتطابق مع هوية المكون المطلوب".ويوضح أيضًا سبب عمل الموقف 3 بشكل جيد، لأنه حتى بدون علامة _BIND_TO_CURRENT_VCLIBS_VERSION، يكون التطبيق مرتبطًا بأحدث الإصدارات من ملفات VC DLLs.

يكون الوضع أكثر غرابة مع التجميعات العامة جنبًا إلى جنب، حيث تم تشغيل vcredist، مما يضع ملفات VC 9.0 DLL في دليل Windows SxS.حتى إذا كان ملف البيان .exe ينص على ضرورة استخدام الإصدارات القديمة من مكتبات الارتباط الحيوي (DLL) (هذه هي الحالة عندما لا يتم تعيين علامة _BIND_TO_CURRENT_VCLIBS_VERSION)، فإن Windows يتجاهل رقم الإصدار هذا بشكل افتراضي!بدلاً من ذلك، سيستخدم Windows إصدارًا أحدث إذا كان موجودًا على النظام، باستثناء عندما يكون "ملف تكوين التطبيق" يستخدم.

هل أنا الوحيد الذي يعتقد أن هذا محير؟

لذا في ملخص:

  • بالنسبة للتجميعات الخاصة، استخدم علامة _BIND_TO_CURRENT_VCLIBS_VERSION في مشروع .exe و الجميع مشاريع .lib التابعة.
  • بالنسبة للتجميعات العامة، هذا غير مطلوب، حيث سيقوم Windows تلقائيًا بتحديد الإصدار الصحيح من ملفات .DLL من دليل SxS.

لقد تذكرت للتو خدعة أخرى استخدمتها لمعرفة المكتبات الثابتة التي كانت سيئة التصرف:"grep" من خلال المكتبات الثابتة للسلسلة "21022".ومع ذلك، لا تستخدم أدوات grep "العادية" مثلwingrep لأنها لن تظهر لك هذه السلاسل (يعتقدون أنه ملف ثنائي ويبحثون عن السلسلة الأولية غير الموحدة).استخدم الأداة المساعدة "السلاسل" من مجموعة الموارد (الآن في موقع Russinovich على ما أعتقد).هذا واحد سوف grep من خلال الثنائيات حسنا.لذا، اترك هذه "السلاسل" تمر عبر شجرة المصدر بأكملها وسترى الملفات الثنائية (dlls والمكتبات الثابتة) التي تحتوي على مراجع إلى البيان الخاطئ (أو إلى البيان الذي يحتوي على إصدار خاطئ فيه).

أداة أخرى لطيفة لعرض بيانات exe وdll هي عرض واضح, ، والذي لن يتم تشغيله على تثبيت نظيف لنظام التشغيل XP، لأنه هو - هي يعتمد على 9.0.21022.

بالنسبة للخيار الثالث، ربما يمكنك العثور على ملفات DLL والبيانات الخاصة بالإصدار 9.0.21022 في الدليل C:\WINDOWS\WinSxS على جهاز التطوير الخاص بك.إذا استطعت، فيمكنك إعداد دليل redist الخاص بك وتثبيت هذه الملفات مع تطبيقك.

وبدلاً من ذلك، يمكنك استخدام 9.0.30729.1 المتوفرة مع Visual Studio وتزوير البيان الذي قمت بتثبيته مع تطبيقك للإبلاغ عن أنه يوفر ملفات DLL 9.0.21022، وليس 9.0.30729.1.لا يبدو أن رابط وقت التشغيل يمانع.انظر الى هذا مدونة, ، والتي كانت مفيدة للغاية لحل هذه المشاكل، لمزيد من المعلومات.

قام كلا الحلين بإصلاح المشكلات التي واجهتني عند نشر مكتبات الارتباط الحيوي (DLL) كتجميعات خاصة باستخدام VS2008 Express.

إجابة Roel هي الطريقة التي يجب اتباعها لخيارك الأول ("إصلاحه بشكل صحيح")، ولكن إذا كنت تعتمد على مكتبة تعتمد على 9.0.21022 (وبالتالي فإن بيانك يسرد كلا الإصدارين)، فقد يكون الخيار الثالث هو الخيار الوحيد طريقة جيدة إذا كنت لا ترغب في تشغيل vcredist_x86.exe.

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