سؤال

سيناريو

لديّ اثنان من الأغلفة حول Microsoft Office ، واحدة لعام 2003 وواحدة لعام 2007. نظرًا لأن الحصول على نسختين من Microsoft Office جنبًا مع Office 2007. نقوم بتجميع الأغلفة بشكل منفصل. يتم تضمين DLLs في حلنا ، كل صندوق لديه نفس الخروج ولكن مع Office 2003 أو 2007 "تفريغ" حتى لا تحاول تجميع هذا DLL معين. الفشل في القيام بذلك سيؤدي إلى إلقاء أخطاء على التجميع بسبب عدم توفر Office Com DLLS.

نستخدم .NET 2.0 و Visual Studio 2008.

حقائق

منذ أن غيرت Microsoft بشكل غامض API Office 2003 في عام 2007 ، إعادة تسمية وتغيير بعض الطرق (تنهد) وبالتالي جعلها غير متوافقة مع الوراء ، نحن بحاجة إلى الأغلفة. لدينا كل آلة بناء مع الحل وتفعيل مكتب DLL واحد. على سبيل المثال: يحتوي الماكينة مع Office 2003 على DLL "Office 2007" ، وبالتالي عدم تجميعها. الصندوق الآخر هو نفس الفكرة ولكن العكس. كل هذا لأنه لا يمكن أن يكون لدينا مكتب مختلفان في نفس المربع لأغراض البرمجة. (يمكنك من الناحية الفنية أن يكون لديك مكتبان معًا وفقًا لـ Microsoft) ولكن ليس للبرمجة وليس بدون بعض القضايا.

مشكلة

عندما نقوم بتغيير إصدار التطبيق (من 1.5.0.1 إلى 1.5.0.2 على سبيل المثال) ، نحتاج إلى إعادة ترجمة DLL لمطابقة الإصدار الجديد من التطبيق ، ويتم ذلك تلقائيًا ، لأن غلاف المكتب مدرج في الحل. نظرًا لأن الأغلفة موجودة في الحل ، فإن هؤلاء يرثون إصدار التطبيق ، ولكن يتعين علينا القيام بذلك مرتين ثم "نسخ" DLL الآخر إلى الجهاز الذي ينشئ المثبت. (ألم…)

سؤال

هل من الممكن تجميع DLL الذي سيعمل معه أي نسخة من التطبيق ، على الرغم من كونها "أكبر سنا"؟ لقد قرأت شيئًا عن البيان ، لكنني لم أضطر أبدًا للتفاعل مع هؤلاء. اي مؤشرات سوف تقدر.

السبب السري لهذا هو أننا لم نغير مغلفةنا في "العصور" ولم يفعلوا Microsoft مع واجهات برمجة التطبيقات القديمة ، ومع ذلك فإننا نعيد تجميع DLL لمطابقة إصدار التطبيق على كل الافراج عننا نجعلها. أرغب في أتمتة هذه العملية بدلاً من الاضطرار إلى الاعتماد عليها اثنين الآلات.

لا يمكنني إزالة DLL من المشروع (لا يوجد منهما) لأن هناك تبعيات.

يمكنني إنشاء "غلاف رئيسي" ثالث ولكن لم أفكر في الأمر بعد.

أيه أفكار؟ أي شخص آخر مع نفس المتطلبات؟

تحديث

التوضيح:

لدي حل واحد مع مشاريع n.

"Application" + Office11Wrapper.dll + Office12Wrapper.dll.

يستخدم كل من "الأغلفة" التبعيات للتطبيق + المكتبات الأخرى في الحل (Datalayer ، BusinessLayer ، Framework ، إلخ)

كل غلاف لديه مراجع لحزمة Office المعنية (2003 و 2007).

إذا قمت بتجميع ولم يتم تثبيت Office 12 ، أحصل على أخطاء من Office12Wrapper.dll لعدم العثور على مكتبات Office 2007. لذا فإن ما لديّ هو جهازان للبناء ، واحدة مع Office 2003 ، واحدة مع Office 2007. بعد تحديث SVN الكامل + ترجمة على كل جهاز ، نستخدم ببساطة Office12 رمز ، نفس الإصدار ".

ملاحظة: آلة بناء Office 2007 ، لديها Wrapper for Office 2003 "تفريغ" و Viceversa.

شكرا مقدما.

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

المحلول

عندما لا يتمكن حل مجموعة التجميع .NET من العثور على مجموعة مرجعية في وقت التشغيل (في هذه الحالة ، لا يمكن العثور على إصدار Wrapper DLL معين تم ربط التطبيق به) ، فإن سلوكه الافتراضي هو الفشل وتحطم التطبيق بشكل أساسي. ومع ذلك ، يمكن تجاوز هذا السلوك عن طريق تثبيت حدث AppDomain.AssemblyResolve. يتم إطلاق هذا الحدث عندما لا يمكن العثور على تجميع مشار إليه ، ويمنحك الفرصة لاستبدال مجموعة أخرى بدلاً من المفقودين (شريطة أن تكون متوافقة). لذلك ، على سبيل المثال ، يمكنك استبدال نسخة أقدم من Wrapper DLL التي تقوم بتحميلها بنفسك.

