2010-09-20 20 views
11

किसी कारण से, जब भी मेरा सी # .NET 2.0 एप्लिकेशन GetProcAddress पर कॉल करता है तो यह हमेशा शून्य देता है।सी # GetProcAddress रिटर्न शून्य

public class MyClass 
{ 
    internal static class UnsafeNativeMethods 
    { 
     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     internal static extern IntPtr LoadLibrary(string lpFileName); 

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     internal static extern bool SetDllDirectory(string lpPathName); 

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 
    } 

    private void MyFunc() 
    { 
     IntPtr _dllHandle; 
     IntPtr _fptr; 
     string _fullPath = ".\\mydll.dll"; 
     string _procName = "MyDllFunc"; 

     _dllHandle = UnsafeNativeMethods.LoadLibrary(_fullPath); 
     _fptr = UnsafeNativeMethods.GetProcAddress(_dllHandle, _procName); // <-- Always returns zero. 
    } 
} 

मुझे यकीन है कि समारोह नाम की वर्तनी सही है हूँ, और _fullPath शायद सही क्योंकि _dllHandle हमेशा एक गैर शून्य मान निर्दिष्ट किया जाए। कोई भी अंतर्दृष्टि जो आप प्रदान करने में सक्षम हो सकती है उसकी सराहना की जाती है। धन्यवाद।

उत्तर

13

GetProcAddress केवल एक एएनएसआई स्वाद में आता है, इसलिए हम स्ट्रिंग पैरामीटर को मार्शल करते समय हमेशा एएनएसआई का उपयोग करने के लिए रनटाइम की मदद करते हैं। हम रनटाइम को एक गैर-मौजूद GetProcAddressA की तलाश में भी रोकते हैं, क्योंकि सी # के लिए डिफ़ॉल्ट ExactSpelling को गलत पर सेट करना है।

http://www.pinvoke.net/default.aspx/kernel32.getprocaddress

+0

+1, मैंने इसे देखा इससे पहले कि आप इसे मिला। –

+0

यह चाल है! धन्यवाद! –

+0

+1 मैं दीवार के खिलाफ अपने सिर को घंटों तक संकेत दे रहा हूं जब तक कि Google ने मुझे यहां भेजा नहीं!आखिरकार यह ** CharSet = CharSet.Ansi ** ** DllImport ** विशेषता के नामित पैरामीटर को काम करने के लिए केवल एक मामला था। –

1

आपने यह नहीं दिखाया है कि आप डीएलएल से फ़ंक्शन कैसे निर्यात करते हैं, लेकिन मुझे संदेह है कि समस्या यह है कि निर्यातित नाम वह नहीं है जो आप चाहते हैं। नाम सत्यापित करने के लिए आप डीएलएल के निर्यात को देखने के लिए dumpbin /exports mydll.dll चला सकते हैं।

यदि आप निर्यात का कोड स्निपेट दिखाते हैं, तो मैं अधिक सीधी सलाह प्रदान कर सकता हूं। परीक्षण के रूप में नाम बदलने वाले नाम को खत्म करने के लिए आप extern "C" के साथ निर्यात किए गए फ़ंक्शन को सजाने का प्रयास कर सकते हैं।

2

आपको वास्तव में कुछ त्रुटि जांच जोड़ने की आवश्यकता है। कम से कम सत्यापित करें कि _dllHandle! = IntPtr.Zero। साथ ही, वर्तमान कार्यशील निर्देशिका के आधार पर खतरनाक है, विधानसभा का उपयोग करें। GETEntryAssembly()। पूर्ण पथ नाम प्राप्त करने के लिए स्थान।

फ़ंक्शन का नाम शायद गलत है। निर्यात को सजाया जाता है, जैसे _MyDllFunc या _MyDllFunc @ 4। अधिक जंगली रूप से अगर यह एक C++ संकलक द्वारा संकलित किया गया था। वास्तविक नाम देखने के लिए अपने डीएलएल पर डंपबिन.एक्सई/निर्यात का उपयोग करें।

त्रुटि प्रबंधन पर वापस, [DllImport] विशेषता में SetLastWin32Error का उपयोग करें। अगर फ़ंक्शन झूठी या IntPtr.Zero लौटाता है तो Win32Exception फेंको।


संपादित करें: मुझे असली समस्या दिखाई देती है। GetProcAddress() के लिए CharSet.Auto का उपयोग करना गलत है। बहुत दुर्भाग्यपूर्ण, यह केवल के बारे में केवल विंडोज एपीआई फ़ंक्शन है जिसमें केवल एक एएनएसआई संस्करण है। आपको CharSet.Ansi का उपयोग करना होगा। उचित [DllImport] घोषणाएं प्राप्त करने के लिए एक अच्छी जगह है pinvoke.net

+0

गलत नाम के लिए वोट दें। निर्यात किए गए फ़ंक्शन नाम आमतौर पर बहुत अजीब लगते हैं। –

+0

मैंने कोड स्निपेट को सरल बनाने के लिए त्रुटि-हैंडलर कोड हटा दिया। –

+0

@Jim: क्या आपने पोस्ट करने से पहले वास्तव में SetLastWin32Error को हटा दिया था? मुझे पता है, स्मार्ट-गधा टिप्पणी :) –

0

क्या डीएलएल के लिए .DEF फ़ाइल में आपका निर्यात इनपुट से मेल खाता है? निर्यात किए जाने वाले अन्य उत्तरों के बारे में जानने के लिए आप dumpbin का उपयोग कर सकते हैं।

GetProcAddress() पर GetLastError() पर अंतर्निहित Win32 त्रुटि क्या है?

आप मूल कोड में इसे पी/Invoke के अतिरिक्त सामान के बिना पहले सही इनपुट करने के लिए कोशिश कर सकते हैं।

+2

बीटीडब्ल्यू आप Win32Exception फेंक कर अंतिम त्रुटि प्राप्त कर सकते हैं: 'नया Win32Exception() फेंक दें;' पैरामीटर रहित कन्स्ट्रक्टर 'मार्शल.गेटलास्टविन 32 ईरर()' कहता है और एक विस्तृत त्रुटि संदेश देता है। – dtb

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