विजुअल स्टूडियो में निर्माण के दौरान 32/64 बिट संदर्भ का उपयोग करें


124

मेरे पास एक प्रोजेक्ट है जो 32/64-बिट में बनाता है और इसमें 32/64-बिट निर्भरताएँ हैं। मैं कॉन्फ़िगरेशन को स्विच करने में सक्षम होना चाहता हूं और इसका सही संदर्भ इस्तेमाल किया है, लेकिन मुझे नहीं पता कि आर्किटेक्चर-उपयुक्त निर्भरता का उपयोग करने के लिए विज़ुअल स्टूडियो को कैसे बताया जाए।

शायद मैं इसके बारे में गलत तरीके से जा रहा हूं, लेकिन मैं कॉन्फ़िगरेशन ड्रॉपडाउन में x86 और x64 के बीच स्विच करने में सक्षम होना चाहता हूं, और संदर्भित DLL सही बिटनेस होना चाहिए।


बहुत अस्पष्ट, यह कौन सी भाषा है? समाधान में DLL परियोजना है?
हंस पसंत

क्षमा करें, यह .NET है, मैं C # में लिख रहा हूं।
जोनाथन यी

4
ठीक है, मैंने इसे एक गूंगे समाधान के साथ हल किया: एक अतिरिक्त csproj फ़ाइल बनाई जो केवल x64 DLL का संदर्भ देती है (और csproj से x86 कॉन्फ़िगरेशन को हटा दिया गया है)। यह काम करता है, लेकिन अगर किसी के पास एक अधिक सुरुचिपूर्ण समाधान था जिसमें एक अतिरिक्त csproj शामिल नहीं था, तो मैं इसे देखना पसंद करूंगा।
जोनाथन यी

जवाबों:


99

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

प्रोजेक्ट में एकल प्लेटफ़ॉर्म के संदर्भ जोड़ने के बाद, .csproj को एक पाठ संपादक में खोलें। <ItemGroup>तत्व के भीतर पहले तत्व से पहले <Project>, निम्न कोड जोड़ें, जो यह निर्धारित करने में मदद करेगा कि आप किस प्लेटफॉर्म (और निर्माण) पर चल रहे हैं।

<!-- Properties group for Determining 64bit Architecture -->
<PropertyGroup>
  <CurrentPlatform>x86</CurrentPlatform>
  <CurrentPlatform Condition="'$(PROCESSOR_ARCHITECTURE)'=='AMD64' or '$(PROCESSOR_ARCHITEW6432)'=='AMD64'">AMD64</CurrentPlatform>
</PropertyGroup>

फिर, आपके प्लेटफ़ॉर्म विशिष्ट संदर्भों के लिए, आप निम्नलिखित जैसे परिवर्तन करते हैं:

<ItemGroup>
  <Reference Include="Leadtools, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.dll</HintPath>
  </Reference>
  <Reference Include="Leadtools.Codecs, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.Codecs.dll</HintPath>
  </Reference>
  <Reference Include="Leadtools.ImageProcessing.Core, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.ImageProcessing.Core.dll</HintPath>
  </Reference>
  <Reference Include="System" />
  <Reference Include="System.Core" />
  <Reference Include="System.Data.Entity" />
  <!--  Other project references -->
</ItemGroup>

उस $(CurrentPlatform)संपत्ति के उपयोग पर ध्यान दें , जिसे हमने ऊपर परिभाषित किया था। इसके बजाय, आप ऐसी स्थिति का उपयोग कर सकते हैं जिसके लिए विधानसभाओं को किस प्लेटफॉर्म के लिए शामिल किया जाए। आपको इसकी आवश्यकता भी पड़ सकती है:

  • बदलें $(PROCESSOR_ARCHITEW6432)और $(PROCESSOR_ARCHITECTURE)साथ $(Platform)ही परियोजनाओं के लक्ष्य मंच पर विचार करने के लिए
  • वर्तमान मशीन के लिए उपयुक्त होने के लिए प्लेटफ़ॉर्म निर्धारण तर्क को बदल दें, ताकि आप 32 बिट प्लेटफ़ॉर्म पर निष्पादित करने के लिए 64 बिट बाइनरी का निर्माण / संदर्भ न कर रहे हों।

