在WPF项目中,当打开SHBrowseForFolder,然后“创建新文件夹”时,应用程序崩溃,没有错误

wko9yo5t  于 2023-08-07  发布在  其他
关注(0)|答案(1)|浏览(71)

我在WPF应用程序中集成了下面的代码片段。它可以很好地检索所选文件夹的路径。然而,使用新的UI标志(bi.ulFlags = 0x 00000040;)有一个按钮“创建新文件夹”。当我按下“创建新文件夹”时,应用程序崩溃,没有任何错误或异常,即使使用try... catch也是如此。我不知道在这种情况下该怎么办?
它不会崩溃,在任何其他情况下,它真的缩小到当我按下“创建新文件夹”与新的用户界面。直到我想出一种方法绕过它,我激活了旧UI的标志,它不显示此选项“创建新文件夹”。

public static class NativeMethods
{
    [DllImport("shell32.dll")]
    public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    public static extern bool SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);

    [DllImport("shell32.dll")]
    public static extern void CoTaskMemFree(IntPtr pv);

    [StructLayout(LayoutKind.Sequential)]
    public struct BROWSEINFO
    {
        public IntPtr hwndOwner;
        public IntPtr pidlRoot;
        public IntPtr pszDisplayName;
        public string lpszTitle;
        public uint ulFlags;
        public IntPtr lpfn;
        public IntPtr lParam;
        public int iImage;
    }
}

