Home > Mobile >  Why is the wsl command not found by CMD on starting a batch file with a double click in FreeCommande
Why is the wsl command not found by CMD on starting a batch file with a double click in FreeCommande

Time:11-29

I want to use a batch script to start Docker in Windows Subsystem for Linux at login. It works when I run the batch file as administrator. So I followed this guide: Always Run Batch file as Administrator in Windows 10

Then I placed the shortcut into the Startup folder. The script is started, but it exits always at the first line.

Then I tried to run manually the batch file in FreeCommander. The batch script works when I run the script as administrator via right click context menu item. But there is output an error message when I run the batch script with a double click. The output error message is:

The command "wsl" is either misspelled or could not be found.

This is the batch script:

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%"

I removed also once Windows Subsystem for Linux completely and reinstalled it, but the problem persists.

CodePudding user response:

There should be read first the following Microsoft documentation pages:

There are two system directories on 64-bit Windows with a processor with AMD64 architecture:

  1. %SystemRoot%\System32 with 64-bit applications used by 64-bit applications by default.
  2. %SystemRoot%\SysWOW64 with 32-bit applications used by 32-bit applications by default.

The system environment variable PATH contains by Windows default %SystemRoot%\System32 as first folder path. If a 32-bit application starts cmd.exe to process a batch file, there is started 32-bit %SystemRoot%\SysWOW64\cmd.exe because of the file system redirector.

cmd.exe is searching for files specified in a batch file just with file name without or with file extension and without path by using the local environment variables PATHEXT and PATH as explained in full details by What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?

wsl.exe belongs to the set of executables which on AMD64 Windows exists only as 64-bit version in %SystemRoot%\System32. There is no 32-bit version in %SystemRoot%\SysWOW64 searched by 32-bit cmd.exe on using %SystemRoot%\System32 in expanded form in local PATH because of file system redirector. For that reason the batch file as posted in the question does not work on being processed by 32-bit cmd.exe on Windows x64.

The solution is taking WOW64 into account with additional code in the batch file:

@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

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • exit /?
  • for /?
  • goto /?
  • if /?
  • netsh /?
  • netsh interface /?
  • netsh interface portproxy /?
  • netsh interface portproxy add /?
  • netsh interface portproxy add v4tov4 /?
  • pause /?
  • set /?
  • setlocal /?
  • Related