为什么在 FreeCommander 中双击启动批处理文件时 CMD 找不到 wsl 命令?
Why is the wsl command not found by CMD on starting a batch file with a double click in FreeCommander?
我想使用批处理脚本在 Windows 子系统中为 Linux 在登录时启动 Docker。当我以管理员身份 运行 批处理文件时,它起作用了。所以我遵循了这个指南:Always Run Batch file as Administrator in Windows 10
然后我将快捷方式放入Startup
文件夹中。脚本已启动,但总是在第一行退出。
然后我尝试在 FreeCommander 中手动 运行 批处理文件。当我通过右键单击上下文菜单项以管理员身份 运行 脚本时,批处理脚本有效。但是当我 运行 双击批处理脚本时会输出一条错误消息。输出错误信息为:
The command "wsl" is either misspelled or could not be found.
这是批处理脚本:
FOR /F "tokens=* USEBACKQ" %%g IN (`wsl.exe sh -c "hostname -I"`) do (SET "ip=%%g")
netsh interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%ip%
wsl sh -c "sudo dockerd -H tcp://%ip%"
我还完全删除了 Windows Linux 的子系统并重新安装,但问题仍然存在。
首先应阅读以下 Microsoft 文档页面:
在 64 位 Windows 上有 两个 个系统目录,处理器采用 AMD64 架构:
%SystemRoot%\System32
默认情况下,64 位应用程序使用 64 位应用程序。
%SystemRoot%\SysWOW64
默认情况下,32 位应用程序使用 32 位应用程序。
系统 环境变量 PATH
默认包含 Windows %SystemRoot%\System32
作为第一个文件夹路径。如果 32 位应用程序启动 cmd.exe
来处理批处理文件,则由于文件系统重定向器,启动了 32 位应用程序 %SystemRoot%\SysWOW64\cmd.exe
。
cmd.exe
正在使用 local 环境变量 [=18] 搜索批处理文件中指定的文件,文件名不带或带文件扩展名,不带路径=] 和 PATH
详见
wsl.exe
属于在 AMD64 Windows 上仅作为 64 位版本存在于 %SystemRoot%\System32
上的可执行文件集。 %SystemRoot%\SysWOW64
中没有 32 位版本 cmd.exe
在 local PATH
中使用扩展形式的 %SystemRoot%\System32
搜索 %SystemRoot%\SysWOW64
因为文件系统重定向器。因此,问题中发布的批处理文件无法在 Windows x64.
上由 32 位 cmd.exe
处理
解决方案是将 WOW64 考虑在内,并在批处理文件中添加额外的代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist %SystemRoot%\System32\wsl.exe set "FileNameWSL=%SystemRoot%\System32\wsl.exe" & goto RunWSLCommands
if exist %SystemRoot%\Sysnative\wsl.exe set "FileNameWSL=%SystemRoot%\Sysnative\wsl.exe" & goto RunWSLCommands
echo ERROR: Could not find wsl.exe. Script execution aborted.
setlocal EnableDelayedExpansion & for /F "tokens=1,2" %%G in ("!CMDCMDLINE!") do endlocal & if /I "%%~nG" == "cmd" if /I "%%~H" == "/c" pause
exit /B
:RunWSLCommands
for /F "tokens=*" %%g in ('%FileNameWSL% sh -c "hostname -I"') do set "ip=%%g"
%SystemRoot%\System32\netsh.exe interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%ip%
%FileNameWSL% sh -c "sudo dockerd -H tcp://%ip%"
endlocal
要了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
exit /?
for /?
goto /?
if /?
netsh /?
netsh interface /?
netsh interface portproxy /?
netsh interface portproxy add /?
netsh interface portproxy add v4tov4 /?
pause /?
set /?
setlocal /?
我想使用批处理脚本在 Windows 子系统中为 Linux 在登录时启动 Docker。当我以管理员身份 运行 批处理文件时,它起作用了。所以我遵循了这个指南:Always Run Batch file as Administrator in Windows 10
然后我将快捷方式放入Startup
文件夹中。脚本已启动,但总是在第一行退出。
然后我尝试在 FreeCommander 中手动 运行 批处理文件。当我通过右键单击上下文菜单项以管理员身份 运行 脚本时,批处理脚本有效。但是当我 运行 双击批处理脚本时会输出一条错误消息。输出错误信息为:
The command "wsl" is either misspelled or could not be found.
这是批处理脚本:
FOR /F "tokens=* USEBACKQ" %%g IN (`wsl.exe sh -c "hostname -I"`) do (SET "ip=%%g")
netsh interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%ip%
wsl sh -c "sudo dockerd -H tcp://%ip%"
我还完全删除了 Windows Linux 的子系统并重新安装,但问题仍然存在。
首先应阅读以下 Microsoft 文档页面:
在 64 位 Windows 上有 两个 个系统目录,处理器采用 AMD64 架构:
%SystemRoot%\System32
默认情况下,64 位应用程序使用 64 位应用程序。%SystemRoot%\SysWOW64
默认情况下,32 位应用程序使用 32 位应用程序。
系统 环境变量 PATH
默认包含 Windows %SystemRoot%\System32
作为第一个文件夹路径。如果 32 位应用程序启动 cmd.exe
来处理批处理文件,则由于文件系统重定向器,启动了 32 位应用程序 %SystemRoot%\SysWOW64\cmd.exe
。
cmd.exe
正在使用 local 环境变量 [=18] 搜索批处理文件中指定的文件,文件名不带或带文件扩展名,不带路径=] 和 PATH
详见
wsl.exe
属于在 AMD64 Windows 上仅作为 64 位版本存在于 %SystemRoot%\System32
上的可执行文件集。 %SystemRoot%\SysWOW64
中没有 32 位版本 cmd.exe
在 local PATH
中使用扩展形式的 %SystemRoot%\System32
搜索 %SystemRoot%\SysWOW64
因为文件系统重定向器。因此,问题中发布的批处理文件无法在 Windows x64.
cmd.exe
处理
解决方案是将 WOW64 考虑在内,并在批处理文件中添加额外的代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist %SystemRoot%\System32\wsl.exe set "FileNameWSL=%SystemRoot%\System32\wsl.exe" & goto RunWSLCommands
if exist %SystemRoot%\Sysnative\wsl.exe set "FileNameWSL=%SystemRoot%\Sysnative\wsl.exe" & goto RunWSLCommands
echo ERROR: Could not find wsl.exe. Script execution aborted.
setlocal EnableDelayedExpansion & for /F "tokens=1,2" %%G in ("!CMDCMDLINE!") do endlocal & if /I "%%~nG" == "cmd" if /I "%%~H" == "/c" pause
exit /B
:RunWSLCommands
for /F "tokens=*" %%g in ('%FileNameWSL% sh -c "hostname -I"') do set "ip=%%g"
%SystemRoot%\System32\netsh.exe interface portproxy add v4tov4 listenport=2375 connectport=2375 connectaddress=%ip%
%FileNameWSL% sh -c "sudo dockerd -H tcp://%ip%"
endlocal
要了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
exit /?
for /?
goto /?
if /?
netsh /?
netsh interface /?
netsh interface portproxy /?
netsh interface portproxy add /?
netsh interface portproxy add v4tov4 /?
pause /?
set /?
setlocal /?