WinForms: Why am I getting an InvalidCastException when a browser dialog is displayed?

I accidentally get an InvalidCastException when showing a FolderBrowserDialog, and many clients have reported this as well.

I could not find anything relevant on the Internet. Does anyone know what causes this / how to fix it?

My code is:

        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: Additional info: I was able to reproduce this only when working in the VS2008 debugger.

When starting the debugger, this happens very rarely (happens once or twice after 6 months) on my 64-bit Windows 7 and leaves after rebooting.

Clients, of course, do not run the application in the debugger, so it certainly plays from the debugger.

+5
4

:

Reflector.Net, finally . , :

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

, , . "Break on Exception" Tools- > Debugging- > . try , , , PInvoke shell32.dll SHBrowseForFolder. , "" .

, , :

    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 .

+1

, , , , , ; -)

:

  • (.. [STAThreadAttribute] )?
  • Windows - 260 . , FolderBrowserDialog, ? () VS, , , .
0

Windows® API Code Pack Microsoft®, XP Windows 2003. , , ...

0

( InvalidCastException) , .

, STAThread. Main [STAThread].

, . , , , - async, Thread, .

If you create new threads (it doesn’t matter if you create it using ThreadPool or an async delegate), they are always MTA threads . Thus, you need to create your own thread and start it explicitly as STAThread.

You can do it as follows:

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

I think you need to dig in this direction to find a mistake.

0
source

All Articles