استهداف كل من الإصدارين 32 بت و64 بت باستخدام Visual Studio في نفس الحل/المشروع

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

سؤال

أواجه معضلة صغيرة حول كيفية إعداد تصميمات الاستوديو المرئي الخاصة بي للاستهداف المتعدد.

خلفية:c# .NET v2.0 مع p/استدعاء ملفات DLL 32 بت لجهة خارجية، وSQL Compact v3.5 SP1، مع مشروع إعداد.في الوقت الحالي، تم تعيين هدف النظام الأساسي على x86 بحيث يمكن تشغيله على Windows x64.

أصدرت شركة الطرف الثالث للتو إصدارات 64 بت من ملفات DLL الخاصة بها وأريد إنشاء برنامج 64 بت مخصص.

وهذا يثير بعض الأسئلة التي لم أحصل على إجابات لها حتى الآن.أريد الحصول على نفس قاعدة التعليمات البرمجية بالضبط.يجب أن أبني مراجع إما لمجموعة 32 بت من ملفات DLL أو 64 بت DLL.(كل من الطرف الثالث وSQL Server المضغوط)

هل يمكن حل هذه المشكلة من خلال مجموعتين جديدتين من التكوينات (Debug64 وRelease64)؟

هل يجب علي إنشاء مشروعي إعداد منفصلين (std.مشاريع الاستوديو المرئي، بدون Wix أو أي أداة مساعدة أخرى)، أو هل يمكن حل هذه المشكلة ضمن نفس ملف .msi؟

سيكون موضع ترحيب أي أفكار و/أو توصيات.

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

المحلول

نعم، يمكنك استهداف كل من x86 وx64 بنفس قاعدة التعليمات البرمجية في نفس المشروع.بشكل عام، ستعمل الأمور فقط إذا قمت بإنشاء تكوينات الحل الصحيحة في VS.NET (على الرغم من أن P/Invention لمكتبات DLL غير المُدارة بالكامل سيتطلب على الأرجح بعض التعليمات البرمجية الشرطية):العناصر التي وجدت أنها تتطلب اهتمامًا خاصًا هي:

  • مراجع للتجميعات المُدارة الخارجية التي تحمل الاسم نفسه ولكن عدد البت الخاص بها (ينطبق هذا أيضًا على تجميعات التشغيل المتداخل لـ COM)
  • حزمة MSI (والتي، كما تمت الإشارة سابقًا، ستحتاج إلى استهداف x86 أو x64)
  • أي إجراءات مخصصة مستندة إلى فئة .NET Installer في حزمة MSI الخاصة بك

لا يمكن حل مشكلة مرجع التجميع بالكامل داخل VS.NET، حيث إنها ستسمح لك فقط بإضافة مرجع باسم معين إلى المشروع مرة واحدة فقط.للتغلب على هذه المشكلة، قم بتحرير ملف مشروعك يدويًا (في VS، انقر بزر الماوس الأيمن فوق ملف مشروعك في Solution Explorer، وحدد Unload Project، ثم انقر بزر الماوس الأيمن مرة أخرى وحدد تحرير).بعد إضافة مرجع إلى إصدار التجميع x86، على سبيل المثال، سيحتوي ملف مشروعك على شيء مثل:

<Reference Include="Filename, ..., processorArchitecture=x86">
  <HintPath>C:\path\to\x86\DLL</HintPath>
</Reference>

قم بلف هذه العلامة المرجعية داخل علامة ItemGroup للإشارة إلى تكوين الحل الذي تنطبق عليه، على سبيل المثال:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
   <Reference ...>....</Reference>
</ItemGroup>

بعد ذلك، انسخ والصق علامة ItemGroup بالكامل، وقم بتحريرها لتحتوي على تفاصيل ملف DLL 64 بت الخاص بك، على سبيل المثال:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
  <Reference Include="Filename, ..., processorArchitecture=AMD64">
     <HintPath>C:\path\to\x64\DLL</HintPath>
   </Reference>