मैंने इसे मूल रूप से काम पर एक आंतरिक विकी के लिए लिखा था, हालांकि, मैंने इसे संशोधित किया है और पूरी प्रक्रिया को अपने ब्लॉग पर पोस्ट किया है , यदि आप विस्तृत चरण-दर-चरण निर्देशों में रुचि रखते हैं।


1
अच्छा लगा। मैं नीचे दिए गए सुझाव के अनुसार ItemGroup पर एक सशर्त का उपयोग करने के साथ गया था, लेकिन यहां की स्थितियों के लिए $ (PROCESSOR_ARCHITEW6432) और $ (PROCESSOR_ARCHITECTURE) का उपयोग कर रहा था। एक नोट है कि मैं $ (PROCESSOR_ARCHITECTURE) $ 32 और 64 बिट दोनों प्लेटफार्मों पर x86 देता है, लेकिन $ (PROCESSOR_ARCHITEW6432) केवल 64 बिट पर AMD64 लौटाता है। यदि आप x86 के लिए परीक्षण करने का प्रयास करते हैं तो कुछ ध्यान दें (क्योंकि AMD64 x86 का व्युत्पन्न है जो मुझे लगता है)।
tjmoore

उस जानकारी के लिए धन्यवाद @tjmoore किस ओ / एस पर आपने यह नोटिस किया? मैंने सिर्फ मेरा फिर से चेक किया (Win7SP1) और $ (PROCESSOR_ARCHITECTURE) के लिए AMD64 कहता है, लेकिन निश्चित रूप से संभव के रूप में पूरी तरह से और पूरी तरह से जानकारी रखना चाहेंगे।
ह्यूगो

7
मजेदार, मेरी खोज मुझे यहां लाती है, और मुझे केवल इसकी आवश्यकता है क्योंकि मैं लीडटूल का भी उपयोग कर रहा हूं ... +1
एड एस।

समाधान डिफ़ॉल्ट कॉन्फ़िगरेशन के लिए काम करता है, लेकिन मेरे परीक्षण से नहीं, यदि आप कॉन्फ़िगरेशन से विज़ुअल स्टूडियो (मेरे मामले में 2012) समाधान कॉन्फ़िगरेशन ड्रॉपडाउन सूची से कॉन्फ़िगरेशन नहीं बदलते हैं।
सारा वेनबर्गर

$ (PROCESSOR_ARCHITEW6432) का उपयोग करने के बजाय मैंने किसी कारण से $ (प्लेटफ़ॉर्म) का उपयोग किया $ (PROCESSOR_ARCHITEW6432) काम नहीं कर रहा था।
डाइजैन

60

AFAIK, यदि आपके प्रोजेक्ट को ऐसे संदर्भों की आवश्यकता है जो 32-बिट या 64-बिट विशिष्ट (यानी COM-इंटरॉप असेंबली) हैं, और आपको .csproj फ़ाइल को मैन्युअल रूप से संपादित करने में कोई दिलचस्पी नहीं है, तो आपको अलग-अलग 32-बिट बनाना होगा। 64-बिट प्रोजेक्ट।

