refactor: 枚举移入Models目录,命名空间更新为Rainbow.Entity.Models
大石头 authored at 2026-07-02 12:54:58
5.41 KiB
RainbowBridge
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace Rainbow.Services;

/// <summary>Windows 网口管理器。通过 System.Net.NetworkInformation 采集网口信息</summary>
public class WindowsNetworkInterfaceManager : INetworkInterfaceManager
{
    /// <summary>获取所有网口信息</summary>
    public Task<List<NetworkInterfaceInfo>> GetInterfacesAsync()
    {
        var result = new List<NetworkInterfaceInfo>();

        try
        {
            var interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (var ni in interfaces)
            {
                // 跳过回环和隧道接口
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue;

                var props = ni.GetIPProperties();
                if (props == null) continue;

                var info = new NetworkInterfaceInfo
                {
                    Name = ni.Name,
                    Mac = ni.GetPhysicalAddress()?.ToString() ?? "",
                    Status = ni.OperationalStatus switch
                    {
                        OperationalStatus.Up => "Up",
                        OperationalStatus.Down => "Down",
                        _ => "Unknown"
                    },
                    Speed = ni.Speed > 0 ? ni.Speed / 1_000_000 : 0, // bit/s → Mbps
                    IsPhysical = IsPhysicalInterface(ni),
                };

                // IPv4 地址
                foreach (var addr in props.UnicastAddresses)
                {
                    if (addr.Address.AddressFamily == AddressFamily.InterNetwork)
                        info.IPv4Addresses.Add(addr.Address.ToString());
                    else if (addr.Address.AddressFamily == AddressFamily.InterNetworkV6)
                        info.IPv6Addresses.Add(addr.Address.ToString());
                }

                // RX/TX 字节数(仅 Windows 支持 GetIPv4Statistics)
                try
                {
                    var stats = ni.GetIPv4Statistics();
                    info.RxBytes = stats.BytesReceived;
                    info.TxBytes = stats.BytesSent;
                }
                catch
                {
                    // 部分接口不支持统计
                }

                result.Add(info);
            }
        }
        catch
        {
            // 异常时返回空列表
        }

        return Task.FromResult(result);
    }

    /// <summary>获取指定网口信息</summary>
    public async Task<NetworkInterfaceInfo?> GetInterfaceAsync(String name)
    {
        var all = await GetInterfacesAsync();
        return all.FirstOrDefault(i =>
            String.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
    }

    /// <summary>启用网口。通过 PowerShell Enable-NetAdapter</summary>
    public async Task<Boolean> EnableAsync(String name)
    {
        try
        {
            var psi = new System.Diagnostics.ProcessStartInfo("powershell",
                $"-Command \"Enable-NetAdapter -Name '{name}' -Confirm:$false\"")
            {
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            using var proc = System.Diagnostics.Process.Start(psi);
            if (proc == null) return false;
            proc.WaitForExit(10000);
            return proc.ExitCode == 0;
        }
        catch
        {
            return false;
        }
    }

    /// <summary>禁用网口。通过 PowerShell Disable-NetAdapter</summary>
    public async Task<Boolean> DisableAsync(String name)
    {
        try
        {
            var psi = new System.Diagnostics.ProcessStartInfo("powershell",
                $"-Command \"Disable-NetAdapter -Name '{name}' -Confirm:$false\"")
            {
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            using var proc = System.Diagnostics.Process.Start(psi);
            if (proc == null) return false;
            proc.WaitForExit(10000);
            return proc.ExitCode == 0;
        }
        catch
        {
            return false;
        }
    }

    /// <summary>判断是否为物理网口。排除虚拟/隧道/软件接口</summary>
    private static Boolean IsPhysicalInterface(NetworkInterface ni)
    {
        var name = ni.Name.ToLower();
        var desc = (ni.Description ?? "").ToLower();

        // 排除虚拟网卡
        if (name.Contains("virtual") || desc.Contains("virtual")) return false;
        if (name.Contains("pseudo") || desc.Contains("pseudo")) return false;
        if (name.Contains("hyper-v") || desc.Contains("hyper-v")) return false;
        if (name.Contains("vmware") || desc.Contains("vmware")) return false;
        if (name.Contains("virtualbox") || desc.Contains("virtualbox")) return false;
        if (name.Contains("docker") || desc.Contains("docker")) return false;
        if (name.Contains("vpn") || desc.Contains("vpn")) return false;
        if (name.Contains("tap") || desc.Contains("tap")) return false;
        if (name.Contains("tun") || desc.Contains("tun")) return false;

        return true;
    }
}