How do I use OpenFileDialog to select a folder?

C#.NetWinformsDialogOpenfiledialog

C# Problem Overview


I was going to use the following project: https://github.com/scottwis/OpenFileOrFolderDialog

However, there's a problem: it uses the GetOpenFileName function and OPENFILENAME structure. OPENFILENAME has the member named templateID, which is the identifier for dialog template. And the project contains the res1.rc file and the templated dialog init, too. But I couldn't figure out how to attach this file to my C# project.

Is there a better way to use an OpenFileDialog to select folders?

C# Solutions


Solution 1 - C#

Basically you need the FolderBrowserDialog class:

> Prompts the user to select a folder. This class cannot be inherited.

Example:

using(var fbd = new FolderBrowserDialog())
{
    DialogResult result = fbd.ShowDialog();

    if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
    {
        string[] files = Directory.GetFiles(fbd.SelectedPath);

        System.Windows.Forms.MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
    }
}

If you work in WPF you have to add the reference to System.Windows.Forms.

you also have to add using System.IO for Directory class

Solution 2 - C#

As a note for future users who would like to avoid using FolderBrowserDialog, Microsoft once released an API called the WindowsAPICodePack that had a helpful dialog called CommonOpenFileDialog, that could be set into a IsFolderPicker mode. The API is available from Microsoft as a NuGet package.

This is all I needed to install and use the CommonOpenFileDialog. (NuGet handled the dependencies)

Install-Package Microsoft.WindowsAPICodePack-Shell

For the include line:

using Microsoft.WindowsAPICodePack.Dialogs;

Usage:

CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = "C:\\Users";
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
    MessageBox.Show("You selected: " + dialog.FileName);
}

Solution 3 - C#

There is a hackish solution using OpenFileDialog where ValidateNames and CheckFileExists are both set to false and FileName is given a mock value to indicate that a directory is selected.

I say hack because it is confusing to users about how to select a folder. They need to be in the desired folder and then just press Open while file name says "Folder Selection."

C# Folder selection dialog

This is based on Select file or folder from the same dialog by Denis Stankovski.

OpenFileDialog folderBrowser = new OpenFileDialog();
// Set validate names and check file exists to false otherwise windows will
// not let you select "Folder Selection."
folderBrowser.ValidateNames = false;
folderBrowser.CheckFileExists = false;
folderBrowser.CheckPathExists = true;
// Always default to Folder Selection.
folderBrowser.FileName = "Folder Selection.";
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
    string folderPath = Path.GetDirectoryName(folderBrowser.FileName);
    // ...
}

Solution 4 - C#

Here is a pure C# version, nuget-free, that should work with all versions of .NET (including .NET Core, .NET 5, WPF, Winforms, etc.) and uses Windows Vista (and higher) IFileDialog interface with the FOS_PICKFOLDERS options so it has the nice folder picker Windows standard UI.

I have also added WPF's Window type support but this is optional, the WPF-marked lines can just be removed.

usage:

var dlg = new FolderPicker();
dlg.InputPath = @"c:\windows\system32";
if (dlg.ShowDialog() == true)
{
	MessageBox.Show(dlg.ResultPath);
}