मुझे ध्यान देना चाहिए कि निम्नलिखित समाधान अप्रयुक्त है, लेकिन काम करना चाहिए। यदि आप .csproj फ़ाइल को मैन्युअल रूप से संपादित करने के लिए तैयार हैं, तो आपको एकल प्रोजेक्ट के साथ वांछित परिणाम प्राप्त करने में सक्षम होना चाहिए। .Csproj फ़ाइल सिर्फ एक MSBuild स्क्रिप्ट है, इसलिए पूर्ण संदर्भ के लिए, यहां देखें । एक बार जब आप एक संपादक में .csproj फ़ाइल खोलते हैं, तो <Reference>तत्वों का पता लगाएं । आपको इन तत्वों को 3 अलग-अलग आइटम समूहों में विभाजित करने में सक्षम होना चाहिए : वे संदर्भ जो प्लेटफ़ॉर्म विशिष्ट, x86- विशिष्ट संदर्भ और x64- विशिष्ट संदर्भ नहीं हैं।

यहाँ एक उदाहरण है कि मान लें कि आपकी परियोजना "x86" और "x64" नामक लक्ष्य प्लेटफार्मों से कॉन्फ़िगर की गई है

<!-- this group contains references that are not platform specific -->
<ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <!-- any other references that aren't platform specific -->
</ItemGroup>

<!-- x86 specific references -->
<ItemGroup Condition=" '$(Platform)' == 'x86' ">
    <Reference Include="MyComAssembly.Interop">
        <HintPath>..\..\lib\x86\MyComAssembly.Interop.dll</HintPath>
    </Reference>

    <!-- any additional x86 specific references -->
</ItemGroup>

<!-- x64 specific referneces -->
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
    <Reference Include="MyComAssembly.Interop">
        <HintPath>..\..\lib\x64\MyComAssembly.Interop.dll</HintPath>
    </Reference>

    <!-- any additional x64 specific references -->
</ItemGroup>

अब, जब आप x86 या x64 प्लेटफ़ॉर्म को लक्षित करने के लिए अपना प्रोजेक्ट / समाधान बिल्ड कॉन्फ़िगरेशन सेट करते हैं, तो इसे प्रत्येक मामले में उचित संदर्भों को शामिल करना चाहिए। बेशक, आपको <Reference>तत्वों के साथ खेलने की आवश्यकता होगी । आप डमी परियोजनाओं को भी सेट कर सकते हैं जहां आप x86 और x64 संदर्भ जोड़ते हैं, और फिर <Reference>उन डमी प्रोजेक्ट फ़ाइलों से आवश्यक तत्वों को अपनी "वास्तविक" प्रोजेक्ट फ़ाइल में कॉपी कर सकते हैं।


संपादन 1
यहाँ सामान्य MSBuild प्रोजेक्ट आइटम का लिंक है, जिसे मैंने गलती से मूल पोस्ट से छोड़ दिया है: http://msdn.microsoft.com/en-us/library/bb629388.aspx


बहुत बढ़िया जवाब !! मेरा दिन बचाया! बहुत बहुत धन्यवाद।
नरकंकाल

20

आप प्रोजेक्ट फ़ाइल में 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>

1
यह बहुत धन्यवाद! यह निश्चित रूप से स्वीकृत समाधान होना चाहिए!
ManicBlowfish

गंभीरता से, यह जवाब बहुत बेहतर और सरल है कि स्वीकार किया गया है।
यैंड्रोस

1
क्या ऐसा करने के बाद सन्दर्भों में डुप्लिकेट प्रविष्टियों का होना सामान्य है?
नत्थेनो

7

मैं x86 DLL का संदर्भ दे रहा हूं, जैसे मेरी परियोजना में \ घटक \ v3_NET4, स्थित है। X86 / x64 के लिए विशिष्ट DLL "x86" और "x64" सम्मान नामक उप-फ़ोल्डर में स्थित हैं।

तब मैं एक प्री-बिल्ड स्क्रिप्ट का उपयोग कर रहा हूं जो $ $ (PlatformName) के आधार पर संदर्भित DLL में उपयुक्त DLL (x86 / x64) की प्रतिलिपि बनाता है।

xcopy /s /e /y "$(SolutionDir)..\component\v3_NET4\$(PlatformName)\*" "$(SolutionDir)..\component\v3_NET4"

