एक ही समाधान / परियोजना में विजुअल स्टूडियो के साथ 32 बिट और 64 बिट दोनों को लक्षित करना


111

मुझे इस बात पर थोड़ी दुविधा है कि मल्टी-टार्गेटिंग के लिए मेरे विजुअल स्टूडियो को कैसे स्थापित किया जाए।

बैकग्राउंड: c # .NET v2.0 पी के साथ / तीसरी पार्टी में 32 बिट डीएलएल, एसक्यूएल कॉम्पैक्ट v3.5 SP1, एक सेटअप प्रोजेक्ट के साथ। अभी, प्लेटफ़ॉर्म लक्ष्य x86 पर सेट है, इसलिए इसे Windows x64 पर चलाया जा सकता है।

3rd पार्टी कंपनी ने अपने DLL के 64 बिट संस्करण जारी किए हैं और मैं एक समर्पित 64 बिट प्रोग्राम बनाना चाहता हूं।

यह कुछ सवाल उठाता है, जिनके जवाब मुझे अभी तक नहीं मिले हैं। मैं ठीक उसी कोड का आधार रखना चाहता हूं। मुझे DLL के 32 बिट सेट या 64 बिट DLL के संदर्भ के साथ निर्माण करना चाहिए। (दोनों 3 पार्टी और SQL सर्वर कॉम्पैक्ट)

क्या इसे कॉन्फ़िगरेशन (डिबग64 और रिलीज़ 64) के 2 नए सेटों के साथ हल किया जा सकता है?

क्या मुझे 2 अलग-अलग सेटअप प्रोजेक्ट्स (std। विज़ुअल स्टूडियो प्रोजेक्ट्स, कोई Wix या कोई अन्य यूटिलिटी) बनाने चाहिए, या क्या यह एक ही सेमी के भीतर हो सकता है?

किसी भी विचार और / या सिफारिशों का स्वागत किया जाएगा।


@ मैग्नस जोहानसन: आप अपना आधा लक्ष्य पूरा करने के लिए दो कॉन्फ़िगरेशन का उपयोग कर सकते हैं। MSI थोड़ा कठिन है।
user7116

जवाबों:


83

हां, आप x86 और x64 दोनों को एक ही प्रोजेक्ट में समान कोड बेस के साथ लक्षित कर सकते हैं। सामान्य तौर पर, यदि आप वीएस.नेट में सही समाधान कॉन्फ़िगरेशन बनाते हैं, तो चीजें बस काम करेंगी (हालांकि पी / पूरी तरह से अप्रबंधित DLL के लिए आह्वान करना सबसे अधिक संभावना है कि कुछ सशर्त कोड की आवश्यकता होगी): जिन वस्तुओं पर मुझे विशेष ध्यान देने की आवश्यकता है, वे हैं:

  • एक ही नाम के साथ प्रबंधित असेंबली के बाहर संदर्भ लेकिन उनकी अपनी विशिष्ट बिटनेस (यह COM इंटरॉप असेंबली पर भी लागू होती है)
  • MSI पैकेज (जो, जैसा कि पहले ही नोट किया गया है, x86 या x64 को लक्षित करने की आवश्यकता होगी)
  • आपके MSI पैकेज में कोई भी कस्टम .NET इंस्टालर वर्ग-आधारित क्रियाएँ

असेंबली रेफरेंस इश्यू को पूरी तरह से वीएस.नेट के भीतर हल नहीं किया जा सकता है, क्योंकि यह आपको एक बार दिए गए नाम के साथ एक प्रोजेक्ट में एक संदर्भ जोड़ने की अनुमति देगा। इसके चारों ओर काम करने के लिए, अपनी प्रोजेक्ट फ़ाइल को मैन्युअल रूप से संपादित करें (वीएस में, समाधान एक्सप्लोरर में अपनी प्रोजेक्ट फ़ाइल को राइट-क्लिक करें, अनलोड प्रोजेक्ट चुनें, फिर राइट-क्लिक करें और फिर संपादित करें चुनें)। एक संदर्भ, एक विधानसभा के x86 संस्करण, को जोड़ने के बाद, आपकी परियोजना फ़ाइल में कुछ इस तरह होगा:

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