code:

	using System;
	using System.Diagnostics;
	using System.Runtime.InteropServices;
	using System.Runtime.InteropServices.ComTypes;
	using System.Windows; // for WPF support
	using System.Windows.Interop;  // for WPF support

	public class FolderPicker
	{
		public virtual string ResultPath { get; protected set; }
		public virtual string ResultName { get; protected set; }
		public virtual string InputPath { get; set; }
		public virtual bool ForceFileSystem { get; set; }
		public virtual string Title { get; set; }
		public virtual string OkButtonLabel { get; set; }
		public virtual string FileNameLabel { get; set; }

		protected virtual int SetOptions(int options)
		{
			if (ForceFileSystem)
			{
				options |= (int)FOS.FOS_FORCEFILESYSTEM;
			}
			return options;
		}

		// for WPF support
		public bool? ShowDialog(Window owner = null, bool throwOnError = false)
		{
			owner ??= Application.Current.MainWindow;
			return ShowDialog(owner != null ? new WindowInteropHelper(owner).Handle : IntPtr.Zero, throwOnError);
		}

		// for all .NET
		public virtual bool? ShowDialog(IntPtr owner, bool throwOnError = false)
		{
			var dialog = (IFileOpenDialog)new FileOpenDialog();
			if (!string.IsNullOrEmpty(InputPath))
			{
				if (CheckHr(SHCreateItemFromParsingName(InputPath, null, typeof(IShellItem).GUID, out var item), throwOnError) != 0)
					return null;

				dialog.SetFolder(item);
			}

			var options = FOS.FOS_PICKFOLDERS;
			options = (FOS)SetOptions((int)options);
			dialog.SetOptions(options);

			if (Title != null)
			{
				dialog.SetTitle(Title);
			}

			if (OkButtonLabel != null)
			{
				dialog.SetOkButtonLabel(OkButtonLabel);
			}

			if (FileNameLabel != null)
			{
				dialog.SetFileName(FileNameLabel);
			}

			if (owner == IntPtr.Zero)
			{
				owner = Process.GetCurrentProcess().MainWindowHandle;
				if (owner == IntPtr.Zero)
				{
					owner = GetDesktopWindow();
				}
			}

			var hr = dialog.Show(owner);
			if (hr == ERROR_CANCELLED)
				return null;

			if (CheckHr(hr, throwOnError) != 0)
				return null;

			if (CheckHr(dialog.GetResult(out var result), throwOnError) != 0)
				return null;

			if (CheckHr(result.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out var path), throwOnError) != 0)
				return null;

			ResultPath = path;

			if (CheckHr(result.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING, out path), false) == 0)
			{
				ResultName = path;
			}
			return true;
		}

		private static int CheckHr(int hr, bool throwOnError)
		{
			if (hr != 0)
			{
				if (throwOnError)
					Marshal.ThrowExceptionForHR(hr);
			}
			return hr;
		}

		[DllImport("shell32")]
		private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);

		[DllImport("user32")]
		private static extern IntPtr GetDesktopWindow();

#pragma warning disable IDE1006 // Naming Styles
		private const int ERROR_CANCELLED = unchecked((int)0x800704C7);
