在 Windows Subsystem for Linux (WSL) 上运行和调试跨平台 .NET (.NET Core, .NET5 和 .NET6) GUI 和控制台应用程序





5.00/5 (22投票s)
本文介绍如何使用 WSL 测试和调试 .NET/Avalonia Linux 应用程序。
请求投票和评论
朋友们,我注意到很多人在阅读这篇文章,有些告诉我或以某种方式表明他们喜欢它,但很少有人投票。请投票并写下评论,告诉我您对这篇文章的喜好和不喜欢之处,以便我改进文章写作技巧。谢谢!
本文内容概要
.NET Standard, CORE .NET5 和 .NET6 使 .NET 实现了跨平台(GUI 程序除外)。Avalonia 填补了这一空白,使得也可以在 .NET 中开发跨平台 GUI 程序。
WSL2 - Windows Subsystem for Linux 的最新版本,允许直接在 Windows 上测试 Linux 程序(包括用 .NET 和 Avalonia 开发的程序)(无需将其移动到 Linux 计算机或虚拟机)。
最后,Visual Studio 2022 可以在 Windows 上调试用 .NET 和 Avalonia 开发的 Linux 程序,无需将其移动到任何地方。
本文详细介绍了如何正确安装和使用 Microsoft 包和 Avalonia 的这一强大组合,以便在 Visual Studio 2022 中开发 Linux .NET Core 应用程序时进行调试。
本文使用的操作系统和软件包
Windows 最新版本(10 和 11)允许在 Windows 平台上运行 Linux 系统。这非常方便,尤其是在使用 Visual Studio 在 Windows 上构建跨平台或 Linux 特定的程序进行测试和调试时。
我特别对使用新的开源 .NET 版本(.NET STANDARD、.NET CORE、.NET5 和 .NET6)构建的跨平台控制台和 GUI 应用程序感兴趣。
上面列出的所有 .NET 版本除了用于构建桌面 UI 应用程序的库(WPF 和 WinForms)之外,都是跨平台的。这就是用于构建跨平台 GUI 应用程序的开源软件包 - Avalonia 发挥作用的地方。它提供了缺失的环节,使 .NET UI 功能也实现了跨平台。
Avalonia 是 WPF 的精神继承者,但比 WPF 更强大,可用于
- 可在Windows、Mac和Linux上运行的桌面解决方案
- 在浏览器中运行的Web应用程序(通过WebAssembly)
- 适用于Android、iOS和Tizen的移动应用程序。
我称 Avalonia 为 Multiplatform WPF++。
我过去写了很多关于 Avalonia 的文章,特别是,我在 《使用 AvaloniaUI 进行跨平台 UI 编码的简单示例》 中解释了为什么 Avalonia 在创建跨平台 UI 应用程序方面远优于 Xamarin、MAUI、Node.js 或 UNO Platform。
当您创建一个需要在 Linux 上运行的应用程序时,它也必须在 Linux 上进行测试,有时甚至需要调试,因为在应该在多个平台上运行的代码中可能存在特定于 Linux 的代码,甚至特定于 Linux 的 bug。
对于 Windows 开发人员(以及大多数使用 .NET 开发的开发人员 - 在 Windows 上开发),Windows Subsystem for Linux (WSL) 非常方便,它允许在开发代码的同一台 Windows 计算机上运行 Linux .NET 应用程序,甚至可以使用 Visual Studio 2022 进行调试。
本文介绍如何使用 Visual Studio 2022 在 Windows 10 上运行和调试 Linux .NET 代码应用程序。
Windows 和 Visual Studio 版本
在我的测试中,我使用了 Windows 11 和 Visual Studio 2022。
我不确定 Visual Studio 的前一个版本(VS2019)是否也允许调试 .NET Linux 应用程序,但即使允许,可能也需要克服更多难题,所以我建议使用 VS2022。我在此过程中的体验几乎没有遇到任何麻烦。
在 Windows 10 和 11 上安装 WSL2
我不会列出在 Windows 10 和 11 操作系统上安装 WSL2(WSL 的高级版本)所需的所有步骤。有很多网站对此进行了详细介绍,例如 《如何在 Windows 10 上安装 WSL 2》 和 《如何在 Windows 10 和 Windows 11 上安装 Linux WSL2》。
我了解到在 Windows 11 上安装 WSL2 比在 Windows 10 上安装要容易得多。
安装用于 WSL 调试的 Visual Studio 2022 组件
有一个 Visual Studio 组件需要安装(或验证已安装)。
在 Visual Studio 中,打开 **工具** 菜单,然后选择 **获取工具和功能...** 菜单项。
在打开的组件安装窗口中,选择 **Individual Components**(单独组件)选项卡,然后在搜索框中输入 **WSL**。
应该会显示 **.NET Debugging with WSL**(使用 WSL 进行 .NET 调试)组件。安装该组件(如果尚未安装)。
运行 WSL Linux Shell(在 Visual Studio 之外)
要从 Windows 命令提示符启动 Linux shell,请使用以下命令:
wsl --install -d Ubuntu
如果您是第一次执行此操作,系统可能会要求您设置用户名和密码;然后 Linux shell 将打开。
在 Linux shell 中,您可以尝试您喜欢的 UNIX 命令,例如 `ls`、`cat` 或 `grep`。
您可以通过在 Windows 命令提示符或 Explorer 中转到“\\wsl$\Ubuntu\home\<linux-acct-name>”来访问您的 Linux 主目录。这可能需要,例如,在您的 Windows OS 和 Linux 之间复制某些文件或文件夹。
您可以像在真正的 Linux 机器上一样安装您喜欢的 Linux 程序,例如,通过输入
sudo apt install emacs
在 Linux shell 中。
从 Linux Shell 运行 UI 程序
在这里,我将演示如何从 WSL Linux shell 运行任何 Linux UI 程序(不一定是 .NET 程序)。
在 Windows 10 或 11 上,您需要从 sourceforge.net/projects/vcxsrv/ 下载、安装并运行 VcXsvr 应用程序。
安装后,您的桌面上会出现 XLaunch 图标。
为了运行 VcXsrv,您必须单击此图标,然后按照以下步骤操作:
- 在第一个屏幕上选择 **Multiple Windows**(多个窗口)选项(默认),然后按 **Next**(下一步)按钮。
- 在第二个屏幕上选择 **Start no client**(不启动客户端)选项(默认),然后按 **Next**(下一步)按钮。
- 在第三个屏幕上,将 **Disable access control**(禁用访问控制)选项添加到默认选项中,然后按 **Next**(下一步)。
- 在第四个屏幕上按 **Finish**(完成)按钮。
现在,尝试在 Linux shell 中运行一个启动 Linux UI 应用程序的命令,例如:
xterm
这将导致以下错误:
xterm: Xt error: Can't open display:
xterm: DISPLAY is not set
我们需要将您的 Linux 系统上的 `DISPLAY` 变量设置为包含 `<your-windows-ip-address>:0.0`。在 WSL Linux shell 中(至少对于 Ubuntu 20.04)为您执行此操作的魔法行是:
export DISPLAY=$(route.exe print | grep 0.0.0.0 | head -1 | awk '{print $4}'):0.0
运行此行后,尝试
echo $DISPLAY
查看您的 `DISPLAY` 变量被设置为多少。在我的情况下,它是:
10.0.0.7:0.0
还建议您运行
export LIBGL_ALWAYS_INDIRECT=1
以避免出现一些错误消息。
现在再次运行 `xterm` 命令,瞧,您的功能齐全的 `xterm` 将作为窗口之一从 Linux shell 中弹出。
作为 xterm 的替代品,您也可以尝试 xclock - Linux 时钟窗口应该会弹出。
使用 Visual Studio 2022 调试 WSL 上的 .NET 项目
代码位置
视觉和非视觉项目都属于 NP.Ava.Demos 仓库。您可以使用 Github 的“下载为 zip”选项下载整个仓库,或者使用 git 的 `clone` 命令克隆仓库。
git clone https://github.com/npolyak/NP.Ava.Demos.git
本文的两个项目是:
- `ConsoleAppForLinuxSubsystemDebuggingDemo` - 一个简单的非视觉 Linux 应用程序示例。
- `AvaloniaAppForLinuxSubsystemDebuggingDemo` - 一个简单的 Linux 可视应用程序示例。
调试控制台(非视觉)Linux 应用程序
打开仓库中 `ConsoleAppForLinuxSubsystemDebuggingDemo` 文件夹下的 `ConsoleAppForLinuxSubsystemDebuggingDemo.sln` 解决方案。
Program.cs 文件中的代码目的是打印有关运行程序的操作系统的一些信息。
bool isLinux = OperatingSystem.IsLinux();
if (isLinux)
{
Console.WriteLine("Yes, it is Linux!!!");
}
else
{
Console.WriteLine("No, it is not Linux");
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Yes, indeed Linux!!!");
}
Console.WriteLine($"RuntimeInformation.OSDescription =
'{RuntimeInformation.OSDescription}'");
// gives Linux type, version number and architecture:
Console.WriteLine($"RuntimeInformation.RuntimeIdentifier =
'{RuntimeInformation.RuntimeIdentifier}'");
Console.WriteLine($"Environment.OSVersion = '{Environment.OSVersion}'");
您可以通过在代码中设置断点后,按 **Debug**(调试)按钮在 Windows 上进行调试。
在 Windows 10 上运行程序,程序将产生以下输出:
No, it is not Linux
RuntimeInformation.OSDescription = 'Microsoft Windows 10.0.19044'
RuntimeInformation.RuntimeIdentifier = 'win10-x64'
Environment.OSVersion = 'Microsoft Windows NT 10.0.19044.0'
注意,**Debug** 按钮(上图中红色椭圆形内的按钮)右侧有一个向下的箭头。如果您按下该箭头,您将看到一个菜单弹出,其中包含 WSL 选项。
单击 **WSL** 选项,然后再次按 **Debug**(调试)按钮。
它将在相同的断点处停止,但现在,应用程序将作为 Linux 程序在 WSL 上运行。此程序的输出将是:
Yes, it is Linux!!!
Yes, indeed Linux!!!
RuntimeInformation.OSDescription =
'Linux 5.10.60.1-microsoft-standard-WSL2 #1 SMP Wed Aug 25 23:20:18 UTC 2021'
RuntimeInformation.RuntimeIdentifier = 'ubuntu.20.04-x64'
Environment.OSVersion = 'Unix 5.10.60.1'
重要提示:在 WSL 上运行的 Linux 程序的输出将写入 **Visual Studio 输出窗口**,而不是像 Windows 程序那样写入打开的控制台窗口。
调试 Avalonia GUI .NET Linux 应用程序
现在打开位于 NP.Avalonia.Demos 仓库的同名文件夹下的 `AvaloniaAppForLinuxSubsystemDebuggingDemo.sln` 解决方案。
由于我们现在要调试一个 UI 应用程序,请不要忘记按照上述方法(除非已启动)在 Windows 10 上启动您的 **VcXsrv**。
这个非常简单的 UI 应用程序的非标准代码位于 `MainWindow.axaml` 和 `MainWindow.axaml.cs` 文件中。
这是 MainWindow.axaml 文件的内容
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaAppForLinuxSubsystemDebuggingDemo.MainWindow"
Title="AvaloniaAppForLinuxSubsystemDebuggingDemo"
Width="500"
Height="300">
<Button x:Name="TestDebuggingButton"
Content="Test Debugging"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Window>
它在窗口中央定义了一个名为“TestDebuggingButton
”的单按钮。
MainWindow.axaml.cs 文件内容同样简单。它定义并为按钮的 `Click` 事件添加了一个处理程序:
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace AvaloniaAppForLinuxSubsystemDebuggingDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TestDebuggingButton.Click += TestDebuggingButton_Click;
}
private void TestDebuggingButton_Click(object? sender, RoutedEventArgs e)
{
}
}
}
在 `TextDebugginButton_Click(...)` 处理程序方法中设置一个断点。
现在将 **Debug**(调试)按钮切换到 WSL(方式与上一小节相同)。请注意,该项目现在有一个包含 `launchSettings.json` 文件的 *Properties* 子文件夹。
在这种情况下 - 此文件已提交到 git 仓库,但当您创建新项目时,当您将 **Debug**(调试)按钮切换到 **WSL** 时,将创建并添加到项目中的此文件。
单击 `launchSettings.json` 文件将其打开。这是其内容:
{
"profiles": {
"AvaloniaAppForLinuxSubsystemDebuggingDemo": {
"commandName": "Project"
},
"WSL": {
"commandName": "WSL2",
"environmentVariables": {
"DISPLAY": "10.0.0.7:0.0",
"LIBGL_ALWAYS_INDIRECT": "1"
},
"distributionName": ""
}
}
}
您需要将 **DISPLAY** 设置更改为您拥有的任何值。为了确定 `DISPLAY` 变量需要设置为多少,您可以使用上面“从 Linux Shell 运行 UI 程序”部分中描述的相同方法,即:
- 通过运行以下命令打开 Linux shell:
wsl --install -d Ubuntu
在 Windows 命令提示符中。 -
在 Linux shell 中,运行以下命令:
echo $(route.exe print | grep 0.0.0.0 | head -1 | awk '{print $4}'):0.0
此命令的输出将产生您需要在 `launchSettings.json` 文件中为 `DISPLAY` 变量分配的值(在我的情况下是“10.0.0.7:0.0”)。
现在您已准备好调试程序。
按 **Debug**(调试)按钮启动程序。
一个窗口弹出,在其左上角显示 **X** term 图标。
这就是我们的 Avalonia 应用程序在 WSL 上运行。
按下窗口中央的按钮,您将在 `TestDebuggingButton_Click(...)` 方法体内的断点处停止。
结论
本文详细介绍了如何使用 WSL 和 Visual Studio 2022 测试和调试 .NET/Avalonia Linux 应用程序。
历史
- 2022 年 4 月 24 日:初始版本。
- 2023 年 12 月 26 日 - 升级到 Avalonia 11。