【发布时间】:2021-06-23 16:11:11
【问题描述】:
我正在使用 PowerShell 让用户能够浏览 Node.js 应用程序的文件/文件夹路径(因为到目前为止我还没有找到更好的轻量级替代方案),并且我在处理不支持的可怕、糟糕的可用性FolderBrowserDialog 时遇到了老麻烦:
- 过去的路径
- 访问快速访问项目
- 改变视图
- 排序或过滤项目
- 等等……
标准脚本如下所示:
Function Select-FolderDialog($Description="Select Folder", $RootFolder="MyComputer"){
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$objForm = New-Object System.Windows.Forms.FolderBrowserDialog
$objForm.RootFolder = $RootFolder
$objForm.ShowNewFolderButton = $true
$objForm.Description = "Please choose a folder"
$Show = $objForm.ShowDialog()
If ($Show -eq "OK")
{
Return $objForm.SelectedPath
}
Else
{
Write-Error "Operation cancelled by user."
}
}
$folder = Select-FolderDialog
write-host $folder
我过去曾将Windows API CodePack 用于C# Windows 窗体应用程序,以使用IsFolderPicker = true 创建CommonOpenFileDialog,为我提供OpenFileDialog 的功能和可访问性以及易于使用的托管文件夹浏览器。
在我在这里寻找使用类似方法的方法时,我了解到常规的 FolderBrowserDialog got an upgrade, at least in .Net Core。
嗯,不错哦。
我有什么方法可以从 PowerShell 脚本访问升级版本?
在上面的代码中添加$objForm.AutoUpgradeEnabled = $true 不会改变任何东西(实际上是the default)
(另外,如果有人知道如何以更直接的方式为 Node.js 应用程序提供一个像样的文件夹浏览器对话框,请给我留言^^)
目前的解决方法:
1:滥用 OpenFileDialog
Function Select-FolderDialog($Description="Select Folder", $RootFolder="MyComputer"){
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$objForm = New-Object System.Windows.Forms.OpenFileDialog
$objForm.DereferenceLinks = $true
$objForm.CheckPathExists = $true
$objForm.FileName = "[Select this folder]"
$objForm.Filter = "Folders|`n"
$objForm.AddExtension = $false
$objForm.ValidateNames = $false
$objForm.CheckFileExists = $false
$Show = $objForm.ShowDialog()
If ($Show -eq "OK")
{
Return $objForm.FileName
}
Else
{
Write-Error "Operation cancelled by user."
}
}
$folder = Select-FolderDialog
write-host $folder
这会创建一个继承自更好的FileDialog Class 的对话框,该对话框仅显示文件夹并允许您返回类似“C:\Some dir\Dir I want\[Select this folder]”之类的路径,即使它没有'不存在,然后我可以将其修剪回“C:\Some dir\Dir I want”。
优点:
- 全功能浏览器,根据需要
缺点:
- 文件名字段不能为空。尝试使用类似的东西
换行符导致错误对话框抱怨
无效的文件名和
FileOpenDialog拒绝返回 文件名,即使ValidateNames是false。 - 用户可以在文件名字段中输入任何内容,这可能会导致混淆。
- 当您向上浏览文件夹树时,单击接受按钮(“打开”)只会浏览回之前选择的子目录,即使您取消选择它也是如此
- 您必须修剪掉返回路径的最后一部分,并希望不会因为选择不存在的文件而发生进一步的怪异事件
2:给标准对话框一个编辑控件
# Included the options values from https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfoa
$BIF_RETURNONLYFSDIRS = [uint32]"0x00000001"
$BIF_DONTGOBELOWDOMAIN = [uint32]"0x00000002"
$BIF_STATUSTEXT = [uint32]"0x00000004"
$BIF_RETURNFSANCESTORS = [uint32]"0x00000008"
$BIF_EDITBOX = [uint32]"0x00000010" # <-- this is the important one
$BIF_VALIDATE = [uint32]"0x00000020"
$BIF_NEWDIALOGSTYLE = [uint32]"0x00000040" # <-- this sounds nice, but somehow changes nothing
$BIF_BROWSEINCLUDEURLS = [uint32]"0x00000080"
$BIF_USENEWUI = $BIF_NEWDIALOGSTYLE
$BIF_UAHINT = [uint32]"0x00000100"
$BIF_NONEWFOLDERBUTTON = [uint32]"0x00000200"
$BIF_NOTRANSLATETARGETS = [uint32]"0x00000400"
$BIF_BROWSEFORCOMPUTER = [uint32]"0x00001000"
$BIF_BROWSEFORPRINTER = [uint32]"0x00002000"
$BIF_BROWSEINCLUDEFILES = [uint32]"0x00004000"
$BIF_SHAREABLE = [uint32]"0x00008000"
$BIF_BROWSEFILEJUNCTIONS = [uint32]"0x00010000"
$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, "Select a folder", $options)
if($folder){
write-host $folder.Self.Path()
}
为了清楚起见,我包含了选项,但您可以将上述所有内容硬编码到 $folder = $shell.BrowseForFolder(0, "Select a folder", 98548),这很简洁。
优点:
- 按预期使用文件夹浏览器对话框
- 强大的用户体验
- 可以粘贴路径
- 支持 UNC 路径
- 支持自动完成
缺点:
- 没有带有快速访问项目等的侧面板
- 无法更改视图、排序等
- 没有预览/缩略图
【问题讨论】:
-
您拥有的磁盘存储量令人印象深刻
-
@stuartd :D 我不幸遭遇了想要保存所有内容和对不完整的事情的FOMO。拥有一切感觉很好,但它会变得昂贵,尤其是当您自己进行备份时>:(
标签: .net winforms powershell