उस संदर्भ टैग को लपेटें जो किसी आइटम समूह के अंदर टैग समाधान पर लागू होने वाले समाधान कॉन्फ़िगरेशन को दर्शाता है, जैसे:

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

फिर, पूरे आइटम समूह टैग को कॉपी और पेस्ट करें, और अपने 64-बिट DLL के विवरण को समाहित करने के लिए इसे संपादित करें, जैसे:

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

वीएस.नेट में अपनी परियोजना को पुनः लोड करने के बाद, विधानसभा संदर्भ संवाद इन परिवर्तनों से थोड़ा भ्रमित हो जाएगा, और आप गलत लक्ष्य प्रोसेसर के साथ असेंबली के बारे में कुछ चेतावनियों का सामना कर सकते हैं, लेकिन आपके सभी बिल्ड बस ठीक काम करेंगे।

MSI समस्या को हल करना अगला है, और दुर्भाग्य से इसके लिए एक गैर-V.NET टूल की आवश्यकता होगी : मैं उस उद्देश्य के लिए Caphyon के एडवांस इंस्टॉलर को प्राथमिकता देता हूं , क्योंकि इसमें शामिल बुनियादी ट्रिक को खींचता है (एक सामान्य MSI बनाएं, साथ ही 32-बिट) और 64-बिट विशिष्ट MSI, और सही संस्करण को निकालने के लिए .EXE सेटअप लॉन्चर का उपयोग करें और रनटाइम में आवश्यक फ़िक्सअप करें) बहुत, बहुत अच्छी तरह से।

आप शायद अन्य टूल या Windows इंस्टालर XML (WiX) टूलसेट का उपयोग करके समान परिणाम प्राप्त कर सकते हैं , लेकिन उन्नत इंस्टॉलर चीजों को इतना आसान बनाता है (और उस पर काफी सस्ती है) कि मैंने वास्तव में कभी विकल्प नहीं देखा है।

उन्नत इंस्टालर का उपयोग करते समय, एक बात के लिए आपको अभी भी वाईएक्स की आवश्यकता हो सकती है, आपके .NET इंस्टालर वर्ग कस्टम क्रियाओं के लिए। यद्यपि यह कुछ क्रियाओं को निर्दिष्ट करने के लिए तुच्छ है, जो केवल कुछ प्लेटफार्मों पर ही चलना चाहिए (क्रमशः संस्करण संस्करण संस्करण का उपयोग नहीं किया जा सकता है), 64-बिट मशीनों पर भी 32-बिट फ्रेमवर्क का उपयोग करके अंतर्निहित AI कस्टम क्रियाओं को निष्पादित किया जाएगा। ।

यह भविष्य के रिलीज़ में ठीक किया जा सकता है, लेकिन अभी के लिए (या अपने MSI बनाने के लिए एक अलग टूल का उपयोग करते समय जो एक ही मुद्दा है), आप उचित बिटनेस के साथ कार्रवाई DLL बनाने के लिए WiX 3.0 के प्रबंधित कस्टम एक्शन सपोर्ट का उपयोग कर सकते हैं जो इसी फ्रेमवर्क का उपयोग करके निष्पादित किया जाएगा।


संपादित करें: संस्करण 8.1.2 के रूप में, उन्नत इंस्टॉलर 64-बिट कस्टम क्रियाओं का सही ढंग से समर्थन करता है। मेरे मूल उत्तर के बाद से, इसकी कीमत में काफी वृद्धि हुई है, दुर्भाग्य से, भले ही यह अभी भी बहुत अच्छा मूल्य है जब InstallShield और इसकी ilk की तुलना में ...


संपादित करें: यदि आपका 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>

