Windows 批处理脚本中的文件/文件夹选择器对话框

发布于 2025-01-20 22:46:01 字数 93 浏览 0 评论 0 原文

在输入文件位置直到运行时才知道的情况下,使用GUI进行文件选择输入会降低用户错误的可能性。

有没有办法从Windows批处理脚本调用文件/文件夹选择器对话框?

In situations where input file location is not known until runtime, using a GUI for file selection input reduces the likelihood of user error.

Is there a way to invoke a file/folder chooser dialog from a Windows batch script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

初心未许 2025-01-27 22:46:01

文件浏览器

更新 2016.3.20

由于 PowerShell 是当今所有现代 Windows 安装的本机组件,因此我宣布不再需要 C# 回退。如果您仍然需要它来实现 Vista 或 XP 兼容性,我将其移至新答案。从这次编辑开始,我将脚本重写为 Batch + PowerShell 混合体,并结合了执行多重选择的功能。它更容易阅读并根据需要进行调整。

<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console

@echo off
setlocal

for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
    echo You chose %%~I
)
goto :EOF

: end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

这会出现一个文件选择器对话框。

文件选择器对话框

选择的结果将 You Choose C:\Users\me\Desktop\tmp.txt 输出到控制台。如果您想强制选择单个文件,只需将 $f.Multiselect 属性更改为 $false 即可。

PowerShell 从 Just Tinkering 博客< /a>.请参阅 OpenFileDialog 类< /a> 您可以设置的其他属性的文档,例如 TitleInitialDirectory

文件夹浏览器

更新2015.08.10:

因为已经有一个COM方法用于调用文件夹选择器 ,构建一个可以打开文件夹选择器并输出路径的 PowerShell 单行代码非常容易。

:: fchooser.bat
:: launches a folder chooser and outputs choice to the console
:: https://stackoverflow.com/a/15885133/1683264

@echo off
setlocal

set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose a folder.',0,0).self.path""

for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"

setlocal enabledelayedexpansion
echo You chose !folder!
endlocal

在 BrowseForFolder() 方法中,第四个参数指定层次结构的根。有关以下列表,请参阅 ShellSpecialFolderConstants有效值。

这会出现一个文件夹选择器对话框。

输入图片此处描述

选择的结果将 You Choose C:\Users\me\Desktop 输出到控制台。

有关其他属性,请参阅 FolderBrowserDialog 类文档您可以设置,例如RootFolder。我原来的 .NET System.Windows.Forms PowerShell 和 C# 解决方案可以在 修订版 4 中找到如果需要的话,可以参考这个答案,但是这个 COM 方法更容易阅读和维护。

File Browser

Update 2016.3.20:

Since PowerShell is a native component of all modern Windows installations nowadays, I'm declaring the C# fallback as no longer necessary. If you still need it for Vista or XP compatibility, I moved it to a new answer. Starting with this edit, I'm rewriting the script as a Batch + PowerShell hybrid and incorporating the ability to perform multi-select. It's profoundly easier to read and to tweak as needed.

<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console

@echo off
setlocal

for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
    echo You chose %%~I
)
goto :EOF

: end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

This results in a file chooser dialog.

File chooser dialog

The result of a selection outputs You chose C:\Users\me\Desktop\tmp.txt to the console. If you want to force single file selection, just change the $f.Multiselect property to $false.

PowerShell taken command from the Just Tinkering Blog. See the OpenFileDialog Class documentation for other properties you can set, such as Title and InitialDirectory.

Folder Browser

Update 2015.08.10:

Since there is already a COM method for invoking a folder chooser, it's pretty easy to build a PowerShell one-liner that can open the folder chooser and output the path.

:: fchooser.bat
:: launches a folder chooser and outputs choice to the console
:: https://stackoverflow.com/a/15885133/1683264

@echo off
setlocal

set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose a folder.',0,0).self.path""

for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"

setlocal enabledelayedexpansion
echo You chose !folder!
endlocal

In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.

This results in a folder chooser dialog.

enter image description here

The result of a selection outputs You chose C:\Users\me\Desktop to the console.

See the FolderBrowserDialog class documentation for other properties you can set, such as RootFolder. My original .NET System.Windows.Forms PowerShell and C# solutions can be found in revision 4 of this answer if needed, but this COM method is much easier to read and maintain.

极致的悲 2025-01-27 22:46:01