أفضل طريقة وجدت للقيام بذلك هي إضافة مُنشئ ثابت على الفصل الرئيسي للتطبيق الذي يربط الحدث ، على سبيل المثال:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}

من خلال وضع هذا في مُنشئ ثابت لفئة التطبيق الرئيسية ، من الضمان تشغيله قبل أن يحاول أي رمز الوصول إلى أي شيء في Wrapper DLL ، مما يضمن أن الخطاف في وقت مبكر.

يمكنك أيضًا استخدام ملفات السياسة لإعادة توجيه الإصدار ، ولكن هذا يميل إلى أن يكون أكثر تعقيدًا.

نصائح أخرى

مجرد تفكير - هل يمكنك استخدام TLBEXP لإنشاء تجميعات interop اثنين (مع أسماء وتجميعات مختلفة) ، واستخدام واجهة/مصنع للرمز مقابل الاثنين عبر الواجهة الخاصة بك؟ بمجرد حصولك على DLL Interop ، لا تحتاج إلى تبعية COM (باستثناء بالطبع للاختبار وما إلى ذلك).

Tlbimp لديه A /esmversion للإصدار ، بحيث يمكن القيام به كجزء من البرنامج النصي للبناء ؛ لكنني متأكد من أنك بحاجة إلى هذا: فقط تأكد من أن "إصدار محدد" خطأ في المرجع (Solution Explorer)؟

أيضًا - أعلم أنه لا يساعد ، لكن C# 4.0 مع dynamic و/أو "لا PIA" قد تساعد هنا (في المستقبل ؛ ربما).

لست متأكدًا من أنني أتابع كل ما ذكرته تمامًا ، لكن دعني أحاول:

يبدو أن لديك حل واحد مع 2 (؟) مشاريع. أحدهما هو التطبيق الفعلي ، والآخر عبارة عن غلاف لمكتب واجهة برمجة تطبيقات. تطبيقك بعد ذلك لديه إشارة مشروع إلى Woster API Wrapper. لم يسبق لي أن برمجت Office من قبل ، ولكن يبدو أن واجهات برمجة تطبيقات البرمجة هي مكون شائع لا يمكنك الحصول إلا على إصدار واحد على الجهاز (أي 2003 أو 2007 ، وليس كلاهما). وربما هذا هو المكان الذي توجد فيه المشكلة ، ولكن نظرًا لأن لديك مرجعًا للمشروع ، سيتم تجميع الغلاف أولاً ، ويتم نسخه إلى دليل الصندوق في التطبيق الخاص بك ، حيث سيتم ربط التطبيق الخاص بك ببناء الغلاف. سيؤدي ذلك إلى أن يطلب بيان التطبيق على وجه التحديد إصدار Wrapper في وقت التشغيل.

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

خيار آخر محتمل هو إعادة توجيه التجميع. هذا أكثر تقدمًا ، ويأتي مع مجموعة من المشكلات الخاصة به ، ولكن يمكنك القراءة عنها هنا.

أو على غرار فكرة مارك ، يمكنك استخراج واجهة وسحب بعض الكائنات المشتركة إلى مكتبة إطار ، وترميز تطبيقك مقابل الواجهة والكائنات المشتركة. ثم في وقت التشغيل ، استخدم انعكاسًا لتحميل التجميع وتثبيت الغلاف الذي تريده.

أعتقد أن المفتاح هو إزالة تبعية المشروع إذا استطعت. يبدو أن الغلاف مستقر إلى حد ما ولا يتغير ، وإلا فلن تطلب الارتباط بإصدار سابق منه.

تثبيت Office 2003 و 2007 جنبًا إلى جنب على نفس الجهاز بالتأكيد ممكن - نفعل ذلك في منظمتنا حتى في محطات عمل إنتاج المستخدم النهائي.

في هذه المقالة المرتبطة ، توصي Microsoft بعدم القيام بذلك للاستخدام الفعلي. ولكن في حالتك ، يبدو أنه فقط لآلة بناء واحدة ، أي أنك لن تستخدم فعليًا أي إصدار من Office على هذا الجهاز. في هذا السياق ، سأحاول معرفة ما إذا كان يمكنك عمل التثبيت جنبًا إلى جنب.

قد يكون افتراضي خطأ ، وأنت تحاول القيام بذلك لجهاز كل مطور. في هذه الحالة ، يجب أن تتجاهل هذه الإجابة :-)

عمل جميل! لقد ألقيت للتو تطبيقًا يعتمد على المفهوم الوارد أعلاه ، وهو يعمل بشكل رائع:

static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
     string partialName = args.Name.Substring(0, args.Name.IndexOf(','));
     return Assembly.Load(new AssemblyName(partialName));
}

بالطبع هناك مجال للتعزيز ، ولكن هذا يفعل الخدعة بالنسبة لي!

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