重新运行Windows .bat文件时传递Unicode参数

7

我的 .bat 文件长这样:

@echo off

CD /D "%~dp0"

if [%2]==[] (  
    set user=%USERNAME%
) else (
    set user=%2%
)

:getFile
if [%1]==[] (
    set /p file=Enter file name : 
) else (
    set file=%~f1
    echo File name: %~f1
)

:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a

if not exist "%file%" (
    echo Error: Could not find file: %file%
    echo.
)

:: Check for admin permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

if '%errorlevel%' == '0' (
    goto gotAdmin
)

:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" ""%file%"" ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B

:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"

echo.

:eof
pause
exit /B

我有这两个测试文件:

  1. C:\Test\Folder\ファイル.txt
  2. C:\Test\フォルダ\File.txt

当我运行上述批处理文件并将1拖到cmd窗口中时,我得到:

enter image description here

这非常好。

当我对2执行相同操作时,我得到:

enter image description here

当我调用UAC.ShellExecute时,%file%没有正确传递。

如何解决这个问题?


批处理代码的第8行中set user=%2%应为set user=%2,无需在末尾添加百分号。 - Mofi
3个回答

4
我首选在以管理员权限启动批处理文件时创建一个快捷方式,然后将该快捷方式标记为需要管理员权限。
首先右键单击foo.bat,然后创建快捷方式。打开该快捷方式的属性,单击“高级...”按钮并启用“以管理员身份运行”。
这有一个缺点:您无法将文件名拖到生成的命令提示符窗口上。但是您可以将文件拖到快捷方式上。
但是,如果我不想或无法使用快捷方式呢?
您可以通过将文件名作为参数传递给脚本来避免写入任意Unicode字符到文件中。即使VBS文件使用ANSI编码,脚本主机始终在内部使用Unicode。
因此,以下是如何编写VBS文件并运行它的方法:
:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" """ + Wscript.Arguments.Item(0) + """ ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs" "%file%"
exit /B

@Scott Griffiths:看起来jpen在这里消失了。你还想在这个答案中看到什么其他的东西吗? - Peter Brittain
@PeterBrittain:我刚刚提醒了jpen,他在查看这个新答案之前会接受它。我认为我们已经有了可行的解决方案,所以赏金可能会给最简单的那个。 - Scott Griffiths

2
尝试在批处理文件开头添加CHCP(改变代码页)命令,使用UTF-8代码页65001,例如:
@echo off

chcp 65001
.
.
.

在这里查看有关代码页标识符的更多信息:https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx

编辑:必须使用支持Unicode的字体,例如Lucida Console来显示命令窗口中的内容。如果没有这个字体,命令处理程序会受到Unicode字符的影响,可能会找不到文件,或者会显示“系统无法将数据写入指定的设备”错误。

单击命令窗口左上角的窗口图标,在菜单上选择“默认值”,然后在“字体”选项卡上选择Lucida Console。

更新-测试批处理文件和输出如下。

这是我用来测试的批处理文件:

@echo off

chcp 65001

CD /D "%~dp0"


:getFile
if [%1]==[] (
    set /p file=Enter file name : 
) else (
    set file=%~f1
    echo File name: %~f1
)

:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a

if not exist "%file%" (
    echo Error: Could not find file: %file%
    echo.
) else (
    echo Found file "%file%"
)

这是我的测试输出,当我首先将 "C:\temp\test\ファイル.txt" 拖到窗口中,然后第二次拖入 "C:\temp\test\フォルダ\file2.txt"。
我的系统是 Win 7 Pro x64 SP1,并且使用英国英语设置。 示例输出

@beercohol-我已经尝试过这个方法,但不幸的是它并没有解决问题。输出信息变成了"错误:找不到文件:C:\Test\フォルダ\File.txt"。 - jpen
请查看我的更新答案 - 我最初关于字体是可选的是错误的 - 您必须使用Unicode字体才能使其正常工作!我已经测试了一部分您的批处理文件,并创建了一个具有相同名称的测试文件和文件夹,当字体设置为Lucida Console时,脚本运行得非常好。 - beercohol
@beercohol-嗯,奇怪...我一直在使用Lucida Console,但问题仍然存在。 - jpen
这很奇怪。我已经进一步更新了我的答案,添加了我的测试批处理文件和输出结果。也许你可以检查一下从中得到的结果。 - beercohol

1
你的问题在于创建临时VBS文件的方式使其不是有效的Unicode文件,因此Windows不知道如何解释你传递的Unicode名称。按照beercohol的建议使用65001代码页后,我仍然发现我无法访问Unicode目录中的文件。但是,如果我尝试使用Unicode编辑器手动创建文件(例如使用记事本并保存为Unicode编码),并调用手动脚本而不是自动生成的VBS文件,则一切都可以正常工作。我已重新设计了你的脚本,使用iconv创建一个UTF-16文件。请注意,必须使用65001代码页运行此脚本才能正常工作。
@echo off

CD /D "%~dp0"

if [%2]==[] (  
    set user=%USERNAME%
) else (
    set user=%2
)

:getFile
if [%1]==[] (
    set /p file=Enter file name : 
) else (
    set file=%~f1
    echo File name: %~f1
)

:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a

if not exist "%file%" (
    echo Error: Could not find file: %file%
    echo.
)

:: Check for admin permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

if '%errorlevel%' == '0' (
    goto gotAdmin
)

:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" ""%file%"" ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
iconv.exe -f utf-8 -t utf-16le "%temp%\getadmin.vbs" > "%temp%\getadmin2.vbs"
"%temp%\getadmin2.vbs"
exit /B

:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
if exist "%temp%\getadmin2.vbs" ( del "%temp%\getadmin2.vbs" )
pushd "%CD%"
CD /D "%~dp0"

echo.

:eof
pause
exit /B

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