之前写了一个迷你系列,来分析 LSP 的 AppId_Catalog 是如何计算的, 但是却忘了提 docker 和 uu 的冲突是如何解决的了,这次我们把这个问题修掉。
我想看过上个系列 的朋友们应该知道了问题的原因,不过我觉得这里再放一个懒人包罗列一下要点也未尝不可:
因此,在安装了 uu 的机器上,你会发现,与 wsl 有关的应用,比如我们这次的 docker, 都会无法启动。
解决这个问题,我们需要让 LSP 放行 wsl,确保 docker 可以正常开启 linux 虚拟机, 然后还要让 LSP 放行 docker 服务, 因为 docker 容器和外部环境的联通是由 docker 控制的,这个默认也会被 uu 接管。
放行 wsl,推荐的做法还是使用 github @mariotaku 的脚本:
#Requires -RunAsAdministrator
# Fix for https://github.com/microsoft/WSL/issues/4177
$MethodDefinition = @'
[DllImport("ws2_32.dll", CharSet = CharSet.Unicode)]
public static extern int WSCSetApplicationCategory([MarshalAs(UnmanagedType.LPWStr)] string Path, uint PathLength, [MarshalAs(UnmanagedType.LPWStr)] string Extra, uint ExtraLength, uint PermittedLspCategories, out uint pPrevPermLspCat, out int lpErrno);
'@
$Ws2Spi = Add-Type -MemberDefinition $MethodDefinition -Name 'Ws2Spi' -PassThru
$WslLocation = Get-AppxPackage MicrosoftCorporationII.WindowsSubsystemForLinux | Select-Object -expand InstallLocation
$Executables = ("wsl.exe", "wslservice.exe");
foreach ($Exe in $Executables) {
$ExePath = "${WslLocation}\${Exe}";
$ExePathLength = $ExePath.Length;
$PrevCat = $null;
$ErrNo = $null;
if ($Ws2Spi::WSCSetApplicationCategory($ExePath, $ExePathLength, $null, 0, [uint32]"0x80000000", [ref] $PrevCat, [ref] $ErrNo) -eq 0) {
Write-Output "Added $ExePath!";
}
}
这个脚本会找到商店安装的 wsl,然后调用 WinSock 的 WSCSetApplicationCategory
接口来对程序进行配置。之前我们说过,商店安装的 wsl 每次更新后路径会变,
所以每次更新都要执行一下这个脚本。简单一点的话,执行后重启即可。
我们根据这个脚本依样画葫芦,就可以给 docker 放行, 由于 docker 的安装位置是固定的,所以还更简单一点:
$DockerLocation = "C:\Program Files\Docker\Docker"
$DockerExes = ("Docker Desktop.exe", "DockerCli.exe", "courgette64.exe", "com.docker.service");
foreach ($Exe in $DockerExes) {
$ExePath = "${DockerLocation}\${Exe}";
$ExePathLength = $ExePath.Length;
$PrevCat = $null;
$ErrNo = $null;
if ($Ws2Spi::WSCSetApplicationCategory($ExePath, $ExePathLength, $null, 0, [uint32]"0x80000000", [ref] $PrevCat, [ref] $ErrNo) -eq 0) {
Write-Output "Added $ExePath!";
}
}
docker 目录下有三个 exe,我全放进去了,还是不成功,后来发现, docker 的后台服务并不是个 exe:
我的理解看来已经过时了,所以 $DockerExes
才有了最后一个 service,再重启。搞定!
解决 docker 与 uu 的冲突,需要同时放行 wsl 和 docker,
方法都是调用 WinSock 的 WSCSetApplicationCategory
。由于 Category 这个 id
是只与程序路径有关,所以对于 docker 来说,设定一次就好,
不过由于 docker 在 windows 上使用的还是 wsl,所以首先要解决 wsl 的问题。