Passing Unicode parameters to Windows .bat file when rerunning it

时间:2015-06-26 09:42:26

标签: windows batch-file unicode dos

My .bat file looks like this:

@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

I have these two test files:

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

When I run the batch file above and drag 1 onto the cmd window I get:

enter image description here

, which is good.

When I do the same for 2, I get:

enter image description here

When I call UAC.ShellExecute, %file% isn't passed correctly.

How can I get around this problem?

3 个答案:

答案 0 :(得分:2)

启动具有管理员权限的批处理文件的首选方法是创建快捷方式,然后将该快捷方式标记为需要管理员权限。

首先右键单击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

答案 1 :(得分:1)

尝试使用UTF-8代码页65001添加CHCP(CHange代码页)命令以启动批处理文件,例如:

@echo off

chcp 65001
.
.
.

有关代码页标识符的更多信息,请参阅此处:https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx

编辑必须还可以在命令窗口中使用支持Unicode的字体,例如Lucida Console。如果没有这个,命令处理器会对unicode字符进行扼流,并且无法找到文件,或者可能显示“系统无法写入指定设备”错误。

单击命令窗口左上角的窗口图标,在菜单上选择Defaults,然后在Fonts选项卡上选择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,具有英国英国设置。

Sample output

答案 2 :(得分: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