这应该适用于 XP 及以上版本,并且不需要 hibrid 文件,它只需使用长命令行运行 mshta:

@echo off
set dialog="about:<input type=file id=FILE><script>FILE.click();new ActiveXObject
set dialog=%dialog%('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);
set dialog=%dialog%close();resizeTo(0,0);</script>"

for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set "file=%%p"
echo selected  file is : "%file%"
pause

This should work from XP upwards and does'nt require an hibrid file, it just runs mshta with a long command line:

@echo off
set dialog="about:<input type=file id=FILE><script>FILE.click();new ActiveXObject
set dialog=%dialog%('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);
set dialog=%dialog%close();resizeTo(0,0);</script>"

for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set "file=%%p"
echo selected  file is : "%file%"
pause
甜宝宝 2025-01-27 22:46:01

Windows脚本主机


文件选择

Windows XP有一个神秘的 useraccounts.commondialog wsh对象和JScript启动文件选择提示。显然,那是被视为安全风险并在Vista中删除。


但是,文件夹选择

,但是,wsh shell.application对象 browseforfolder 方法仍然允许创建文件夹选择对话框。这是一个混合批次 + JScript示例。用 .bat 扩展名保存。

@if (@a==@b) @end /*

:: fchooser2.bat
:: batch portion

@echo off
setlocal

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0"') do (
    echo You chose %%I
)

goto :EOF

:: JScript portion */

var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, "Please choose a folder.", 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');

“文件夹选择对话框”

browseforfolder()方法中。参见

Windows Script Host


File Selection

Windows XP had a mysterious UserAccounts.CommonDialog WSH object which allowed VBScript and JScript to launch the file selection prompt. Apparently, that was deemed a security risk and removed in Vista.


Folder Selection

However, the WSH Shell.Application object BrowseForFolder method will still allow the creation of a folder selection dialog. Here's a hybrid batch + JScript example. Save it with a .bat extension.

@if (@a==@b) @end /*

:: fchooser2.bat
:: batch portion

@echo off
setlocal

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0"') do (
    echo You chose %%I
)

goto :EOF

:: JScript portion */

var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, "Please choose a folder.", 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');

folder selection dialog

In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.

一指流沙 2025-01-27 22:46:01

可以使用纯批处理进行文件 /文件夹选择,如下所示。当然,感觉和外观并不像GUI那样令人愉悦,但是它的效果很好,我认为它比GUI版本更容易使用。选择方法基于Choice命令,因此它需要在不包括它并稍微修改其参数的Windows版本中下载它。当然,可以轻松地修改代码以使用Set /P而不是选择,但是此更改将消除非常简单且快速的选择方法,该方法仅需要一个键键即可进行导航和选择。

@echo off
setlocal

rem Select a file or folder browsing a directory tree
rem Antonio Perez Ayala

rem Usage examples of SelectFileOrFolder subroutine:

call :SelectFileOrFolder file=
echo/
echo Selected file from *.* = "%file%"
pause

call :SelectFileOrFolder file=*.bat
echo/
echo Selected Batch file = "%file%"
pause

call :SelectFileOrFolder folder=/F
echo/
echo Selected folder = "%folder%"
pause

goto :EOF


:SelectFileOrFolder resultVar [ "list of wildcards" | /F ]

setlocal EnableDelayedExpansion

rem Process parameters
set "files=*.*"
if "%~2" neq "" (
   if /I "%~2" equ "/F" (set "files=") else set "files=%~2"
)

rem Set the number of lines per page, max 34
set "pageSize=30"
set "char=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

rem Load current directory contents
set "name[1]=<DIR>  .."
:ProcessThisDir
set "numNames=1"
for /D %%a in (*) do (
   set /A numNames+=1
   set "name[!numNames!]=<DIR>  %%a"
)
for %%a in (%files%) do (
   set /A numNames+=1
   set "name[!numNames!]=       %%a"
)
set /A numPages=(numNames-1)/pageSize+1

rem Show directory contents, one page at a time
set start=1
:ShowPage
set /A page=(start-1)/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
echo Page %page%/%numPages% of %CD%
echo/
if %start% equ 1 (set base=0) else set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
   for %%j in (!j!) do echo     !char:~%%j,1! -  !name[%%i]!
   set /A j+=1
)
echo/

rem Assemble the get option message
if %start% equ 1 (set "mssg=: ") else (set "mssg= (0=Previous page")
if %end% lss %numNames% (
   if "%mssg%" equ ": " (set "mssg= (") else set "mssg=%mssg%, "
   set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq ": " set "mssg=%mssg%): "

:GetOption
choice /C "%char%" /N /M "Select desired item%mssg%"
if %errorlevel% equ 1 (
   rem "0": Previous page or Parent directory
   if %start% gtr 1 (
      set /A start-=pageSize
      goto ShowPage
   ) else (
      cd ..
      goto ProcessThisDir
   )
)
if %errorlevel% equ 36 (
   rem "Z": Next page, if any
   if %end% lss %numNames% (
      set /A start+=pageSize
      goto ShowPage
   ) else (
      goto GetOption
   )
)
if %errorlevel% gtr %lastOpt% goto GetOption
set /A option=start+%errorlevel%-1-base
if %option% gtr %numNames% goto GetOption
if defined files (
   if "!name[%option%]:~0,5!" neq "<DIR>" goto endSelect
) else (
   choice /C OS /M "Open or Select '!name[%option%]:~7!' folder"
   if errorlevel 2 goto endSelect
)
cd "!name[%option%]:~7!"
goto ProcessThisDir

:endSelect
rem Return selected file/folder
for %%a in ("!name[%option%]:~7!") do set "result=%%~Fa"
endlocal & set "%~1=%result%
exit /B

A file / folder selection may be done with pure Batch, as shown below. Of course, the feel and look is not as pleasant as a GUI, but it works very well and in my opinion it is easier to use than the GUI version. The selection method is based on CHOICE command, so it would require to download it in the Windows versions that don't include it and slightly modify its parameters. Of course, the code may be easily modified in order to use SET /P instead of CHOICE, but this change would eliminate the very simple and fast selection method that only requires one keypress to navigate and select.

@echo off
setlocal

rem Select a file or folder browsing a directory tree
rem Antonio Perez Ayala

rem Usage examples of SelectFileOrFolder subroutine:

call :SelectFileOrFolder file=
echo/
echo Selected file from *.* = "%file%"
pause

call :SelectFileOrFolder file=*.bat
echo/
echo Selected Batch file = "%file%"
pause

call :SelectFileOrFolder folder=/F
echo/
echo Selected folder = "%folder%"
pause

goto :EOF


:SelectFileOrFolder resultVar [ "list of wildcards" | /F ]

setlocal EnableDelayedExpansion

rem Process parameters
set "files=*.*"
if "%~2" neq "" (
   if /I "%~2" equ "/F" (set "files=") else set "files=%~2"
)

rem Set the number of lines per page, max 34
set "pageSize=30"
set "char=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

rem Load current directory contents
set "name[1]=<DIR>  .."
:ProcessThisDir
set "numNames=1"
for /D %%a in (*) do (
   set /A numNames+=1
   set "name[!numNames!]=<DIR>  %%a"
)
for %%a in (%files%) do (
   set /A numNames+=1
   set "name[!numNames!]=       %%a"
)
set /A numPages=(numNames-1)/pageSize+1

rem Show directory contents, one page at a time
set start=1
:ShowPage
set /A page=(start-1)/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
echo Page %page%/%numPages% of %CD%
echo/
if %start% equ 1 (set base=0) else set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
   for %%j in (!j!) do echo     !char:~%%j,1! -  !name[%%i]!
   set /A j+=1
)
echo/

rem Assemble the get option message
if %start% equ 1 (set "mssg=: ") else (set "mssg= (0=Previous page")
if %end% lss %numNames% (
   if "%mssg%" equ ": " (set "mssg= (") else set "mssg=%mssg%, "
   set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq ": " set "mssg=%mssg%): "

:GetOption
choice /C "%char%" /N /M "Select desired item%mssg%"
if %errorlevel% equ 1 (
   rem "0": Previous page or Parent directory
   if %start% gtr 1 (
      set /A start-=pageSize
      goto ShowPage
   ) else (
      cd ..
      goto ProcessThisDir
   )
)
if %errorlevel% equ 36 (
   rem "Z": Next page, if any
   if %end% lss %numNames% (
      set /A start+=pageSize
      goto ShowPage
   ) else (
      goto GetOption
   )
)
if %errorlevel% gtr %lastOpt% goto GetOption
set /A option=start+%errorlevel%-1-base
if %option% gtr %numNames% goto GetOption
if defined files (
   if "!name[%option%]:~0,5!" neq "<DIR>" goto endSelect
) else (
   choice /C OS /M "Open or Select '!name[%option%]:~7!' folder"
   if errorlevel 2 goto endSelect
)
cd "!name[%option%]:~7!"
goto ProcessThisDir

:endSelect
rem Return selected file/folder
for %%a in ("!name[%option%]:~7!") do set "result=%%~Fa"
endlocal & set "%~1=%result%
exit /B
滥情哥ㄟ 2025-01-27 22:46:01

在批处理中直接运行 PowerShell 命令的其他解决方案

rem preparation command
set pwshcmd=powershell -noprofile -command "&{[System.Reflection.Assembly]::LoadWithPartialName('System.windows.forms') | Out-Null;$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog; $OpenFileDialog.ShowDialog()|out-null; $OpenFileDialog.FileName}"

rem exec commands powershell and get result in FileName variable
for /f "delims=" %%I in ('%pwshcmd%') do set "FileName=%%I"

echo %FileName%

Other solution with direct run PowerShell command in Batch

rem preparation command
set pwshcmd=powershell -noprofile -command "&{[System.Reflection.Assembly]::LoadWithPartialName('System.windows.forms') | Out-Null;$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog; $OpenFileDialog.ShowDialog()|out-null; $OpenFileDialog.FileName}"

rem exec commands powershell and get result in FileName variable
for /f "delims=" %%I in ('%pwshcmd%') do set "FileName=%%I"

echo %FileName%
山田美奈子 2025-01-27 22:46:01

批次 + powershell + C#polyglot解决方案

这与批次 + powerShell hybrid ,但是有C#shartback re re re Re - 用于XP和Vista兼容性。已在 xnirting /a>。

<# : chooser_XP_Vista.bat
:: // launches a File... Open sort of file chooser and outputs choice(s) to the console
:: // https://stackoverflow.com/a/36156326/1683264

@echo off
setlocal enabledelayedexpansion

rem // Does powershell.exe exist within %PATH%?

for %%I in ("powershell.exe") do if "%%~$PATH:I" neq "" (
    set chooser=powershell -noprofile "iex (${%~f0} | out-string)"
) else (

    rem // If not, compose and link C# application to open file browser dialog

    set "chooser=%temp%\chooser.exe"

    >"%temp%\c.cs" (
        echo using System;
        echo using System.Windows.Forms;
        echo class dummy {
        echo    public static void Main^(^) {
        echo        OpenFileDialog f = new OpenFileDialog^(^);
        echo        f.InitialDirectory = Environment.CurrentDirectory;
        echo        f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
        echo        f.ShowHelp = true;
        echo        f.Multiselect = true;
        echo        f.ShowDialog^(^);
        echo        foreach ^(String filename in f.FileNames^) {
        echo            Console.WriteLine^(filename^);
        echo        }
        echo    }
        echo }
    )
    for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
        if not exist "!chooser!" "%%I" /nologo /out:"!chooser!" "%temp%\c.cs" 2>NUL
    )
    del "%temp%\c.cs"
    if not exist "!chooser!" (
        echo Error: Please install .NET 2.0 or newer, or install PowerShell.
        goto :EOF
    )
)

rem // Do something with the chosen file(s)
for /f "delims=" %%I in ('%chooser%') do (
    echo You chose %%~I
)

rem // comment this out to keep chooser.exe in %temp% for faster subsequent runs
del "%temp%\chooser.exe" >NUL 2>NUL

goto :EOF
:: // end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

对于用于XP或Vista的文件夹选择器,请使用 wsh解决方案 npocmaka的HTA解决方案

Batch + PowerShell + C# polyglot solution

This is the same solution as the Batch + PowerShell hybrid, but with the C# fallback stuff re-added for XP and Vista compatibility. Multiple file selection has been added at xNightmare67x's request.

<# : chooser_XP_Vista.bat
:: // launches a File... Open sort of file chooser and outputs choice(s) to the console
:: // https://stackoverflow.com/a/36156326/1683264

@echo off
setlocal enabledelayedexpansion

rem // Does powershell.exe exist within %PATH%?

for %%I in ("powershell.exe") do if "%%~$PATH:I" neq "" (
    set chooser=powershell -noprofile "iex (${%~f0} | out-string)"
) else (

    rem // If not, compose and link C# application to open file browser dialog

    set "chooser=%temp%\chooser.exe"

    >"%temp%\c.cs" (
        echo using System;
        echo using System.Windows.Forms;
        echo class dummy {
        echo    public static void Main^(^) {
        echo        OpenFileDialog f = new OpenFileDialog^(^);
        echo        f.InitialDirectory = Environment.CurrentDirectory;
        echo        f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
        echo        f.ShowHelp = true;
        echo        f.Multiselect = true;
        echo        f.ShowDialog^(^);
        echo        foreach ^(String filename in f.FileNames^) {
        echo            Console.WriteLine^(filename^);
        echo        }
        echo    }
        echo }
    )
    for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
        if not exist "!chooser!" "%%I" /nologo /out:"!chooser!" "%temp%\c.cs" 2>NUL
    )
    del "%temp%\c.cs"
    if not exist "!chooser!" (
        echo Error: Please install .NET 2.0 or newer, or install PowerShell.
        goto :EOF
    )
)

