使用PowerShell/C#从cmd批处理中打开“保存文件”对话框

6
我正在尝试从Windows批处理脚本中获取基于GUI的保存文件对话框。我希望在保存和取消按钮左侧有一个新建文件夹按钮,而且没有预定义的文件类型。因此,它可能需要设置为所有文件。
类似于这个示例:Save Dialog (忽略左上角的按钮)
我已经找到了一个不错的解决方案,来自顶部答案,在这里打开文件: File / folder chooser dialog from a Windows batch script 最重要的是,我希望能够设置路径和文件名为它们自己的变量。以"Hello World"作为输出示例。
echo Hello World > %variable.path%%variable.file%

下面的例子是从链接帖子中直接引用的。
:: chooser.bat
:: launches a File... Open sort of file chooser and outputs choice to the console

@echo off
setlocal enabledelayedexpansion

:: Does powershell.exe exist within %PATH%?
for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
set chooser=powershell "Add-Type -AssemblyName System.windows.forms|Out-Null;$f=New-    Object System.Windows.Forms.OpenFileDialog;$f.InitialDirectory='%cd%';$f.Filter='Text Files     (*.txt)|*.txt|All Files (*.*)|*.*';$f.showHelp=$true;$f.ShowDialog()|Out-Null;$f.FileName"
) 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;using System.Windows.Forms;
>>"%temp%\c.cs" echo class dummy{
>>"%temp%\c.cs" echo public static void Main^(^){
>>"%temp%\c.cs" echo OpenFileDialog f=new OpenFileDialog^(^);
>>"%temp%\c.cs" echo f.InitialDirectory=Environment.CurrentDirectory;
>>"%temp%\c.cs" echo f.Filter="Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
>>"%temp%\c.cs" echo f.ShowHelp=true;
>>"%temp%\c.cs" echo f.ShowDialog^(^);
>>"%temp%\c.cs" echo Console.Write^(f.FileName^);}}
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
)
)

:: capture choice to a variable
for /f "delims=" %%I in ('%chooser%') do set "filename=%%I"

echo You chose %filename%

:: Clean up the mess
del "%temp%\chooser.exe" 2>NUL
    goto :EOF

我已经尝试将上面的示例调整为“另存为”工作,但我不理解得足够好。这就是为什么我一开始使用批处理脚本而不是更高级的编程语言的原因。
我的理解是它是Windows批处理脚本,如果PowerShell存在,它会调用PowerShell,否则调用.net。然后,如果两者都不存在,我将使用我的现有代码作为替代方案。替代方案只需手动输入完整路径。
echo Set path to file:
echo Path and file cannot contain any spaces. e.g. c:\folder_name\file.ext
echo Be sure you include the filename.
SET /P path1=">"?
cls
echo path set to: %path1%
pause
cls
goto :eof

我本来想在现有的帖子上提问。但是根据网站规则,这是不允许的。所以我另外发了一个问题。欢迎任何帮助或见解。
感谢您的时间和努力。
2个回答

7

下面是一个使用Windows表单(SaveFileDialog 类)的示例。

注意:你不需要使用按钮来创建一个新目录,因为你可以右键单击文件面板来完成。

Clear-Host
Add-Type -AssemblyName system.Windows.Forms
$saveFile = New-Object System.Windows.Forms.SaveFileDialog

$saveFile.Filter = "All files (*.*)|*.*"
$saveFile.FilterIndex = 2
$saveFile.RestoreDirectory = $true

$rc = $saveFile.ShowDialog()
if ($rc -eq [System.Windows.Forms.DialogResult]::OK)
{
  $saveFile.FileName
  [System.Windows.Forms.MessageBox]::Show("You can save $($saveFile.FileName)", "Ok")
}

注意,当消息框弹出时,它的“确定”按钮并不会出现在Windows的顶部。


谢谢,感激不尽。我已经自己解决了。不过我想我将在不久的将来转向C#。批处理似乎几乎需要一个临时的绕路方法来完成几乎所有任务。 - Terus

1
我设法自己让它工作了。虽然没有我想要用于创建新文件夹的按钮。右键单击需要更多步骤,并强制使用鼠标。而按钮可以编程为使用ALT+N进行调用。尽管如此,我基本上拥有了最初寻求的代码。
:: chooser.bat
:: launches a save file dialog and outputs choice to the console
@echo off
setlocal enabledelayedexpansion

:: Does powershell.exe exist within %PATH%?
for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
    set chooser=powershell "Add-Type -AssemblyName System.windows.forms|Out-Null;$f=New-Object System.Windows.Forms.SaveFileDialog;$f.InitialDirectory='%cd%';$f.Filter='All Files (*.*)|*.*';$f.showHelp=$true;$f.ShowDialog()|Out-Null;$f.FileName"
) 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;using System.Windows.Forms;
    >>"%temp%\c.cs" echo class dummy{
    >>"%temp%\c.cs" echo public static void Main^(^){
    >>"%temp%\c.cs" echo SaveFileDialog f=new SaveFileDialog^(^);
    >>"%temp%\c.cs" echo f.InitialDirectory=Environment.CurrentDirectory;
    >>"%temp%\c.cs" echo f.Filter="All Files (*.*)|*.*";
    >>"%temp%\c.cs" echo f.ShowHelp=true;
    >>"%temp%\c.cs" echo f.ShowDialog^(^);
    >>"%temp%\c.cs" echo Console.Write^(f.FileName^);}}
    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
    )
)

:: capture choice to a variable
for /f "delims=" %%I in ('%chooser%') do set "filename=%%I"

echo You chose %filename%
pause

:: Clean up the mess
del "%temp%\chooser.exe" 2>NUL
goto :EOF

Save Dialog


我的解决方案更短,我有2个问题:为什么你要将PowerShell代码封装到CMD代码中?为什么要在PowerShell中编译C#,当你可以直接使用它内联(Add-Type),或者像你的情况一样,在不使用C#的情况下简单地使用.NET类? - JPBlanc
这个目的是在Windows批处理脚本(.bat文件)中打开一个对话框。我不是那个将标题更改为PowerShell而不是批处理的人。我的结果几乎是从链接帖子中找到的代码的直接副本,并在此引用。至于C#部分,我不是很确定。但我确实喜欢有第二个功能性的选择。 - Terus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接