2010-05-11 11 views
5

मैं फ़ोल्डरब्राउज़रडिअलॉग दिखाते समय यादृच्छिक रूप से अमान्य कैस्टएक्सप्शन प्राप्त कर रहा हूं और कई क्लाइंट ने इसकी सूचना दी है।WinForms: फ़ोल्डर ब्राउज़र संवाद दिखाते समय मुझे InvalidCastException क्यों मिलता है?

मुझे इंटरनेट पर कुछ भी प्रासंगिक नहीं मिला है। क्या किसी को पता है कि इसका कारण क्या है/इसे कैसे ठीक किया जाए?

मेरे कोड:

 using (FolderBrowserDialog fbd = new FolderBrowserDialog()) 
     { 
      fbd.ShowNewFolderButton = false; 
      if (fbd.ShowDialog() == DialogResult.OK) 

स्टैक ट्रेस: ​​

Error: System.InvalidCastException: 
'Unable to cast object of type 'System.__ComObject' to type 'IMalloc'.'. 

    Stack trace:  
at System.Windows.Forms.UnsafeNativeMethods.Shell32.SHGetMalloc(IMalloc[] ppMalloc) 
at System.Windows.Forms.FolderBrowserDialog.GetSHMalloc() 
at System.Windows.Forms.FolderBrowserDialog.RunDialog(IntPtr hWndOwner) 
at System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner) 
at System.Windows.Forms.CommonDialog.ShowDialog() 

संपादित करें: अतिरिक्त जानकारी: मैं केवल इस पुन: पेश करने के लिए जब VS2008 डिबगर में चल कर पाए हैं।

डीबगर से बाहर होने पर, यह मेरे 64 बिट विंडोज 7 पर केवल बहुत ही कम होता है (6 महीने में एक या दो बार हुआ) और फिर से शुरू होने के बाद चला जाता है।

ग्राहक निश्चित रूप से डीबगर में ऐप नहीं चला रहे हैं, इसलिए यह निश्चित रूप से डीबगर से पुन: उत्पन्न होता है। जहाँ तक इस फेंक दिया जा रहा है में अंत में सिर्फ वास्तविक संवाद रिटर्न के बाद ब्लॉक Reflector.Net का उपयोग करने से के रूप में मैं बता सकता हूँ

:

+0

वाह, यह अजीब है। वह कोड पूरी तरह से हानिरहित दिखता है। क्या आपने .NET को अपग्रेड या डाउनग्रेड करने का प्रयास किया था? – Thomas

+0

क्या आप यूआई थ्रेड के अलावा किसी थ्रेड से 'FolderBrowserDialog' को कॉल कर रहे हैं? –

+0

@ थॉमस: नहीं और मैं कोशिश नहीं करूँगा और न ही मैं किसी भी उपयोगकर्ता से – Marek

उत्तर

1

यहाँ विचारों के एक जोड़े है। यहाँ मूल रूप से वह जगह है जहाँ आपकी समस्या हो रही है: अपने सभी अपवाद में संवाद नहीं दिख रहा है ऊपर शायद वास्तविक त्रुटि मास्किंग है

