2010-09-24 12 views
12

मेरे पास System.Data.SQLite.DLL के दो संस्करण हैं - x86 और x64 प्लेटफ़ॉर्म के लिए। X86 संस्करण अनुप्रयोग फ़ोल्डर में रहता है और x64 संस्करण appFolder \ x64 फ़ोल्डर में रहता है। एप्लिकेशन किसी भीCPC के रूप में संकलित। विंडोज प्लेटफार्म के अनुसार मैं SQLite के आवश्यक संस्करण को कैसे लोड कर सकता हूं?लोड हो रहा है x86 या x64 असेंबली

उत्तर

17

यदि आप http://system.data.sqlite.org से SQLite का उपयोग कर रहे हैं, तो System.Data.SQLite.DLL पूरी तरह से प्रबंधित है। एक अंतर्निहित मूल डीएलएल, SQLite.Interop.DLL है, जिसे प्रक्रिया (32- या 64-बिट) के आधार पर बदलने की आवश्यकता है।

मैं 64-बिट के लिए "। \ Native \ X64" में देशी पुस्तकालयों को तैनात करता हूं और 32-बिट के लिए "। \ Native \ X86"। रनटाइम पी/प्रक्रिया के सही पथ पर इंगित DLL लोड निर्देशिका सेट करने के लिए SetDllDirectory को आमंत्रित करें। http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx

