File: Utils\EnvironmentChecker\WslEnvironmentCheck.cs
Web Access
Project: src\src\Aspire.Cli\Aspire.Cli.Tool.csproj (aspire)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
 
namespace Aspire.Cli.Utils.EnvironmentChecker;
 
/// <summary>
/// Checks if running in WSL environment and detects potential issues.
/// </summary>
internal sealed class WslEnvironmentCheck : IEnvironmentCheck
{
    public int Order => 20; // Fast check - file system reads
 
    public Task<IReadOnlyList<EnvironmentCheckResult>> CheckAsync(CancellationToken cancellationToken = default)
    {
        // WSL detection only relevant on Linux
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            // Not running on Linux, nothing to check
            return Task.FromResult<IReadOnlyList<EnvironmentCheckResult>>([]);
        }
 
        // Check for WSL-specific environment indicators
        var isWsl = IsRunningInWsl();
 
        if (!isWsl)
        {
            // Running on native Linux, nothing to check
            return Task.FromResult<IReadOnlyList<EnvironmentCheckResult>>([]);
        }
 
        // Detect WSL version
        var wslVersion = GetWslVersion();
 
        if (wslVersion == 1)
        {
            return Task.FromResult<IReadOnlyList<EnvironmentCheckResult>>([new EnvironmentCheckResult
            {
                Category = "environment",
                Name = "wsl",
                Status = EnvironmentCheckStatus.Warning,
                Message = "WSL1 detected - limited container support",
                Fix = "Upgrade to WSL2 for best experience: wsl --set-version <distro> 2",
                Link = "https://aka.ms/aspire-prerequisites#wsl-setup"
            }]);
        }
 
        // WSL2 detected - just informational, not a warning unless there are known issues
        return Task.FromResult<IReadOnlyList<EnvironmentCheckResult>>([new EnvironmentCheckResult
        {
            Category = "environment",
            Name = "wsl",
            Status = EnvironmentCheckStatus.Pass,
            Message = "WSL2 environment detected",
            Details = "If you experience container connectivity issues, ensure Docker Desktop WSL integration is enabled."
        }]);
    }
 
    private static bool IsRunningInWsl()
    {
        try
        {
            // Check for WSL-specific indicators
            if (File.Exists("/proc/version"))
            {
                var version = File.ReadAllText("/proc/version");
                return version.Contains("microsoft", StringComparison.OrdinalIgnoreCase) ||
                       version.Contains("WSL", StringComparison.OrdinalIgnoreCase);
            }
 
            // Alternative: check for WSL environment variable
            return Environment.GetEnvironmentVariable("WSL_DISTRO_NAME") != null;
        }
        catch
        {
            return false;
        }
    }
 
    private static int GetWslVersion()
    {
        try
        {
            // WSL2 uses a real Linux kernel, WSL1 doesn't
            // Check /proc/version for indicators
            if (File.Exists("/proc/version"))
            {
                var version = File.ReadAllText("/proc/version");
                // WSL2 typically includes "microsoft" and version 4.x or 5.x
                if (version.Contains("microsoft", StringComparison.OrdinalIgnoreCase))
                {
                    // Try to determine version based on kernel version
                    // WSL2 uses kernel 4.x or higher, WSL1 uses much older version strings
                    // Use regex to match actual kernel version numbers (e.g., "Linux version 4.19" or "Linux version 5.10")
                    var kernelVersionMatch = Regex.Match(version, @"Linux\s+version\s+(\d+)\.", RegexOptions.IgnoreCase);
                    if (kernelVersionMatch.Success && int.TryParse(kernelVersionMatch.Groups[1].Value, out int majorVersion))
                    {
                        // WSL2 uses kernel 4.x or higher
                        if (majorVersion >= 4)
                        {
                            return 2;
                        }
                    }
                    return 1;
                }
            }
        }
        catch
        {
            // If we can't determine, assume WSL2 (more common now)
        }
 
        return 2;
    }
}