Last active
January 14, 2024 05:43
-
-
Save IMJLA/1d570aa2bb5c30215c222e7a5e5078fd to your computer and use it in GitHub Desktop.
A folder browser dialog with an address bar in native PowerShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$AssemblyFullName = 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' | |
$Assembly = [System.Reflection.Assembly]::Load($AssemblyFullName) | |
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog | |
$OpenFileDialog.AddExtension = $false | |
$OpenFileDialog.CheckFileExists = $false | |
$OpenFileDialog.DereferenceLinks = $true | |
$OpenFileDialog.Filter = "Folders|`n" | |
$OpenFileDialog.Multiselect = $false | |
$OpenFileDialog.Title = "Select folder" | |
$OpenFileDialogType = $OpenFileDialog.GetType() | |
$FileDialogInterfaceType = $Assembly.GetType('System.Windows.Forms.FileDialogNative+IFileDialog') | |
$IFileDialog = $OpenFileDialogType.GetMethod('CreateVistaDialog',@('NonPublic','Public','Static','Instance')).Invoke($OpenFileDialog,$null) | |
$null = $OpenFileDialogType.GetMethod('OnBeforeVistaDialog',@('NonPublic','Public','Static','Instance')).Invoke($OpenFileDialog,$IFileDialog) | |
[uint32]$PickFoldersOption = $Assembly.GetType('System.Windows.Forms.FileDialogNative+FOS').GetField('FOS_PICKFOLDERS').GetValue($null) | |
$FolderOptions = $OpenFileDialogType.GetMethod('get_Options',@('NonPublic','Public','Static','Instance')).Invoke($OpenFileDialog,$null) -bor $PickFoldersOption | |
$null = $FileDialogInterfaceType.GetMethod('SetOptions',@('NonPublic','Public','Static','Instance')).Invoke($IFileDialog,$FolderOptions) | |
$VistaDialogEvent = [System.Activator]::CreateInstance($AssemblyFullName,'System.Windows.Forms.FileDialog+VistaDialogEvents',$false,0,$null,$OpenFileDialog,$null,$null).Unwrap() | |
[uint32]$AdviceCookie = 0 | |
$AdvisoryParameters = @($VistaDialogEvent,$AdviceCookie) | |
$AdviseResult = $FileDialogInterfaceType.GetMethod('Advise',@('NonPublic','Public','Static','Instance')).Invoke($IFileDialog,$AdvisoryParameters) | |
$AdviceCookie = $AdvisoryParameters[1] | |
$Result = $FileDialogInterfaceType.GetMethod('Show',@('NonPublic','Public','Static','Instance')).Invoke($IFileDialog,[System.IntPtr]::Zero) | |
$null = $FileDialogInterfaceType.GetMethod('Unadvise',@('NonPublic','Public','Static','Instance')).Invoke($IFileDialog,$AdviceCookie) | |
if ($Result -eq [System.Windows.Forms.DialogResult]::OK) { | |
$FileDialogInterfaceType.GetMethod('GetResult',@('NonPublic','Public','Static','Instance')).Invoke($IFileDialog,$null) | |
} | |
Write-Output $OpenFileDialog.FileName |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@DanGough thank you!
Interesting, I can't reproduce $Result being 0 on my Windows 10 machine but I suspect we have an environment difference; I certainly didn't do thorough testing. (also why PS7 doesn't work, thank you for posting a modern alternative)
I did need to invoke the Advise method, although I'm pretty sure I could have dumped $AdviseResult to $null instead since it is unused, and that would make PSScriptAnalyzer happy.