File / folder chooser dialog from a Windows batch script

后端 未结 9 580
一生所求
一生所求 2020-11-22 11:58

Typically, asking the user to supply a file name to a batch script is a messy affair, requiring no misspellings, quotes around paths with spaces, and so forth. Unfortunatel

相关标签:
9条回答
  • 2020-11-22 12:59

    File Browser

    Update 2016.3.20:

    Since PowerShell is a native component of pretty much 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
    :: https://stackoverflow.com/a/15885133/1683264
    
    @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

    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 command mercilessly leeched 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.

    0 讨论(0)
  • 2020-11-22 12:59

    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%
    
    0 讨论(0)
  • 2020-11-22 13:01

    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
        :sum [mud] [ret]
        echo "%~1"
        set FileName=%FileName% "%~1"
        set ret=%FileName%
        exit /B
    
    0 讨论(0)
提交回复
热议问题