private string SelectFolder(string windowTitle)
{
    IntPtr buffer = Marshal.AllocHGlobal(260 * Marshal.SystemDefaultCharSize);
    try
    {
        NativeMethods.BROWSEINFO bi = new NativeMethods.BROWSEINFO();
        bi.hwndOwner = new WindowInteropHelper(Application.Current.MainWindow).Handle;
        bi.lpszTitle = windowTitle;
        bi.ulFlags = 0x00000040;//bi.ulFlags = 0x00000000; //bi.ulFlags = 0x00000040; // BIF_USENEWUI, Enable the new UI style

        IntPtr pidl = NativeMethods.SHBrowseForFolder(ref bi);
        StringBuilder path = new StringBuilder(260);

        if (pidl != IntPtr.Zero)
        {
            bool success = NativeMethods.SHGetPathFromIDList(pidl, path);

            if (success)
            {
                string folderPath = path.ToString();
                return folderPath;
            }                    
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error: " + ex.Message); 
    }
    finally
    {
        Marshal.FreeHGlobal(buffer);
    }

    return null; 
}

字符串
激活本机代码调试后,我在Windows应用程序事件查看器中发现了此错误:
出现故障的应用程序名称:app.exe,版本:1.0.0.0,时间戳:0x 8 f5958 c 0故障模块名称:未知,版本:0.0.0.0,时间戳:0x 00000000异常代码:0xc 000041 d故障偏移:0x 04 c 00002故障进程ID:0x 31 d8故障应用程序开始时间:0x 01 d9 c 0600 eb 1538 e故障应用程序路径:C:\app.exe故障模块路径:未知报告ID:1f 791 fc 1-e8 c6 - 481 e-af 3a-5a 2a 80 d 70 d8 c故障包全名:正在出错的包相关应用程序ID:

0tdrvxhp

0tdrvxhp1#

我的实现似乎比你的更具戏剧性。这对我来说非常有效:

using System;
    using System.Runtime.InteropServices;
    
    namespace application
    {
        public static class BrowseForFolderConstants
        {
            public const int 
                WM_USER = 0x400;
    
            public const int 
                BFFM_INITIALIZED = 1;
    
            public const int 
                BFFM_SELCHANGED = 2;
    
            public const int 
                BFFM_VALIDATEFAILEDA = 3;
    
            public const int 
                BFFM_VALIDATEFAILEDW = 4;
    
            public const int 
                BFFM_IUNKNOWN = 5;
    
            public const int 
                BFFM_SETSTATUSTEXTA = WM_USER + 100;
    
            public const int 
                BFFM_ENABLEOK = WM_USER + 101;
    
            public const int 
                BFFM_SETSELECTIONA = WM_USER + 102;
    
            public const int 
                BFFM_SETSELECTIONW = WM_USER + 103;
    
            public const int 
                BFFM_SETSTATUSTEXTW = WM_USER + 104;
    
            public const int 
                BFFM_SETOKTEXT = WM_USER + 105;
    
            public const int 
                BFFM_SETEXPANDED = WM_USER + 106;
    
            public const uint 
                BIF_NEWDIALOGSTYLE = 0x0040;
    
            public const uint 
                BIF_SHAREABLE = 0x8000;
    
            public static string 
                folderpath = string.Empty;
        }
    
        public class BrowseForFolder
        {
            [DllImport("shell32.dll")]
            static extern IntPtr SHBrowseForFolder
                (ref BROWSEINFO browserinfo);
    
            [DllImport("shell32.dll", CharSet = CharSet.Unicode)]        
            static extern bool SHGetPathFromIDList
                (IntPtr browseforfolder, 
                    IntPtr folderpath);
    
            [DllImport("user32.dll", PreserveSig = true)]
            public static extern IntPtr SendMessage
                (HandleRef handle, 
                    uint message, 
                        int longparameters, 
                            IntPtr wordparameters);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage
                (HandleRef handle, 
                    int message, 
                        int longparameters, 
                            string wordparameters);
    
            public delegate int BrowseCallBackProc
                (IntPtr handle, 
                    int message, 
                        IntPtr longparameters, 
                            IntPtr wordparameters);
    
            struct BROWSEINFO
            {
                public IntPtr 
                    Owner;
    
                public IntPtr 
                    Root;
    
                public string 
                    DisplayName;
    
                public string 
                    Title;
    
                public uint 
                    Flags;
    
                public BrowseCallBackProc 
                    CallBack;
    
                public IntPtr 
                    Paramters;
    
                public int 
                    Image;
            }
    
            public int OnBrowseEvent
                (IntPtr handle, 
                    int message, 
                        IntPtr browserforfolder, 
                            IntPtr folderdata)
            {
                switch (message) 
                {
                    case BrowseForFolderConstants
                            .BFFM_INITIALIZED: 
                        {
                            SendMessage(new 
                                HandleRef(null, handle),
                                    BrowseForFolderConstants.BFFM_SETSELECTIONW, 1, 
                                        BrowseForFolderConstants.folderpath);
                            break;
                        }
    
                    case BrowseForFolderConstants
                            .BFFM_SELCHANGED: 
                        {
                            IntPtr folderpath = 
                                Marshal.AllocHGlobal
                                    (260 * Marshal.SystemDefaultCharSize);
    
                            if (SHGetPathFromIDList
                                    (browserforfolder, folderpath))
    
                                SendMessage(new 
                                    HandleRef(null, handle),
                                        BrowseForFolderConstants.BFFM_SETSTATUSTEXTW, 0, 
                                            folderpath);
    
                            Marshal
                                .FreeHGlobal
                                    (folderpath);
                            break;
                        }
                }
    
                return 0;
            }
    
            public string SelectFolder
                (string caption, 
                    string initialPath, 
                        IntPtr parentHandle)
            {
                BrowseForFolderConstants.folderpath = 
                    initialPath;
    
                string selectedpath = 
                    string.Empty;
    
                IntPtr folderpath = 
                    Marshal.AllocHGlobal(256); 
    
                IntPtr broweforfolder = 
                    IntPtr.Zero;
    
                BROWSEINFO browserinfo = 
                    new()
                    {
                        Owner = 
                            parentHandle,
    
                        Root = 
                            IntPtr.Zero,
    
                        Title = 
                            caption,
    
                        Flags = 
                            BrowseForFolderConstants
                                .BIF_NEWDIALOGSTYLE 
                                    | BrowseForFolderConstants
                                        .BIF_SHAREABLE,
    
                        CallBack = 
                            new BrowseCallBackProc
                                (OnBrowseEvent),
    
                        Paramters = 
                            IntPtr.Zero,
    
                        Image = 
                            0
                    };
    
                broweforfolder = 
                    SHBrowseForFolder
                        (ref browserinfo);
    
                if (SHGetPathFromIDList
                        (broweforfolder, folderpath))
    
                    selectedpath = 
                        Marshal.PtrToStringAuto
                            (folderpath);
    
                Marshal
                    .FreeCoTaskMem
                        (broweforfolder);
    
                return 
                    selectedpath;
            }
        }
    }

    // The code below is called from a method somewhere

            BrowseForFolder browser = 
                new();

            HwndSource source = 
                HwndSource.FromHwnd
                    (new WindowInteropHelper
                        (UI.Application).Handle);                        

            browser.SelectFolder(
                "Export report(s) to the selected folder", 
                    "This PC", source.Handle);

字符串

相关问题