(ध्यान दें कि मैं http://sqlite.phxsoftware.com से विरासत System.Data.SQLite.DLL संस्करण की वास्तुकला से परिचित नहीं हूँ)

private static class NativeMethods 
{ 
    [DllImport("kernel32.dll", CallingConvention = CallingConvention.Cdecl)] 
    internal static extern bool SetDllDirectory(string pathName); 
} 

... 

    // Underlying SQLite libraries are native. 
    // Manually set the DLL load path depending on the process. 
    var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Native"); 
    if(IntPtr.Size == 8) // or: if(Environment.Is64BitProcess) // .NET 4.0 
    { 
     path = Path.Combine(path, "X64"); 
    } 
    else 
    { 
     // X32 
     path = Path.Combine(path, "X86"); 
    } 
    NativeMethods.SetDllDirectory(path); 
+3

मैंने इस समस्या को हल किया है। धन्यवाद। मैंने "IntPtr.Size == 8" का उपयोग किया। मैंने SetDllDirectory के बजाय AppDomain.CurrentDomain.AssemblyResolve का उपयोग किया। – Rover

1

आप प्रक्रिया को 64 बिट के रूप में पहचानने के लिए Environment.Is64BitProcess का उपयोग कर सकते हैं। (मैं जहां भी संभव हो प्रवाह प्रवाह के रूप में अपवादों को पकड़ने से बचने की कोशिश करता हूं।)

+0

यह अच्छा प्रस्ताव है लेकिन यह मेरी समस्या का समाधान नहीं करता है। – Rover

+0

@ रोवर: कैसे? क्या आपके पास निश्चित रूप से 64 बिट .NET स्थापित है? –

+0

मैं .NET 3.5 का उपयोग करता हूं जिसमें यह चर नहीं है। मुझे लगता है कि मैं मंच के संस्करण की जांच कर सकता हूं लेकिन यह केवल कुछ अपवादों को पकड़ने से बचता है लेकिन आवश्यक असेंबली लोड नहीं होती है। – Rover

0

क्या आप प्रीकंपील्ड असेंबली के बजाय अपने समाधान में एक अलग परियोजना के रूप में SQLite के स्रोत का उपयोग नहीं कर सके? AnyCPU का उपयोग करना सिस्टम स्वयं सब कुछ का ख्याल रखेगा और आपको कोड में ऐसा करने की ज़रूरत नहीं है ...

+0

यह डीएलएस में से एक है जिसका उपयोग मैं x86 और x64 पर विभाजित करता हूं। मेरे पास सभी प्रयुक्त डीएलएस का स्रोत कोड नहीं है। – Rover

+0

यह किसी भी समस्या का समाधान नहीं करेगा, क्योंकि विकास मशीन की वास्तुकला हमेशा तैनाती मशीन के समान नहीं है। कोई भी सीपीयू केवल .NET असेंबली के लिए काम करता है, देशी डीएलएल (हुड के नीचे चुड़ैल SQLite उपयोग) के लिए नहीं – BigBoss

3

मुझे आश्चर्य है कि यह बिल्कुल काम करता है। इसे पहले x86 संस्करण मिलना चाहिए और असफल होना चाहिए। असफल असेंबली बांध विधानसभा के माध्यम से एक और प्रयास नहीं करती है।

स्पष्ट रूप से, सीएलआर वास्तव में x86 संस्करण नहीं ढूंढ सकता है या यह x64 मोड में भी असफल हो जाएगा। दूसरे शब्दों में, जब आप समस्या को ठीक करते हैं, तो आप 64-बिट कोड को तोड़ देंगे। पहले x86 समस्या का पीछा करें, यह देखने के लिए Fuslogvw.exe का उपयोग करें कि असेंबली के लिए कौन से फ़ोल्डरों की जांच की जा रही है।

एक वास्तविक फ़िक्स में x86 असेंबली को एक अलग फ़ोल्डर में स्थानांतरित करना और तदनुसार अपने ईवेंट हैंडलर को समायोजित करना शामिल होना चाहिए। यदि आप 64-बिट मोड (आकार == 8) में चल रहे हैं तो यह पता लगाने के लिए आप IntPtr.Size का परीक्षण कर सकते हैं। इसके अलावा सापेक्ष पथ का उपयोग करके एक पूर्ण पथ नाम उत्पन्न करना सुनिश्चित करें, जैसे कि अब आप विफल होने का कारण बन सकते हैं जब ऐप की कार्यशील निर्देशिका सेट नहीं की जाती है, जहां आप उम्मीद करते हैं। असेंबली.GetEntryAssembly()। स्थान आपको EXE का मार्ग प्राप्त करता है।

+0

मैंने भ्रम से बचने के लिए कोड हटा दिया और केवल प्रश्न छोड़ दिया। – Rover

+0

हम्म, मुझे नहीं लगता कि मेरा जवाब बदलता है। अंतिम अनुच्छेद आपको बताता है कि इसे सही तरीके से कैसे करें। –

+0

ठीक है, मैंने मंच की जांच की, आवश्यक असेंबली मिली। AppDomain को असेंबली लोड करने के लिए मुझे क्या करना चाहिए? – Rover

0
  1. GAC में उपयुक्त DLL स्थापित (जैसे 64 बिट संस्करण 64 बिट प्लेटफ़ॉर्म पर)
  2. अपने वेब/ऐप कॉन्फ़िगरेशन (संभवतः मशीन कॉन्फ़िगरेशन में) में असेंबली बाध्यकारी का उपयोग करें
  3. अपने वेब/ऐप कॉन्फ़िगरेशन में किसी भी आंशिक असेंबली संदर्भों को पूरी तरह अर्हता प्राप्त करें।
5

1.0.80.0 और बाद में इसके लिए अंतर्निहित समर्थन है।

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

हालांकि, यह मेरे अपने में काम करने के लिए प्राप्त करने के लिए प्लग में मैं भी पहली बार के लिए SQLite संदर्भित करने से पहले इस जोड़ने के लिए किया था: New SQLite mixed assemblies

11

:

// Make SQLite work... (loading dll from e.g. x64/SQLite.Interop.dll) 
System.Environment.SetEnvironmentVariable("PreLoadSQLite_BaseDirectory", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)); 

Sql.Data.SQLite... 

इस सवाल देखें कुछ एंटीवायर प्रोगोज़ SetDllDirectory() को रोकते हैं - मुझे इसका एहसास करने में काफी समय लगा। हम

System.Reflection.Assembly myass = System.Reflection.Assembly.GetExecutingAssembly(); 
FileInfo fi = new FileInfo(myass.Location); 
System.IntPtr moduleHandle = LoadLibraryEx(fi.Directory.FullName + "\\x64\\SQLite.Interop.DLL", IntPtr.Zero, 0); 

उपयोग कर रहे हैं स्पष्ट पथ के साथ 64 DLL लोड करने के लिए। यह उस बिंदु पर लोड होता है और .NET Runtime इसके लिए डिस्क खोजने के बजाय इन-मेमोरी डीएलएल का उपयोग करेगा।

+5

'myass' के लिए उपरोक्त :) –

+0

मेरे मामले में काम नहीं किया। भले ही मैंने डीबगर के साथ सत्यापित किया हो, कि मूल पुस्तकालय सही ढंग से लोड हो जाता है। SQLite अभी भी देशी डीएलएल गायब होने के बारे में एक अपवाद फेंकता है। – BartoszKP

संबंधित मुद्दे