सभी बिल्ड प्रकार, रिलीज़ या डीबग के लिए भी स्थिति कम हो जाती है, और बस प्रोसेसर आर्किटेक्चर को निर्दिष्ट करता है।


विजुअल स्टूडियो 2008 में, मैंने पाया कि <ItemGroup> s को नेस्ट नहीं किया जा सकता है। एक बार जब मैंने समूह के नीचे नया <ItemGroup> s शेष <संदर्भ> s बना दिया, तो यह समाधान ठीक काम करता है। मुझे x86 को AnyCPU में भी बदलना पड़ा, जो संभवतः मेरे विशेष प्रोजेक्ट के इतिहास से संबंधित है।
ओलिवर बॉक

कि उन्नत इंस्टालर बहुत भयानक लग रहा है।
पाट

यह एक गूंगा सवाल हो सकता है लेकिन आप इसे मैन्युअल रूप से संपादित करने के लिए फाइल पर कैसे पहुंच सकते हैं?
hr

1
वीएस के भीतर फ़ाइल को संपादित करने के लिए, समाधान एक्सप्लोरर में प्रोजेक्ट पर राइट क्लिक करें और "अनलोड प्रोजेक्ट" ढूंढें। एक बार प्रोजेक्ट अनलोड होने के बाद, उस पर फिर से राइट क्लिक करें और "एडिट <प्रोजेक्ट फाइल नेम>" पर क्लिक करें। प्रोजेक्ट फ़ाइल को संपादित करने के बाद, इसे सहेजें और प्रोजेक्ट फ़ाइल पर फिर से क्लिक करें और इसे लोड करें। यदि कोई टाइपो या त्रुटि नहीं है, तो यह फिर से लोड होगा। यदि नहीं, तो वी.एस. आपको बताएंगे कि फ़ाइल में क्या समस्या है। उम्मीद है की वो मदद करदे!
जॉन बेटमैन

बहुत बढ़िया जवाब! धन्यवाद!
जॉन बेटमैन

27

मान लें कि आपके पास दोनों प्लेटफ़ॉर्म के लिए 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 चुने गए प्लेटफ़ॉर्म के लिए सही निर्देशिका में दिखेगा।


यह शानदार होगा अगर यह काम करता है, लेकिन यह नहीं है। कम से कम मेरे लिए नहीं।
जॉन शीहान

10
ऐसा नहीं माना जाता है: <HintPath> C: \ जो \ $ (प्लेटफ़ॉर्म) \ जो भी हो। सभी </ HintPath>
एंड्रियास

मेरे लिए विज़ुअल स्टूडियो 2008 पर ठीक काम किया, लेकिन सामान्य <संदर्भ> करता है के रूप में निर्माण लक्ष्य निर्देशिका के लिए DLL को स्वचालित रूप से कॉपी नहीं किया। mdb के समाधान ने मेरे लिए बेहतर काम किया।
ओलिवर बॉक

1

आपके प्रश्न के कुल उत्तर के बारे में निश्चित नहीं है - लेकिन मुझे लगा कि आप SQL 64 के एडिशनल इंफॉर्मेशन सेक्शन में एक कमेंट को इंगित करेंगे, जिसे आप x64 में देख रहे हैं।

SQL सर्वर कॉम्पेक्ट SP1 और अतिरिक्त 64-बिट संस्करण समर्थन में परिवर्तन के कारण, SQL सर्वर कॉम्पेक्ट 3.5 के 32-बिट संस्करण के केंद्रीय रूप से स्थापित और मिश्रित मोड वातावरण और SQL सर्वर कॉम्पेक्ट 3.5 SP1 के 64-बिट संस्करण बना सकते हैं जो रुक-रुक कर दिखाई देते हैं समस्या। संघर्ष की क्षमता को कम करने के लिए, और प्रबंधित क्लाइंट अनुप्रयोगों के प्लेटफ़ॉर्म न्यूट्रल परिनियोजन को सक्षम करने के लिए, Windows इंस्टालर (MSI) फ़ाइल का उपयोग करते हुए SQL सर्वर कॉम्पैक्ट 3.5 SP1 के 64-बिट संस्करण को स्थापित करने के लिए भी SQL सर्वर के 32-बिट संस्करण को स्थापित करने की आवश्यकता होती है कॉम्पैक्ट 3.5 SP1 MSI फ़ाइल। उन अनुप्रयोगों के लिए जिनमें केवल मूल 64-बिट की आवश्यकता होती है, SQL Server कॉम्पैक्ट 3.5 SP1 के 64-बिट संस्करण की निजी तैनाती का उपयोग किया जा सकता है।