</ItemGroup>

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

حل مشكلة MSI هو التالي، ولسوء الحظ هذا سوف تتطلب أداة غير VS.NET:أنا أفضّل كافيون المثبت المتقدم لهذا الغرض، لأنه ينفذ الخدعة الأساسية المعنية (إنشاء MSI مشترك، بالإضافة إلى MSIs محددة 32 بت و64 بت، واستخدام مشغل إعداد .EXE لاستخراج الإصدار الصحيح وإجراء الإصلاحات المطلوبة في وقت التشغيل ) جيد جدا.

ربما يمكنك تحقيق نفس النتائج باستخدام أدوات أخرى أو مجموعة أدوات Windows Installer XML (WiX)., ، لكن Advanced Installer يجعل الأمور سهلة للغاية (وبتكلفة معقولة جدًا) لدرجة أنني لم أبحث أبدًا عن بدائل.

شيء واحد لك يمكن لا تزال تتطلب WiX، حتى عند استخدام Advanced Installer، فهي مخصصة للإجراءات المخصصة لفئة .NET Installer.على الرغم من أنه من التافه تحديد إجراءات معينة يجب تشغيلها فقط على أنظمة أساسية معينة (باستخدام شروط التنفيذ VersionNT64 وNOT VersionNT64، على التوالي)، سيتم تنفيذ الإجراءات المخصصة للذكاء الاصطناعي المضمنة باستخدام إطار عمل 32 بت، حتى على الأجهزة 64 بت .

قد يتم إصلاح هذا في إصدار مستقبلي، ولكن في الوقت الحالي (أو عند استخدام أداة مختلفة لإنشاء ملفات MSI التي بها نفس المشكلة)، يمكنك استخدام دعم الإجراء المخصص المُدار لـ WiX 3.0 لإنشاء مكتبات الارتباط الحيوي (DLL) الخاصة بالإجراء بمعدل البت المناسب الذي سيتم تنفيذها باستخدام الإطار المقابل.


يحرر:اعتبارًا من الإصدار 8.1.2، يدعم Advanced Installer بشكل صحيح الإجراءات المخصصة 64 بت.منذ إجابتي الأصلية، ارتفع سعره قليلاً، لسوء الحظ، على الرغم من أنه لا يزال ذا قيمة جيدة للغاية بالمقارنة مع InstallShield وأمثاله...


يحرر:إذا تم تسجيل ملفات DLL الخاصة بك في GAC، فيمكنك أيضًا استخدام العلامات المرجعية القياسية بهذه الطريقة (SQLite كمثال):

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
    <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64" />
</ItemGroup>

يتم تقليل الشرط أيضًا إلى جميع أنواع البناء أو الإصدار أو التصحيح، ويحدد فقط بنية المعالج.

نصائح أخرى

لنفترض أن لديك ملفات DLL مصممة لكلا النظامين الأساسيين، وهي موجودة في الموقع التالي:

C:\whatever\x86\whatever.dll
C:\whatever\x64\whatever.dll

تحتاج ببساطة إلى تعديل ملف .csproj الخاص بك من هذا:

<HintPath>C:\whatever\x86\whatever.dll</HintPath>

الى هذا:

<HintPath>C:\whatever\$(Platform)\whatever.dll</HintPath>

يجب أن تكون قادرًا بعد ذلك على إنشاء مشروعك الذي يستهدف كلا النظامين الأساسيين، وسيقوم MSBuild بالبحث في الدليل الصحيح للنظام الأساسي المختار.

لست متأكدًا من الإجابة الكاملة على سؤالك - ولكني أعتقد أنني أود الإشارة إلى تعليق في قسم المعلومات الإضافية في صفحة تنزيل SQL Compact 3.5 SP1 رؤيتك تنظر إلى x64 - آمل أن يكون ذلك مفيدًا.