IntPtr pszPath = IntPtr.Zero; 
try 
{ 
    UnsafeNativeMethods.BROWSEINFO lpbi = new UnsafeNativeMethods.BROWSEINFO(); 
    hglobal = Marshal.AllocHGlobal((int) (260 * Marshal.SystemDefaultCharSize)); 
    pszPath = Marshal.AllocHGlobal((int) (260 * Marshal.SystemDefaultCharSize)); 
    ... /*init structure*/ 
    pidl = UnsafeNativeMethods.Shell32.SHBrowseForFolder(lpbi); 
    if (pidl != IntPtr.Zero) 
    { 
     UnsafeNativeMethods.Shell32.SHGetPathFromIDList(pidl, pszPath); 
     ... 
    } 
} 
finally 
{ 
    UnsafeNativeMethods.IMalloc sHMalloc = GetSHMalloc(); /* Boom! */ 
    sHMalloc.Free(zero); 
    ... 

। 'ब्रेक ऑन अपवाद' के साथ चलने का प्रयास करें और टूल्स-> डिबगिंग-> बस मेरा कोड अक्षम करें। कोशिश ब्लॉक में कोड बहुत बुनियादी दिखता है, वे सबसे जोखिम भरा चीज जो कर रहे हैं वह है shell32.dll के SHBrowseForFolder पर PInvoke मुझे आश्चर्य होगा अगर यह 'यादृच्छिक' त्रुटि उत्पन्न कर रहा है।

आप संवाद और केवल समापन पर देख रहे हैं आप तो यह त्रुटि मिलता है तो आप सिर्फ स्मृति लीक की कीमत पर इसे अनदेखा कर सकता है जब ऐसा होता है:

using (FolderBrowserDialog fbd = new FolderBrowserDialog()) 
    { 
     fbd.ShowNewFolderButton = false; 
     DialogResult r; 
     try { r = fbd.ShowDialog(); } 
     catch (InvalidCastException) 
     { r = DialogResult.OK; /* you might check the path first */ } 
     if (fbd.ShowDialog() == DialogResult.OK) 
      ... 
बेशक

आप अपने आप को हमेशा PInvoke the SHBrowseForFolder कर सकते हैं और संवाद वर्ग का उपयोग न करें।

+0

हां, संवाद बंद होने के बाद मुझे यह मिल रहा है। कैच टिप के लिए धन्यवाद, मुझे लगता है कि मुझे इस पथ पर जाना होगा, लेकिन मुझे यकीन नहीं है कि चयनित पाथ सही होगा या नहीं। कल जांच लेंगे। क्या आप दो बार संवाद दिखाने का सुझाव दे रहे हैं? – Marek

+0

क्षमा करें, हाँ दूसरा शो एक बग है। –

0

इस लक्षण, happened to others है लगता है तो कम से कम आप अकेले नहीं हैं ;-)

संभावनाओं के एक जोड़े:

  1. आप के साथ एक एकल थ्रेड अपार्टमेंट में इस चला रहे हैं (यानी [ STATHreadAttribute] प्रवेश बिंदु विधि पर)?
  2. विंडोज़ में अधिकतम पथ लंबाई 260 वर्ण है। क्या FolderBrowserDialog द्वारा उपयोग किया जाने वाला प्रारंभिक पथ इस से अधिक लंबा हो सकता है? यदि आप (कभी-कभी) इसे वीएस डीबग मोड में पुन: पेश कर सकते हैं, तो अपने समाधान को अपने फ़ोल्डर पेड़ में उच्च स्थानांतरित करने का प्रयास करें, इस प्रकार संवाद द्वारा उपयोग किए गए डिफ़ॉल्ट फ़ोल्डर पथ को छोटा करें।
+0

1. बेशक :) 2. नहीं, पथ की लंबाई यहां कोई मुद्दा नहीं है। – Marek

0

यदि आप XP या Windows 2003 का समर्थन करने की आवश्यकता नहीं है तो आप Windows® API Code Pack for Microsoft® का उपयोग करने पर विचार कर सकते हैं। शायद इसका फ़ोल्डर ब्राउज़र संवाद केवल अधिक सुंदर नहीं बल्कि अधिक स्थिर है ...

+0

मुझे WinXP – Marek

0

मैं लगभग अपने प्रोजेक्ट है, जो केवल कभी कभी हुई में एक ही समस्या (यह भी एक InvalidCastException) था।

यह एक धागा है कि एक STAThread के रूप में नहीं चल रहा है से आया है। हालांकि मेरी मुख्य विधि को [STAThread] विशेषता के साथ टैग किया गया था।

तुमने कहा था, कि you'r एक अलग थ्रेड का उपयोग नहीं। लेकिन शायद आपको एसिंक प्रतिनिधि के कारण के बारे में पता नहीं है, जो स्पष्ट रूप से थ्रेड क्लास का उपयोग नहीं करता है, लेकिन एक के रूप में माना जाता है।

यदि आप नए धागे बनाते हैं, (इससे कोई फर्क नहीं पड़ता कि आप इसे थ्रेडपूल या एसिंक प्रतिनिधि के साथ बनाते हैं), वे हमेशा एमटीए थ्रेड होते हैं। तो आपको अपने थ्रेड को स्वयं ही बनाना होगा और इसे STATHread के रूप में स्पष्ट करना होगा।

आप इस तरह कर सकते हैं:

var thread=new Thread(() => method()); 
thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

मुझे लगता है कि आप उस दिशा में खुदाई करने के लिए बग मिल जाना है।

+0

समेत सभी विंडोज संस्करणों का समर्थन करने की आवश्यकता है यह फ़ोल्डर ब्राउज़र संवाद सीधे एक बटन से दिखाया गया है। ईवेंट हैंडलर पर क्लिक करें। कोई प्रतिनिधि/BeginInvokes/... जो थ्रेडिंग समस्या को छुपा सकता है। – Marek

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