解决方案是在Window注册表文件中使用:
@="cmd.exe /V:ON /C cd /D \"C:\\Program Files (x86)\\Google\\Chrome\\Application\\\" & set \"url=%1\" & set \"url=!url:cnx://%%20=!\" & set \"url=!url:cnx://=!\" & for /F \"tokens=1-3 delims=?#\" %%a in (\"!url!\") do if \"%%a#%%b%%c\"==\"!url!\" (chrome.exe \"!url!\") else (chrome.exe \"%%a#%%c%%b\")"
这会在 Windows 注册表中生成以下命令行:
cmd.exe /V:ON /C cd /D "C:\Program Files (x86)\Google\Chrome\Application\" & set "url=%1" & set "url=!url:cnx://%%20=!" & set "url=!url:cnx://=!" & for /F "tokens=1-3 delims=?#" %%a in ("!url!") do if "%%a#%%b%%c"=="!url!" (chrome.exe "!url!") else (chrome.exe "%%a#%%c%%b")
重要的是 Windows 命令处理器选项 /V:ON,它为环境变量启用 delayed expansion,如在命令提示符窗口中运行时的帮助输出 cmd /? 中所述。选项/V:ON 必须分别指定给选项/C(在执行命令行后关闭)/K(在执行命令行后保持命令进程运行),因为/C 或/K 之后的所有内容都被解释为部分要执行的命令行。
使用/K 代替/C 可以查看执行此命令行时发生的情况,用户可以在命令行执行完成后执行set url 以查看最终值是多少环境变量url.
在 cmd 窗口中运行的帮助输出 set /? 解释了何时以及如何使用延迟的环境变量扩展。如果在命令行上定义或修改环境变量并在同一命令行上引用它,则必须使用它,就像single line with multiple commands 的情况一样。如果在以( 开头并以匹配) 结尾的命令块中定义或修改了环境变量,因为cmd.exe 会解析整个命令块并用当前引用值替换所有%variable% 引用在执行此命令块的任何命令之前或在同一命令行上离开命令块开始之前的环境变量。
另见How does the Windows Command Interpreter (CMD.EXE) parse scripts?
启用延迟扩展后,需要使用!variable! 引用环境变量以延迟扩展此引用。
注意:命令行中的每个感叹号都被解释为延迟扩展环境变量引用的开始/结束,即使在双引号参数字符串中启用。
带有(几乎)相同代码的注释批处理文件将是:
@echo off
rem Explicitly enable command extensions although enabled by default
rem and delayed environment variable expansion disabled by default.
setlocal EnableExtensions EnableDelayedExpansion
rem Change current directory to directory containing Google Chrome browser.
cd /D "%ProgramFiles(x86)%\Google\Chrome\Application\"
rem Define environment variable url with value of first
rem argument with surrounding double quotes removed.
set "url=%~1"
rem Exit batch file if called without any argument or with just "".
if not defined url goto EndBatch
rem Remove case-insensitive all occurrences of string "cnx://"
rem with an additional percent encoded space from the url argument.
set "url=!url:cnx://%%20=!"
rem Remove case-insensitive all occurrences of string "cnx://".
set "url=!url:cnx://=!"
rem Split up the url strings on question mark and hash and assign just
rem first three ?# delimited substrings to loop variables a, b and c.
rem FOR would not run any command in command block on url starting with
rem a semicolon. Run Google Chrome with the url if first substring with #
rem and the two other substrings appended is case-sensitive equal the url.
rem Otherwise run Google Chrome with redefined url with second and third
rem substring exchanged after first substring and hash character.
for /F "tokens=1-3 delims=?#" %%a in ("!url!") do (
if "%%a#%%b%%c" == "!url!" (
start "" chrome.exe "!url!"
) else (
start "" chrome.exe "%%a#%%c%%b"
)
)
rem Restore initial environment on calling the batch file which means
rem discarding all environment variables defined or modified in block
rem above like environment variable url, restore initial current directory
rem as it was before using command CD and restore also initial states of
rem command extensions (most likely enabled) and delayed expansion (most
rem likely disabled).
:EndBatch
endlocal