6

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か月に1〜2回発生)、再起動後に消えます。

クライアントは確かにデバッガーでアプリを実行していないので、デバッガーから確実に再現できます。

4

3 に答える 3

1

ここにいくつかの考えがあります:

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->Just my code を無効にします。try ブロック内のコードは非常に基本的なものに見えますが、最も危険なのは、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)
            ...

もちろん、いつでも自分でSHBrowseForFolder を PInvoke し、ダイアログ クラスを使用しないことができます。

于 2010-05-11T16:58:10.720 に答える
0

この症状は他の人にも起こっているようですので、少なくともあなたは一人ではありません;-)

いくつかの可能性:

  1. これをシングルスレッドアパートメントで実行していますか(つまり、エントリポイントメソッドの[STAThreadAttribute]を使用)?
  2. Windowsでの最大パス長は260文字です。FolderBrowserDialogによって使用される初期パスはこれより長くなる可能性がありますか?VSデバッグモードでこれを(ときどき)再現できる場合は、ソリューションをフォルダーツリーの上位に移動して、ダイアログで使用されるデフォルトのフォルダーパスを短くしてみてください。
于 2010-05-11T17:19:18.407 に答える
0

プロジェクトでほぼ同じ問題(InvalidCastExceptionも)が発生しましたが、これは時々しか発生しませんでした。

STAThread として実行されていないスレッドからのものです。私の Main メソッドは [STAThread] 属性でタグ付けされていましたが。

あなたは、別のスレッドを使用していないと言いました。しかし、非同期デリゲートは Thread クラスを明示的に使用しないが、1 つとして扱われるため、おそらくあなたは気づいていません。

新しいスレッドを作成する場合 (ThreadPool で作成するか、非同期デリゲートで作成するかは関係ありません)、それらは常に MTA Threadsです。そのため、自分でスレッドを作成し、STAThread として明示的に開始する必要があります。

これは次のように行うことができます:

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

バグを見つけるには、その方向に掘り下げる必要があると思います。

于 2010-05-12T14:31:24.397 に答える