title: Use the upgraded FolderBrowserDialog ("Vista style") in Powershell
body: <p>I'm using <strong>PowerShell</strong> to enable the user to browse for file/folder paths for a Node.js app (because I haven't found a better light-weight alternative so far), and I'm having the age old trouble of dealing with the horrible, poor usability <code>FolderBrowserDialog</code> that doesn't support:</p>
  <ul>
  <li>pasting paths</li>
  <li>accessing Quick Access items</li>
  <li>changing the view</li>
  <li>Sorting or filtering items</li>
  <li>etc...</li>
  </ul>
  <p><a href="https://i.stack.imgur.com/yeVJe.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/yeVJe.png" alt="The bad dialog" /></a></p>
  <p>The standard script looks like this:</p>
  <pre><code>Function Select-FolderDialog($Description=&quot;Select Folder&quot;, $RootFolder=&quot;MyComputer&quot;){
      [System.Reflection.Assembly]::LoadWithPartialName(&quot;System.windows.forms&quot;) | Out-Null     
          
      $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
      $objForm.RootFolder = $RootFolder
      $objForm.ShowNewFolderButton = $true
      $objForm.Description = &quot;Please choose a folder&quot;
      $Show = $objForm.ShowDialog()
      If ($Show -eq &quot;OK&quot;)
      {
          Return $objForm.SelectedPath
      }
      Else
      {
          Write-Error &quot;Operation cancelled by user.&quot;
      }
  }
  $folder = Select-FolderDialog
  write-host $folder
  </code></pre>
  <p>I've used the <a href="https://www.nuget.org/packages/Microsoft-WindowsAPICodePack-Core/" rel="nofollow noreferrer">Windows API CodePack</a> for C# Windows Forms apps in the past to create a <code>CommonOpenFileDialog</code> with <code>IsFolderPicker = true</code>, giving me the features and accessibility of the <code>OpenFileDialog</code> with the ease of use of a managed folder browser.
  <a href="https://i.stack.imgur.com/7tI3K.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7tI3K.png" alt="Better, but non-standard dialog" /></a></p>
  <p>in my search of a way to use something like this here as well, I learned that the regular FolderBrowserDialog <a href="https://github.com/dotnet/winforms/issues/2993#issuecomment-601544256" rel="nofollow noreferrer">got an upgrade, at least in .Net Core</a>.<br />
  Huh, that's neat.</p>
  <h2><strong>Is there any way I can access the upgraded version</strong> from a PowerShell script?</h2>
  <p>Adding <code>$objForm.AutoUpgradeEnabled = $true</code> to the above code doesn't change anything (and is indeed <a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.folderbrowserdialog.autoupgradeenabled?view=net-5.0#System_Windows_Forms_FolderBrowserDialog_AutoUpgradeEnabled" rel="nofollow noreferrer">the default</a>)<br />
  (Also, if somebody has a good idea how to provide a decent Folder Browser Dialog to a Node.js app in a more direct way, drop me a comment ^^)</p>
  <h2>Workarounds so far:</h2>
  <h3>1: Abuse an OpenFileDialog</h3>
  <pre><code>Function Select-FolderDialog($Description=&quot;Select Folder&quot;, $RootFolder=&quot;MyComputer&quot;){
      [System.Reflection.Assembly]::LoadWithPartialName(&quot;System.windows.forms&quot;) | Out-Null     
  
      $objForm = New-Object System.Windows.Forms.OpenFileDialog
      $objForm.DereferenceLinks = $true
      $objForm.CheckPathExists = $true
      $objForm.FileName = &quot;[Select this folder]&quot;
      $objForm.Filter = &quot;Folders|`n&quot;
      $objForm.AddExtension = $false
      $objForm.ValidateNames = $false
      $objForm.CheckFileExists = $false
      $Show = $objForm.ShowDialog()
      If ($Show -eq &quot;OK&quot;)
      {
          Return $objForm.FileName
      }
      Else
      {
          Write-Error &quot;Operation cancelled by user.&quot;
      }
  }
  
  $folder = Select-FolderDialog
  write-host $folder
  </code></pre>
  <p>This creates a dialog inheriting from the much nicer <a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog?view=net-5.0" rel="nofollow noreferrer">FileDialog Class</a>, which displays only folders and enables you to return a path like &quot;C:\Some dir\Dir I want\[Select this folder]&quot;, even when it doesn't exist, which I can then trim back to &quot;C:\Some dir\Dir I want&quot;.</p>
  <p><strong>Pros:</strong></p>
  <ul>
  <li>Full featured browser, as desired</li>
  </ul>
  <p><strong>Cons:</strong></p>
  <ul>
  <li>The file name field can't be empty. Trying to use something like a
  newline character results in an error dialog complaining about an
  invalid filename and the <code>FileOpenDialog</code> refusing to return the
  filename, even though <code>ValidateNames</code> is <code>false</code>.</li>
  <li>The user could enter anything in the filename field, which could lead to confusion.</li>
  <li>When you navigate up a folder tree, clicking the accept button (&quot;Open&quot;) simply browses back to the previously selected child directory, even if you deselect it</li>
  <li>You have to trim away the last part of the returned path and hope that no further weirdness happened as a result of selecting a non-existent file</li>
  </ul>
  <h3>2: Give a standard dialog an Edit control</h3>
  <p>Using the <a href="https://docs.microsoft.com/en-us/windows/win32/shell/shell-browseforfolder" rel="nofollow noreferrer">Shell.BrowseForFolder</a> method</p>
  <pre><code># Included the options values from https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfoa
  $BIF_RETURNONLYFSDIRS = [uint32]&quot;0x00000001&quot;
  $BIF_DONTGOBELOWDOMAIN = [uint32]&quot;0x00000002&quot;
  $BIF_STATUSTEXT = [uint32]&quot;0x00000004&quot;
  $BIF_RETURNFSANCESTORS = [uint32]&quot;0x00000008&quot;
  $BIF_EDITBOX = [uint32]&quot;0x00000010&quot; # &lt;-- this is the important one
  $BIF_VALIDATE = [uint32]&quot;0x00000020&quot;
  $BIF_NEWDIALOGSTYLE = [uint32]&quot;0x00000040&quot; # &lt;-- this sounds nice, but somehow changes nothing
  $BIF_BROWSEINCLUDEURLS = [uint32]&quot;0x00000080&quot;
  $BIF_USENEWUI = $BIF_NEWDIALOGSTYLE
  $BIF_UAHINT = [uint32]&quot;0x00000100&quot;
  $BIF_NONEWFOLDERBUTTON = [uint32]&quot;0x00000200&quot;
  $BIF_NOTRANSLATETARGETS = [uint32]&quot;0x00000400&quot;
  $BIF_BROWSEFORCOMPUTER = [uint32]&quot;0x00001000&quot;
  $BIF_BROWSEFORPRINTER = [uint32]&quot;0x00002000&quot;
  $BIF_BROWSEINCLUDEFILES = [uint32]&quot;0x00004000&quot;
  $BIF_SHAREABLE = [uint32]&quot;0x00008000&quot;
  $BIF_BROWSEFILEJUNCTIONS = [uint32]&quot;0x00010000&quot;
  
  $options = 0
  $options += $BIF_STATUSTEXT
  $options += $BIF_EDITBOX
  $options += $BIF_VALIDATE
  $options += $BIF_NEWDIALOGSTYLE
  $options += $BIF_BROWSEINCLUDEURLS
  $options += $BIF_SHAREABLE
  $options += $BIF_BROWSEFILEJUNCTIONS
  
  $shell = new-object -comobject Shell.Application
  $folder = $shell.BrowseForFolder(0, &quot;Select a folder&quot;, $options)
  if($folder){
      write-host $folder.Self.Path()
  }
  </code></pre>
  <p>I included the options for clarity, but you could hard-code all of the the above into <code>$folder = $shell.BrowseForFolder(0, &quot;Select a folder&quot;, 98548)</code>, which is neat.<br />
  <a href="https://i.stack.imgur.com/bnz41.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/bnz41.png" alt="Look mom, auto-completing UNC paths" /></a><br />
  <strong>Pros:</strong></p>
  <ul>
  <li>Using the folder browser dialog as intended</li>
  <li>Robust UX</li>
  <li>Can paste a path</li>
  <li>Supports UNC paths</li>
  <li>Supports auto-complete</li>
  </ul>
  <p><strong>Cons:</strong></p>
  <ul>
  <li>No side panel with Quick Access Items, etc</li>
  <li>Can't change view, sort, etc</li>
  <li>No previews/thumbnails</li>
  </ul>