نظرًا للتغيرات في SQL Server Compact SP1 ودعم الإصدار 64 بت إضافي ، فإن بيئات الوضع المثبتة مركزيًا والموضع المختلط لإصدار 32 بت من SQL Server Compact 3.5 و 64 بت من SQL Server Compact 3.5 SP1 يمكن أن يخلق ما يبدو أنه متقطع مشاكل.لتقليل إمكانات التنوع ، وتمكين النشر المحايد لتطبيقات العميل المدارة ، فإن تثبيت الإصدار 64 بت من SQL Server Compact 3.5 SP1 باستخدام ملف Windows Installer (MSI) يتطلب أيضًا تثبيت الإصدار 32 بت من SQL Server Compact 3.5 SP1 MSI ملف.بالنسبة للتطبيقات التي تتطلب فقط النشر الأصلي 64 بت ، يمكن استخدام النشر الخاص للإصدار 64 بت من SQL Server Compact 3.5 SP1.

قرأت هذا على أنه "يتضمن ملفات SQLCE 32 بت إلى جانب ملفات 64 بت" في حالة التوزيع لعملاء 64 بت.

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

فيما يتعلق بسؤالك الأخير.على الأرجح أنك غير قادر على حل هذه المشكلة داخل MSI واحد.إذا كنت تستخدم مجلدات التسجيل/النظام أو أي شيء ذي صلة، فيجب أن يكون MSI نفسه على علم بذلك ويجب عليك إعداد MSI 64 بت للتثبيت بشكل صحيح على جهاز 32 بت.

هناك احتمال أن تتمكن من تثبيت منتجك كتطبيق 32 بت، ولا يزال بإمكانك تشغيله كتطبيق 64 بت، لكنني أعتقد أنه قد يكون من الصعب تحقيقه إلى حد ما.

ومع ذلك، أعتقد أنه يجب أن تكون قادرًا على الاحتفاظ بقاعدة تعليمات برمجية واحدة لكل شيء.وفي مكان عملي الحالي تمكنا من القيام بذلك.(ولكن الأمر استغرق بعض التلاعب لجعل كل شيء يلعب معًا)

أتمنى أن يساعدك هذا.إليك رابط لبعض المعلومات المتعلقة بمشكلات 32/64 بت:http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

إذا كنت تستخدم الإجراءات المخصصة المكتوبة بلغة .NET كجزء من برنامج تثبيت MSI لديك، فستواجه مشكلة أخرى.

إن "الرقائق" التي تقوم بتشغيل هذه الإجراءات المخصصة هي دائمًا 32 بت، ثم سيتم تشغيل الإجراء المخصص الخاص بك 32 بت أيضًا، بغض النظر عن الهدف الذي تحدده.

مزيد من المعلومات وبعض تحركات النينجا للتجول (قم بتغيير MSI بشكل أساسي لاستخدام الإصدار 64 بت من هذه الرقائق)

بناء MSI في Visual Studio 2005/2008 للعمل على SharePoint 64

الإجراءات المخصصة المُدارة 64 بت باستخدام Visual Studio

يمكنك إنشاء حلين بشكل مختلف ودمجهما بعد ذلك!لقد فعلت هذا لـ VS 2010.ويعمل.كان لدي حلان مختلفان تم إنشاؤهما بواسطة CMake وقمت بدمجهما

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

مثال:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <Reference Include="DLLName">
      <HintPath>..\DLLName.dll</HintPath>
    </Reference>
    <ProjectReference Include="..\MyOtherProject.vcxproj">
      <Project>{AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT}</Project>
      <Name>MyOtherProject</Name>
    </ProjectReference>
  </ItemGroup>

بناء .Net واحد مع تبعيات x86/x64

في حين أن جميع الإجابات الأخرى تمنحك حلاً لإنشاء إصدارات مختلفة وفقًا للنظام الأساسي، فأنا أقدم لك خيارًا للحصول على تكوين "AnyCPU" فقط وإنشاء إصدار يعمل مع ملفات dll الخاصة بـ x86 وx64.