#pragma warning restore IDE1006 // Naming Styles

		[ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] // CLSID_FileOpenDialog
		private class FileOpenDialog
		{
		}

		[ComImport, Guid("42f85136-db7e-439c-85f1-e4075d135fc8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IFileOpenDialog
		{
			[PreserveSig] int Show(IntPtr parent); // IModalWindow
			[PreserveSig] int SetFileTypes();  // not fully defined
			[PreserveSig] int SetFileTypeIndex(int iFileType);
			[PreserveSig] int GetFileTypeIndex(out int piFileType);
			[PreserveSig] int Advise(); // not fully defined
			[PreserveSig] int Unadvise();
			[PreserveSig] int SetOptions(FOS fos);
			[PreserveSig] int GetOptions(out FOS pfos);
			[PreserveSig] int SetDefaultFolder(IShellItem psi);
			[PreserveSig] int SetFolder(IShellItem psi);
			[PreserveSig] int GetFolder(out IShellItem ppsi);
			[PreserveSig] int GetCurrentSelection(out IShellItem ppsi);
			[PreserveSig] int SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
			[PreserveSig] int GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
			[PreserveSig] int SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
			[PreserveSig] int SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
			[PreserveSig] int SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
			[PreserveSig] int GetResult(out IShellItem ppsi);
			[PreserveSig] int AddPlace(IShellItem psi, int alignment);
			[PreserveSig] int SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
			[PreserveSig] int Close(int hr);
			[PreserveSig] int SetClientGuid();  // not fully defined
			[PreserveSig] int ClearClientData();
			[PreserveSig] int SetFilter([MarshalAs(UnmanagedType.IUnknown)] object pFilter);
			[PreserveSig] int GetResults([MarshalAs(UnmanagedType.IUnknown)] out object ppenum);
			[PreserveSig] int GetSelectedItems([MarshalAs(UnmanagedType.IUnknown)] out object ppsai);
		}

		[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IShellItem
		{
			[PreserveSig] int BindToHandler(); // not fully defined
			[PreserveSig] int GetParent(); // not fully defined
			[PreserveSig] int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
			[PreserveSig] int GetAttributes();  // not fully defined
			[PreserveSig] int Compare();  // not fully defined
		}

        #pragma warning disable CA1712 // Do not prefix enum values with type name
		private enum SIGDN : uint
		{
			SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
			SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
			SIGDN_FILESYSPATH = 0x80058000,
			SIGDN_NORMALDISPLAY = 0,
			SIGDN_PARENTRELATIVE = 0x80080001,
			SIGDN_PARENTRELATIVEEDITING = 0x80031001,
			SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
			SIGDN_PARENTRELATIVEPARSING = 0x80018001,
			SIGDN_URL = 0x80068000
		}

		[Flags]
		private enum FOS
		{
			FOS_OVERWRITEPROMPT = 0x2,
			FOS_STRICTFILETYPES = 0x4,
			FOS_NOCHANGEDIR = 0x8,
			FOS_PICKFOLDERS = 0x20,
			FOS_FORCEFILESYSTEM = 0x40,
			FOS_ALLNONSTORAGEITEMS = 0x80,
			FOS_NOVALIDATE = 0x100,
			FOS_ALLOWMULTISELECT = 0x200,
			FOS_PATHMUSTEXIST = 0x800,
			FOS_FILEMUSTEXIST = 0x1000,
			FOS_CREATEPROMPT = 0x2000,
			FOS_SHAREAWARE = 0x4000,
			FOS_NOREADONLYRETURN = 0x8000,
			FOS_NOTESTFILECREATE = 0x10000,
			FOS_HIDEMRUPLACES = 0x20000,
			FOS_HIDEPINNEDPLACES = 0x40000,
			FOS_NODEREFERENCELINKS = 0x100000,
			FOS_OKBUTTONNEEDSINTERACTION = 0x200000,
			FOS_DONTADDTORECENT = 0x2000000,
			FOS_FORCESHOWHIDDEN = 0x10000000,
			FOS_DEFAULTNOMINIMODE = 0x20000000,
			FOS_FORCEPREVIEWPANEON = 0x40000000,
			FOS_SUPPORTSTREAMABLEITEMS = unchecked((int)0x80000000)
		}
        #pragma warning restore CA1712 // Do not prefix enum values with type name
	}

result:

enter image description here

Solution 5 - C#

Sounds to me like you're just after the FolderBrowserDialog.

Solution 6 - C#

Strange that so much answers/votes, but no one add the following code as an answer:

using (var opnDlg = new OpenFileDialog()) //ANY dialog
{ 
    //opnDlg.Filter = "Png Files (*.png)|*.png";
    //opnDlg.Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv"

    if (opnDlg.ShowDialog() == DialogResult.OK)
    {
        //opnDlg.SelectedPath -- your result
    }
}

Solution 7 - C#

Here is another solution, that has all the source available in a single, simple ZIP file.

It presents the OpenFileDialog with additional windows flags that makes it work like the Windows 7+ Folder Selection dialog.

Per the website, it is public domain: "There’s no license as such as you are free to take and do with the code what you will."

Archive.org links:

Solution 8 - C#

Take a look at the Ookii Dialogs libraries which has an implementation of a folder browser dialog for Windows Forms and WPF respectively.

enter image description here

> Ookii.Dialogs.WinForms > > https://github.com/augustoproiete/ookii-dialogs-winforms


> Ookii.Dialogs.Wpf > > https://github.com/augustoproiete/ookii-dialogs-wpf

Solution 9 - C#

this should be the most obvious and straight forward way

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{

   System.Windows.Forms.DialogResult result = dialog.ShowDialog();

   if(result == System.Windows.Forms.DialogResult.OK)
   {
      selectedFolder = dialog.SelectedPath;
   }

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYunView Question on Stackoverflow
Solution 1 - C#Ionică BizăuView Answer on Stackoverflow
Solution 2 - C#JoeView Answer on Stackoverflow
Solution 3 - C#Daniel BallingerView Answer on Stackoverflow
Solution 4 - C#Simon MourierView Answer on Stackoverflow
Solution 5 - C#Simon WhiteheadView Answer on Stackoverflow
Solution 6 - C#Andrew____Pls_Support_UkraineView Answer on Stackoverflow
Solution 7 - C#Ben KeeneView Answer on Stackoverflow
Solution 8 - C#C. Augusto ProieteView Answer on Stackoverflow
Solution 9 - C#AHMView Answer on Stackoverflow