Scripting with WSL interoperability: Tips & Tricks---
date: May 22, 2020
This is the resource page for things I have talked about or not talked about on the session Scripting with WSL interoperability: Tips & Tricks.
You can get the ppt here: https://cdn.patrickwu.space/wslconf/wslconf-wsl-interop.pptx.
You can find the source code here: https://github.com/patrick330602/wslconf.
|1607||1703||1709||1803, 1809||1903, 1909||2004|
*1: Kept for backward compatibility
*2: feature of the function extended in these builds
grep ^enabled /proc/sys/fs/binfmt_misc/WSLInterop will print
enabled if WSL interoperability is enabled, otherwise it will be a empty output.
Also, you can use the file
/proc/sys/fs/binfmt_misc/WSLInterop to check whether the script/program is running in WSL or Linux.
You can find reference for the
To get the mount location, you can use
root in option in
[automount] section to get the location. By default, it will use
/mnt/, and the logic can be something like this:
If /etc/wsl.conf exists and if root under [automount] is defined
After finding the mount location, you can scan through the already mounted drive to find where the Windows install location is, as %SystemRoot% is sometimes not defined properly.
For already mounted drive in mount location
It is suggested to running them using the full path in case the Windows Path does not append properly on the Windows side.
- straight forward and fast
- Possibly problematic with UNC path(which includes WSL file access, which locates at
\\wsl$\DistroName)but no error will possibly going to be shown.
Commands can be executed using
cmd.exe /C “Command”.
cmd.exescript support (such as
- Run under Windows environment, easier to pass environment variables
UNC path is not supported and an error will be shown as the following one when executing:
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.
To solve this, you can just move to a Windows folder in WSL before executing the command, for example, your C Drive (
- Allows you to execute
powershellcommands and scripts
- Windows PowerShell is suggested not PowerShell Core for Maximum compatibility
Execute commands/scripts using
powershell.exe -NoProfile -NonInteractive -Command "<Command>" for faster speed.
-ExecutionPolicy ByPass if you want to execute the command.
For the raster font problem, you can refer to my article here to fix the problem.
These three options have some speed difference.
Running individual tools directly are usually the fastest; and then the
powershell.exe is slowest. Here is a benchmark video:
This is the legacy of the origin of WSL (Bash on Ubuntu on Windows).
bash.exe will start a bash login shell of your default WSL Linux distribution.
bash.exe uses the Linux bash command-line arguments, and just like linux bash, you need to execute a command like the following:
bash.exe -c "<COMMAND>"
Merged feature from
wsl.exe is the one that allows you to run and manage WSL distros. It also has allows you to run WSL with different distro with different users:
wsl [-d <distro>] [-u <user>] [-e] <Command>:
-e is the interesting part here:
wsl.exeexecutes commands with the default login shell of your WSL distribution.
wsl.exe -eexecutes commands on your WSL distribution without any shell.
<distro>.exe allows you to interact with a specific distro. However, it has some interesting behaviors that you need to pay attention:
<distro>.exewith no arguments launches the user’s default shell in the user’s home directory;
<distro>.exe runlaunches the user’s default shell in the current working directory;
<distro>.exe run [Command]run the provided command line in the current working directory with user’s default shell.
But there are some issues:
- Imported distributions don’t have
.exe can be different from distribution registered name.
I am not able to cover everything in WSLConf, so here are some additional tips and tricks you might be interested in:
I have posted a post about this topic before. You can view it here.
Due to the lack of documentation, some of the information is possibly not complete.
Information of WSL distributions store here:
- Subkeys are the definition of single WSL distributions. They are named using GUID.
DafaultDistribution, RGE_SZ: This defines the default distribution used when using
wsl.exe. The value passed is a GUID. By default, it’s the first distribution installed.
DefaultVersion, REG_DWORD: (WSL2 Only) This defines the default WSL version that would be used for new WSL distributions. Value for WSL1 is 0x1(1); for WSL2, 0x2(2).
Here are the details of the key values:
BasePath, REG_SZ: This defines where the WSL distribution source location is.
DefaultEnvironment, REG_MULTI_SZ: This defines the default environment value that passed to WSL Distribution when opening the WSL distribution.
DefaultUid, REG_DWORD: This defines the default user for the distro. The value uses the
uidin Linux, for example,
DistributionName, REG_SZ: This defines the registered name of the WSL distribution. This will be used in
wsl.exe --listand in
Flags, REG_DWORD: This defines the behavior of a distribution registered with the Windows Subsystem for Linux. The value passed is numeral combination of enumeration
WSL_DISTRIBUTION_FLAGS, which is used by function
wslapi.h. The default value is
WSL_DISTRIBUTION_FLAGS_DEFAULT, which is 0x7(7) in older version and 0xf(15) in newer version. Known available single options are the following:
There is also one unknown undocumented flag with value 0x8(8) in the newer version. Related issue here: https://github.com/microsoft/WSL/issues/4251 (I personally suspect this is related to case-sensitive)
KernelCommandLine, REG_SZ: (2004 Only) This defines the command passed to WSL2 Kernel.
PackageFamilyName, REG_SZ: This defines the WSL distribution’s UWP package Family name.
State, REG_DWORD: This defines the state of WSL distribution. By default, it is in normal state 0x1(1). Here are also some other states:
- Normal: 0x1(1)
- Installing: 0x3(3)
- Uninstalling: 0x4(4)
Version, REG_DWORD: (2004 Only) This defines whether you are using WSL1 or WSL2. Value for WSL1 is 0x1(1); for WSL2, 0x2(2).
As you can see, by default imported distribution do not have
PackageFamilyName. Also by default,
DefaultUid will be
0 which is root.
You can start using the
Start-Process command in powershell, which will become something like the following:
powershell.exe -NonInteractive -NoProfile -Command "Start-Process -FilePath powershell.exe -WorkingDirectory \"$(wslpath -w $(pwd))\" -ArgumentList "-NonInteractive -NoProfile -Command <Command>" -Verb RunAs"
You might also want to tweak the line for your needs.
If you find this is a bit too long or it is a bit complicated, you can use the following script from scoop creator Luke Sampson to do the thing: https://github.com/lukesampson/psutils/blob/master/sudo.ps1. TO use this one,
-ExecutionPolicy ByPass is suggested to use.