private void SetPropertiesFromDialogResult(NativeFolderBrowserDialog dialog)
        {
            dialog.GetResults(out IShellItemArray resultsArray);

            DirectoryNames.Clear();

            resultsArray.GetCount(out uint count);
            for (uint i = 0; i < count; i++)
            {
                resultsArray.GetItemAt(i, out IShellItem result);

                HResult hr = result.GetDisplayName(NativeMethods.SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out IntPtr ppszName);

                if (hr == HResult.Ok && ppszName != IntPtr.Zero)
                {
                    DirectoryNames.Add(Marshal.PtrToStringAuto(ppszName));
                }

                Marshal.FreeCoTaskMem(ppszName);
            }

            if (DirectoryNames.Count > 0)
            {
                DirectoryName = DirectoryNames[0];
            }
        }
        private void SetDialogProperties(NativeFolderBrowserDialog dialog)
        {
            var flags = NativeMethods.FOS.FOS_PICKFOLDERS |
                        NativeMethods.FOS.FOS_FORCEFILESYSTEM |
                        NativeMethods.FOS.FOS_PATHMUSTEXIST |
                        NativeMethods.FOS.FOS_FILEMUSTEXIST |
                        NativeMethods.FOS.FOS_NOVALIDATE;

            if (MultiSelect)
            {
                flags |= NativeMethods.FOS.FOS_ALLOWMULTISELECT;
            }

            dialog.SetOptions(flags);

            if (!string.IsNullOrWhiteSpace(InitialDirectory))
            {
                if (!Directory.Exists(InitialDirectory))
                {
                    try
                    {
                        // C:\Folder\File.exe becomes C:\Folder
                        InitialDirectory = Path.GetDirectoryName(InitialDirectory) ?? "";
                        if (!Directory.Exists(InitialDirectory))
                        {
                            return;
                        }
                    }
                    // Fix: we weren't checking for invalid path names
                    catch
                    {
                        return;
                    }
                }

                var guid = new Guid(Guids.IShellItem);

                HResult result = NativeMethods.SHCreateItemFromParsingName(
                    InitialDirectory,
                    IntPtr.Zero,
                    ref guid,
                    out object item);

                if (result != HResult.Ok)
                {
                    throw Marshal.GetExceptionForHR((int)result) ?? new Exception("Argh!\r\n" + result);
                }

                dialog.SetFolder((IShellItem)item);
            }
        }
        protected override bool RunDialog(IntPtr hwndOwner)
        {
            NativeFolderBrowserDialog?dialog = null;

            try
            {
                dialog = new NativeFolderBrowserDialog();

                SetDialogProperties(dialog);

                HResult result = dialog.Show(hwndOwner);
                if (result != HResult.Ok)
                {
                    // ReSharper disable once ConvertIfStatementToReturnStatement
                    if (result == HResult.Canceled)
                    {
                        return(false);
                    }
                    else
                    {
                        // I think I want to just ignore exceptions and cancel if anything at all went wrong, but
                        // just in case I change my mind, here's the line to use:
                        // throw Marshal.GetExceptionForHR((int)result);
                        return(false);
                    }
                }

                SetPropertiesFromDialogResult(dialog);

                return(true);
            }
            finally
            {
                if (dialog != null)
                {
                    Marshal.FinalReleaseComObject(dialog);
                }
            }
        }