मेरे लिये कार्य करता है।


3

X86 / x64 निर्भरता के साथ एक .Net निर्माण

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

रनटाइम पर सही x86 / x64-dll का रिज़ॉल्यूशन

कदम:

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

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

लाभ:

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

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

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

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


2

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

खाता प्रबंधक में मैंने x86 और x64 प्लेटफार्मों के लिए हमेशा की तरह दो अलग-अलग बिल्ड लक्ष्य बनाए। इसके बाद, मैंने अपने प्रोजेक्ट में x86 असेंबली का संदर्भ जोड़ा। इस बिंदु पर, मेरा मानना ​​था कि परियोजना केवल x86 बिल्ड के लिए कॉन्फ़िगर की गई है और कभी भी x64 कॉन्फ़िगरेशन के लिए नहीं बनेगी, जब तक कि मैं इसे ह्यूगो द्वारा सुझाए गए अनुसार मैन्युअल संपादन नहीं करूंगा।

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

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

सारांश में:

  1. किसी एकल प्रोजेक्ट में x86 और x64 लक्ष्य बनाएँ
  2. X86 असेंबली में सभी उचित प्रोजेक्ट संदर्भ जोड़ें
  3. सभी x64 असेंबली के लिए एक सामान्य बिल्ड लक्ष्य निर्देशिका सेट करें
  4. यदि आपके पास x64 असेंबली तैयार है, तो बस एक बार अपने x64 बिल्ड लक्ष्य निर्देशिका में उन्हें कॉपी करें

इन चरणों के पूरा होने के बाद आपका समाधान x86 और x64 दोनों कॉन्फ़िगरेशन के लिए ठीक से निर्मित होगा।

इसने मेरे लिए विजुअल स्टूडियो 2010 .NET 4.0 C # प्रोजेक्ट पर काम किया। जाहिर है, यह विज़ुअल स्टूडियो के एक प्रकार के अनजाने आंतरिक व्यवहार है, जो 2012, 2013 और 2015 संस्करणों में परिवर्तन का विषय हो सकता है। यदि कोई अन्य संस्करणों पर प्रयास करेगा, तो कृपया अपना अनुभव साझा करें।


-1

मैंने वह उपयोग करना समाप्त कर दिया जो मैं एक आसान समाधान मानता हूं जो मिकी के उलट के समान है। प्रोजेक्ट एक C # फॉर्म ऐप है, विजुअल स्टूडियो 2015, x86 और x64 लक्ष्य के साथ। मैंने .NET असेंबली में से एक का संदर्भ दिया, मैंने 32 बिट का उपयोग किया। संदर्भ गुणों में, मैंने "कॉपी लोकल" को झूठा सेट किया। तब मैं सिर्फ मैन्युअल रूप से उपयुक्त (32 या 64 बिट) .नेट असेंबली को प्रत्येक लक्ष्य निर्देशिका में डालता हूं। वास्तविक संदर्भ बिटनेस अप्रासंगिक है, यह मानते हुए कि उनके पास समान क्षमताएं हैं, क्योंकि यह केवल बाहरी इंटरफ़ेस को परिभाषित कर रहा है। यदि आप फैंसी प्राप्त करना चाहते हैं तो आप पोस्ट बिल्ड कॉपी स्टेप भी डाल सकते हैं। ध्यान दें कि इस परियोजना में एक COM संदर्भ भी था, वही काम करता है। संदर्भ वस्तुओं / इंटरफेस को परिभाषित करता है इसलिए संदर्भ DLL की कड़वाहट अप्रासंगिक है। यदि 32 बिट और 64 बिट COM DLL पंजीकृत हैं, ऐप रजिस्ट्री में उपयुक्त स्थान पर दिखेगा और सही 32 या 64 बिट COM ऑब्जेक्ट बनाएगा। मेरे लिये कार्य करता है!

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