2010-05-11 37 views
5

Tôi nhận ngẫu nhiên InvalidCastException khi hiển thị FolderBrowserDialog và nhiều khách hàng đã báo cáo điều này.WinForms: Tại sao tôi nhận được InvalidCastException khi hiển thị hộp thoại trình duyệt thư mục?

Tôi chưa thể tìm thấy bất kỳ nội dung nào có liên quan trên internet. Có ai biết điều gì gây ra điều này/làm thế nào để sửa lỗi này?

Mã của tôi:

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

Stack trace:

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() 

EDIT: Thông tin thêm: Tôi đã có thể tái sản xuất này chỉ khi chạy trong trình gỡ lỗi VS2008.

Khi hết trình gỡ rối, nó chỉ xảy ra rất hiếm (xảy ra một hoặc hai lần trong 6 tháng) trên Windows 7 64 bit của tôi và biến mất sau khi khởi động lại.

Khách hàng chắc chắn không chạy ứng dụng trong trình gỡ lỗi để chắc chắn có thể sao chép được từ trình gỡ rối.

+0

Ồ, thật kỳ lạ. Mã đó trông hoàn toàn vô hại. Bạn đã thử nâng cấp hoặc hạ cấp .NET chưa? – Thomas

+0

Bạn có đang gọi 'FolderBrowserDialog' từ một chuỗi khác với chuỗi giao diện người dùng không? –

+0

@Thomas: Không và tôi sẽ không thử điều đó cũng như không thể yêu cầu bất kỳ người dùng nào làm điều đó – Marek

Trả lời

1

Dưới đây là một vài suy nghĩ:

Theo như tôi có thể nói từ việc sử dụng Reflector.Net này là nhận được ném vào khối finally ngay sau khi trở về hộp thoại thực tế. Đây là cơ bản nơi bạn gặp phải sự cố:

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); 
    ... 

Nếu bạn không thấy hộp thoại ở tất cả ngoại lệ trên có thể che giấu lỗi thực. Hãy thử chạy với 'Break on Exception' và vô hiệu hóa Tools-> Debugging-> Chỉ cần mã của tôi. Các mã trong khối thử trông khá cơ bản, điều nguy hiểm nhất mà họ đang làm là PInvoke trên SHBrowseForFolder shell32.dll của tôi sẽ ngạc nhiên nếu nó tạo ra một lỗi 'ngẫu nhiên'.

Nếu bạn đang nhìn thấy hộp thoại và chỉ khi đóng cửa để bạn nhận được lỗi này thì bạn chỉ có thể bỏ qua nó tại các chi phí của rò rỉ bộ nhớ khi điều này xảy ra:

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) 
      ... 

Tất nhiên bạn luôn có thể PInvoke the SHBrowseForFolder bản thân và không sử dụng lớp hộp thoại.

+0

Có, tôi nhận được thông báo này sau khi hộp thoại đóng. Cảm ơn bạn đã bắt đầu, tôi nghĩ rằng tôi sẽ phải đi con đường này nhưng tôi không chắc chắn nếu các lựa chọnPath sẽ là chính xác. Sẽ kiểm tra ngày mai. Bạn có đề xuất hiển thị hộp thoại hai lần không? – Marek

+0

Xin lỗi, yea show thứ hai là một lỗi. –

0

triệu chứng này dường như có happened to others, vì vậy ít nhất bạn không đơn độc ;-)

Một vài khả năng:

  1. Bạn chạy này trong một căn hộ đơn luồng (tức là với [ STAThreadAttribute] về phương pháp điểm nhập)?
  2. Độ dài đường dẫn tối đa trong Windows là 260 ký tự. Đường dẫn ban đầu được sử dụng bởi FolderBrowserDialog có dài hơn điều này không? Nếu bạn có thể (đôi khi) tái tạo điều này trong chế độ gỡ lỗi VS, hãy thử di chuyển giải pháp của bạn cao hơn trong cây thư mục của bạn, do đó rút ngắn đường dẫn thư mục mặc định được hộp thoại sử dụng.
+0

1. tất nhiên :) 2. không, chiều dài đường dẫn không phải là vấn đề ở đây. – Marek

0

Bạn có thể cân nhắc sử dụng Windows® API Code Pack for Microsoft® nếu bạn không cần hỗ trợ XP hoặc Windows 2003. Có thể hộp thoại trình duyệt thư mục của nó không chỉ đẹp hơn mà còn ổn định hơn ...

+0

Tôi cần hỗ trợ tất cả các phiên bản cửa sổ, bao gồm cả WinXP – Marek

0

Tôi đã gần như cùng một Vấn đề (cũng là một InvalidCastException) trong dự án của tôi, đôi khi chỉ xảy ra.

Nó đến từ Chủ đề chưa được chạy dưới dạng STAThread. Mặc dù phương pháp chính của tôi đã được gắn thẻ với thuộc tính [STAThread].

Bạn đã nói, rằng bạn không sử dụng một chuỗi riêng biệt. Nhưng có lẽ you'r không nhận thức được, bởi vì một đại biểu async, mà không rõ ràng sử dụng một lớp Thread, nhưng được coi là một.

Nếu bạn tạo chủ đề mới, (không quan trọng nếu bạn tạo nó với ThreadPool hoặc đại biểu async), chúng luôn là MTA Threads. Vì vậy, bạn phải tạo chủ đề của bạn bằng cách riêng của bạn và bắt đầu nó rõ ràng như là một STAThread.

Bạn có thể làm như thế này:

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

Tôi nghĩ rằng bạn phải đào theo hướng đó để tìm ra lỗi.

+0

Hộp thoại trình duyệt thư mục này được hiển thị trực tiếp từ trình xử lý sự kiện button.Click. Không có đại biểu/BeginInvokes/... có thể ẩn một vấn đề luồng. – Marek

Các vấn đề liên quan