अगर मैं 64 बिट क्लाइंट के लिए वितरित करता हूं तो "32 बिट एसक्यूसीई फाइलों के साथ-साथ 64 बिट्स फ़ाइलों को शामिल करें" इसे पढ़ें ।

लगता है कि जीवन दिलचस्प है मुझे लगता है कि .. मुझे कहना होगा कि मैं "क्या आंतरायिक समस्याओं प्रतीत होता है" लाइन ... थोड़ा सा लगता है "आप चीजों की कल्पना कर रहे हैं, लेकिन सिर्फ मामले में, ऐसा करें ..."


1

एक .Net का निर्माण x86 / x64 निर्भरता के साथ होता है

जबकि अन्य सभी उत्तर आपको प्लेटफ़ॉर्म के अनुसार अलग-अलग बिल्ड बनाने के लिए एक समाधान देते हैं, मैं आपको केवल "एएनसीपीयू" कॉन्फ़िगरेशन के लिए एक विकल्प देता हूं और एक निर्माण करता हूं जो आपके x86 और x64 dll के साथ काम करता है।

आपको इसके लिए कुछ प्लंबिंग कोड लिखना होगा।

रनटाइम पर सही x86 / x64-dll का संकल्प

कदम:

  1. Csproj में AnyCPU का उपयोग करें
  2. यदि आप केवल x86 या x64 dlls को अपने csprojs में संदर्भित करते हैं तो निर्णय लें। आपके द्वारा चुनी गई आर्किटेक्चर सेटिंग्स पर यूनिटटेस्ट सेटिंग्स को एडॉप्ट करें। VisualStudio के अंदर परीक्षणों को डिबग करना / चलाना महत्वपूर्ण है।
  3. संदर्भ-गुण सेट पर स्थानीय और विशिष्ट संस्करण की प्रतिलिपि बनाकर झूठे को सेट करें
  4. अपने सभी csproj फ़ाइलों में जहाँ आप x86 / x64 का संदर्भ देते हैं, इस लाइन को पहले प्रॉपर्टी ग्रुप में जोड़कर आर्किटेक्चर चेतावनियों से छुटकारा पाएं : <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. अपने स्टार्टअप प्रोजेक्ट में इस पोस्ट स्क्रिप्ट को जोड़ें, इस स्क्रिप्ट के पथों का उपयोग करें और संशोधित करें कि यह आपके सभी x86 / x64 dlls को आपके बिल्ड बिन \ 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. अपने आवेदन प्रविष्टि बिंदु की शुरुआत में असेंबली को पंजीकृत करें

    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. यदि आपके पास इकाई परीक्षण हैं, तो एक विधानसभा के साथ एक टेस्टक्लास बनाते हैं जिसमें असेंबलीइंटरिलाइज़ेशन एट्रिब्यूट है और ऊपर दिए गए TryResolveArchitectureD dependency-Handler को भी पंजीकृत करें। (इसे कभी-कभी निष्पादित नहीं किया जाएगा यदि आप दृश्य स्टूडियो के अंदर एकल परीक्षण चलाते हैं, तो संदर्भों को यूनिटटेस्ट बिन से नहीं सुलझाया जाएगा। इसलिए चरण 2 में निर्णय महत्वपूर्ण है।)

