c# - WinForms:为什么在显示文件夹浏览器对话框时出现 InvalidCastException?

标签 c# winforms .net-2.0 folderbrowserdialog

我在显示 FolderBrowserDialog 时随机出现 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 位 Windows 7 上很少发生(6 个月内发生一次或两次)并在重新启动后消失。

客户端肯定不会在调试器中运行该应用程序,因此它肯定可以在调试器之外重现。

最佳答案

这里有一些想法:

据我使用 Reflector.Net 所知,这是在实际对话框返回后立即被抛入 finally block 中的。这基本上是您遇到问题的地方:

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->Just my code。 try block 中的代码看起来非常基本,他们正在做的最危险的事情是对 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自己而不使用对话框类。

关于c# - WinForms:为什么在显示文件夹浏览器对话框时出现 InvalidCastException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2811823/

相关文章:

c# - 无法在 .NET Framework 2.0 中引用 .NET Standard 2.0

c# - 如何向 xaml 中的绑定(bind)添加附加文本(或字符串)

c# - TryParseExact 方法如何在多格式数组中工作

c# - 为什么 DisplayMember 不适用于 ListBox 中手动添加的 DataRow?

c# - 并登录 LinkLabel 文本

c# - 具有嵌入式数据 GridView 更改表的数据中继器

c# - 可滚动面板中的组合框导致问题

C# - 启动/或运行类

c# - 单击启用按钮

c# - 如何检查当前操作是否在对象范围内?