عليك أن تكتب بعض رموز السباكة لهذا الغرض.لم أتمكن من الحصول على هذا العمل مع app.config.إذا كان شخص آخر يعرف طريقة لحلها عبر app.config، فأنا أرغب حقًا في معرفة ذلك.

حل ملفات x86/x64-dll الصحيحة في وقت التشغيل

خطوات:

  1. استخدم AnyCPU في csproj
  2. قرر ما إذا كنت تشير فقط إلى x86 أو x64 dlls في csprojs.قم بتكييف إعدادات UnitTests مع إعدادات البنية التي اخترتها.من المهم تصحيح الأخطاء/تشغيل الاختبارات داخل VisualStudio.
  3. على مجموعة الخصائص المرجعية نسخ محلي & نسخة محددة ل خطأ شنيع
  4. تخلص من تحذيرات الهندسة المعمارية بإضافة هذا السطر إلى الأول PropertyGroup في جميع ملفات csproj حيث تشير إلى x86/x64:<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. أضف هذا البرنامج النصي لما بعد البناء إلى مشروع بدء التشغيل الخاص بك، واستخدم وعدل مسارات هذا البرنامج النصي sp بحيث يقوم بنسخ كافة ملفات dll الخاصة بـ x86/x64 في المجلدات الفرعية المقابلة في حاوية البناء\x86\ bin\x64\

    xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86 xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64

    -> عندما تبدأ التطبيق الآن ، تحصل على استثناء من أنه لا يمكن العثور على التجميع.

  6. قم بتسجيل حدث AssemblyResolve مباشرة في بداية نقطة دخول التطبيق الخاص بك

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
    

    بهذه الطريقة:

    /// <summary>
    /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve
    /// </summary>
    /// <param name="sender">The app domain</param>
    /// <param name="resolveEventArgs">The resolve event args</param>
    /// <returns>The architecture dependent assembly</returns>
    public static Assembly TryResolveArchitectureDependency(object sender, ResolveEventArgs resolveEventArgs)
    {
        var dllName = resolveEventArgs.Name.Substring(0, resolveEventArgs.Name.IndexOf(","));
    
        var anyCpuAssemblyPath = $".\\{dllName}.dll";
    
        var architectureName = System.Environment.Is64BitProcess ? "x64" : "x86";
    
        var assemblyPath = $".\\{architectureName}\\{dllName}.dll";
    
        if (File.Exists(assemblyPath))
        {
            return Assembly.LoadFrom(assemblyPath);
        }
    
        return null;
    }
    
  7. إذا كان لديك اختبارات وحدة، فقم بإنشاء TestClass بطريقة تحتوي على AssemblyInitializeAttribute وقم أيضًا بتسجيل TryResolveArchitectureDependency-Handler أعلاه هناك.(لن يتم تنفيذ هذا في بعض الأحيان إذا قمت بتشغيل اختبارات فردية داخل الاستوديو المرئي، فسيتم حل المراجع ليس من حاوية UnitTest.ولذلك فإن القرار في الخطوة 2 مهم.)

فوائد:

  • تثبيت/بناء واحد لكلا النظامين الأساسيين

العيوب:- لا توجد أخطاء في وقت الترجمة عندما لا تتطابق ملفات dlls x86/x64.- لا يزال يتعين عليك إجراء الاختبار في كلا الوضعين!

اختياريًا، قم بإنشاء ملف تنفيذي ثانٍ حصريًا لبنية x64 باستخدام Corflags.exe في البرنامج النصي لما بعد البناء

المتغيرات الأخرى للتجربة:- لن تحتاج إلى معالج أحداث AssemblyResolve إذا كنت تأكد من أن يتم نسخ DLLs في المجلد الثنائي في البداية (تقييم بنية العملية -> تحرك DLLs المقابلة من X64/x86 إلى مجلد BIN والعودة.) - في التقييم التقييم للهندسة المعمارية و حذف الثنائيات للهندسة المعمارية الخاطئة ونقل تلك الصحيحة إلى مجلد بن.

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