लाभ:

  • दोनों प्लेटफार्मों के लिए एक इंस्टालेशन / बिल्ड

कमियां: - x86 / x64 dll से मेल नहीं खाने पर संकलन समय में कोई त्रुटि नहीं है। - आपको अभी भी दोनों मोड में परीक्षण चलाना चाहिए!

वैकल्पिक रूप से एक दूसरी निष्पादन योग्य बनाएं जो x64 आर्किटेक्चर के लिए अनन्य है जो कि स्क्रिप्ट को पोस्ट करने में Corflags.exe के साथ है

अन्य वेरिएंट को आज़माने के लिए: - आपको असेंबली की आवश्यकता नहीं है। ईवेंट हैंडलर को व्यवस्थित करें यदि आप आश्वस्त करते हैं कि प्रारंभ में सही बाइनरी आपके बाइनरी फ़ोल्डर में कॉपी किए गए हैं (प्रोसेस आर्किटेक्चर का मूल्यांकन करें -> संबंधित dlls को x64 / x86 से बिन फ़ोल्डर और बैक पर ले जाएं। ) - इंस्टॉलर में आर्किटेक्चर का मूल्यांकन करें और गलत आर्किटेक्चर के लिए बायनेरिज़ को हटा दें और सही लोगों को बिन फ़ोल्डर में स्थानांतरित करें।


0

अपने आखिरी सवाल के बारे में। सबसे अधिक संभावना है कि आप इसे एकल MSI के अंदर हल नहीं कर सकते। यदि आप रजिस्ट्री / सिस्टम फ़ोल्डर या संबंधित कुछ भी उपयोग कर रहे हैं, तो MSI को स्वयं इस बारे में पता होना चाहिए और आपको 32 बिट मशीन पर ठीक से स्थापित करने के लिए 64bit MSI तैयार करना होगा।

इस बात की संभावना है कि आप 32 के रूप में स्थापित किए गए उत्पाद को एप्लिकेशन बना सकते हैं और फिर भी इसे 64 बिट के रूप में चलाने में सक्षम हो सकते हैं, लेकिन मुझे लगता है कि इसे प्राप्त करना कुछ कठिन हो सकता है।

कहा जा रहा है कि मुझे लगता है कि आपको हर चीज के लिए एक ही कोड आधार रखने में सक्षम होना चाहिए। मेरे वर्तमान कार्य स्थान में हम ऐसा करने में कामयाब रहे हैं। (लेकिन यह सब कुछ एक साथ खेलने के लिए कुछ करतब दिखाने लगा)

उम्मीद है की यह मदद करेगा। 32/64 बिट मुद्दों से संबंधित कुछ जानकारी के लिए लिंक: http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html


0

अगर आप अपने MSI इंस्टॉलर के भाग के रूप में .NET में लिखे कस्टम एक्टेशन का उपयोग करते हैं तो आपको एक और समस्या है।

इन कस्टम क्रियाओं को चलाने वाला 'shim' हमेशा 32bit का होता है, फिर आपकी कस्टम क्रिया 32bit भी चलेगी, इसके बावजूद कि आप किस लक्ष्य को निर्दिष्ट करते हैं।

अधिक जानकारी और कुछ निनजा घूमने के लिए (मूल रूप से एमएसआई को इस शिम के 64 बिट संस्करण का उपयोग करने के लिए बदल देता है)

SharePoint 64 पर काम करने के लिए Visual Studio 2005/2008 में MSI का निर्माण

दृश्य स्टूडियो के साथ 64-बिट प्रबंधित कस्टम क्रियाएँ


0

आप दो समाधान अलग-अलग उत्पन्न कर सकते हैं और बाद में उनका विलय कर सकते हैं! मैंने वीएस 2010 के लिए यह किया है। यह काम करता है। मेरे पास सीएमके द्वारा उत्पन्न 2 अलग-अलग समाधान थे और मैंने उन्हें विलय कर दिया


0

आप प्रोजेक्ट फ़ाइल में 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>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.