rem // Do something with the chosen file(s)
for /f "delims=" %%I in ('%chooser%') do (
    echo You chose %%~I
)

rem // comment this out to keep chooser.exe in %temp% for faster subsequent runs
del "%temp%\chooser.exe" >NUL 2>NUL

goto :EOF
:: // end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

For a folder chooser for XP or Vista, use either the WSH solution or npocmaka's HTA solution.

留蓝 2025-01-27 22:46:01

还有两种方法。

1.使用混合.bat/hta(必须保存为bat)脚本。它可以使用vbscript或javascript,但示例是javascrtipt。不创建临时文件。选择文件夹不是这样简单,需要外部 javascript 库,但选择文件很容易

<!-- : starting html comment

:: FileSelector.bat
@echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
    set "file=%%~fp"
)
echo/
if not "%file%" == "" (
    echo selected  file is : %file%
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
    <script language='javascript'>
    function pipeFile() {

         var file=document.getElementById('file').value;
         var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
         close(fso.Write(file));

    }
    </script>
<input type='file' name='file' size='30'>
</input><hr><button onclick='pipeFile()'>Submit</button>
</body>

1.1 - 无需提交 rojo 提出的表单(参见评论):

<!-- : starting html comment

:: FileSelector.bat
@echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
    set "file=%%~fp"
)
echo/
if not "%file%" == "" (
    echo selected  file is : "%file%"
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
    <script language='javascript'>
    function pipeFile() {

         var file=document.getElementById('file').value;
         var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
         close(fso.Write(file));

    }
    </script>
<input id='file' type='file' name='file' size='30' onchange='pipeFile()' >
</input>
<hr>
<button onclick='pipeFile()'>Submit</button>
<script>document.getElementById('file').click();</script>
</body>

2.由于您已经使用 powershell/net,您可以创建自编译jscript.net Hybrid。它不需要临时 cs 文件进行编译,而是直接使用内置的 jscrript.net 编译器。也不需要 powershell,代码的可读性要高得多:

@if (@X)==(@Y) @end /* JScript comment
@echo off

:: FolderSelectorJS.bat
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

for /f "tokens=* delims=" %%p in ('"%~n0.exe"') do (
    set "folder=%%p"
)
if not "%folder%" == "" ( 
    echo selected folder  is %folder%
)

endlocal & exit /b %errorlevel%

*/

import System;
import System.Windows.Forms;

var  f=new FolderBrowserDialog();
f.SelectedPath=System.Environment.CurrentDirectory;
f.Description="Please choose a folder.";
f.ShowNewFolderButton=true;
if( f.ShowDialog() == DialogResult.OK ){
    Console.Write(f.SelectedPath);
}

Two more ways.

1.Using a hybrid .bat/hta (must be saved as a bat) script .It can use vbscript or javascript but the example is with javascrtipt.Does not create temp files.Selecting folder is not so easy and will require an external javascript libraries , but selecting file is easy

<!-- : starting html comment

:: FileSelector.bat
@echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
    set "file=%%~fp"
)
echo/
if not "%file%" == "" (
    echo selected  file is : %file%
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
    <script language='javascript'>
    function pipeFile() {

         var file=document.getElementById('file').value;
         var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
         close(fso.Write(file));

    }
    </script>
<input type='file' name='file' size='30'>
</input><hr><button onclick='pipeFile()'>Submit</button>
</body>

1.1 - without submit form proposed by rojo (see comments):

<!-- : starting html comment

:: FileSelector.bat
@echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
    set "file=%%~fp"
)
echo/
if not "%file%" == "" (
    echo selected  file is : "%file%"
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
    <script language='javascript'>
    function pipeFile() {

         var file=document.getElementById('file').value;
         var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
         close(fso.Write(file));

    }
    </script>
<input id='file' type='file' name='file' size='30' onchange='pipeFile()' >
</input>
<hr>
<button onclick='pipeFile()'>Submit</button>
<script>document.getElementById('file').click();</script>
</body>

2.As you already using powershell/net you can create selfcompiled jscript.net hybrid.It will not require temp cs file for compilation and will directly use the built-in jscrript.net compiler.There's no need of powershell too and the code is far more readable:

@if (@X)==(@Y) @end /* JScript comment
@echo off

:: FolderSelectorJS.bat
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

for /f "tokens=* delims=" %%p in ('"%~n0.exe"') do (
    set "folder=%%p"
)
if not "%folder%" == "" ( 
    echo selected folder  is %folder%
)

endlocal & exit /b %errorlevel%

*/

import System;
import System.Windows.Forms;

var  f=new FolderBrowserDialog();
f.SelectedPath=System.Environment.CurrentDirectory;
f.Description="Please choose a folder.";
f.ShowNewFolderButton=true;
if( f.ShowDialog() == DialogResult.OK ){
    Console.Write(f.SelectedPath);
}
一城柳絮吹成雪 2025-01-27 22:46:01

我什至会留下一个“回声”来验证此代码中的多项选择是否有效

echo off
set cmd=Add-Type -AssemblyName System.Windows.Forms;$f=new-object                 Windows.Forms.OpenFileDialog;$f.InitialDirectory=        [environment]::GetFolderPath('Desktop');$f.Filter='Text Files(*.txt)^|*.txt^|All         Files(*.*)^|*.*';$f.Multiselect=$true;[void]$f.ShowDialog();if($f.Multiselect)        {$f.FileNames}else{$f.FileName}
set pwshcmd=powershell -noprofile -command "&{%cmd%}"
for /f "tokens=* delims=" %%I in ('%pwshcmd%') do call :sum "%%I" ret
echo =========
echo --%ret%--
pause
exit /B
:sum [mud] [ret]
echo "%~1"
set FileName=%FileName% "%~1"
set ret=%FileName%
exit /B

I will leave an 'echo' even to verify that multiple choice works in this code

echo off
set cmd=Add-Type -AssemblyName System.Windows.Forms;$f=new-object                 Windows.Forms.OpenFileDialog;$f.InitialDirectory=        [environment]::GetFolderPath('Desktop');$f.Filter='Text Files(*.txt)^|*.txt^|All         Files(*.*)^|*.*';$f.Multiselect=$true;[void]$f.ShowDialog();if($f.Multiselect)        {$f.FileNames}else{$f.FileName}
set pwshcmd=powershell -noprofile -command "&{%cmd%}"
for /f "tokens=* delims=" %%I in ('%pwshcmd%') do call :sum "%%I" ret
echo =========
echo --%ret%--
pause
exit /B
:sum [mud] [ret]
echo "%~1"
set FileName=%FileName% "%~1"
set ret=%FileName%
exit /B
悸初 2025-01-27 22:46:01

我已经写了自己的便携式解决方案:

您可以从此处下载可执行文件:

该实用程序对WXWIDGETS 3.1.x有依赖性,因此您实际上可以为其他操作系统构建它。

I has been wrote my own portable solution:
https://github.com/andry81/contools/tree/HEAD/Utilities/src/_gui/wxFileDialog/

You can download executable from here:
https://github.com/andry81/contools/tree/HEAD/Utilities/bin/contools/wxFileDialog.exe

The utility has dependency on wxWidgets 3.1.x, so you can actually build it for other operating systems.

不忘初心 2025-01-27 22:46:01

罗霍,谢谢你的代码。有用。

一个小注意事项:
对于“浏览文件夹”代码,用户可以单击 X,但根本不选择文件夹。对于这种情况,我会添加:

if not defined folder (goto :noFolderSelected)

另外,对于 BrowseForFolder() 方法,我建议第四个参数为 0x11。这将显示所有驱动器。

rojo, thanks for the code. It works.

A small note:
For the "Browse for Folder" code, a user may click the X and NOT select a folder at all. For this case, I would add:

if not defined folder (goto :noFolderSelected)

Also, for the BrowseForFolder() method, I recommend the 4th argument to be 0x11. This will display all drives.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文