解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
4.94 KiB
X
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using NewLife;

namespace Mobile;

/// <summary>机器信息文本报告。桌面、Android 与 iOS 宿主共用同一份采集逻辑。</summary>
public static class MachineInfoReport
{
    /// <summary>采集一次机器信息并生成文本报告。</summary>
    /// <param name="title">报告标题</param>
    /// <returns>可直接输出到控制台或屏幕的纯文本</returns>
    public static String Build(String title = "新生命移动测试台")
    {
        var sb = new StringBuilder();
        sb.AppendLine("=== " + title + " ===");
        sb.AppendLine("采集时间: " + DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture));
        sb.AppendLine();

        var info = new MachineInfo();
        try
        {
            info.Init();

            // 首次采样无法计算 CPU 与网络速度,稍等再刷新一次
            Thread.Sleep(500);
            info.Refresh();
        }
        catch (Exception ex)
        {
            sb.AppendLine("[MachineInfo] 采集异常: " + ex.Message);
        }

        AppendSection(sb, "MachineInfo", [
            ("系统名称", info.OSName),
            ("系统版本", info.OSVersion),
            ("产品名称", info.Product),
            ("设备名称", info["DeviceName"] as String),
            ("制造商", info.Vendor),
            ("处理器型号", info.Processor),
            ("硬件唯一标识", info.UUID),
            ("软件唯一标识", info.Guid),
            ("计算机序列号", info.Serial),
            ("主板", info.Board),
            ("磁盘序列号", info.DiskID),
            ("内存总量", FormatSize(info.Memory)),
            ("可用内存", FormatSize(info.AvailableMemory)),
            ("空闲内存", FormatSize(info.FreeMemory)),
            ("CPU占用率", FormatPercent(info.CpuRate)),
            ("网络上行速度", FormatSpeed(info.UplinkSpeed)),
            ("网络下行速度", FormatSpeed(info.DownlinkSpeed)),
            ("温度", FormatNumber(info.Temperature, " °C")),
            ("电池剩余", FormatPercent(info.Battery)),
        ]);

        AppendSection(sb, "运行时", [
            ("框架", RuntimeInformation.FrameworkDescription),
            ("运行时标识", RuntimeInformation.RuntimeIdentifier),
            ("OS 描述", RuntimeInformation.OSDescription),
            ("进程架构", RuntimeInformation.ProcessArchitecture + ""),
            ("Mono", Runtime.Mono + ""),
            ("Unity", Runtime.Unity + ""),
            ("容器", Runtime.Container + ""),
            ("控制台宿主", Runtime.IsConsole + ""),
            ("进程编号", Runtime.ProcessId + ""),
            ("运行时长", FormatDuration(Runtime.TickCount64)),
        ]);

        AppendSection(sb, "环境", [
            ("机器名称", Environment.MachineName),
            ("用户名称", SafeGet(() => Environment.UserName)),
            ("处理器数量", Environment.ProcessorCount + ""),
            ("64位进程", Environment.Is64BitProcess + ""),
            ("CLR 版本", Environment.Version + ""),
            ("托管内存", GC.GetTotalMemory(false).ToGMK()),
            ("工作集", Environment.WorkingSet.ToGMK()),
            ("时区", TimeZoneInfo.Local.Id),
        ]);

        AppendSection(sb, "路径", [
            ("程序目录", AppContext.BaseDirectory),
            ("当前目录", Environment.CurrentDirectory),
            ("应用数据", SafeGet(() => Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData))),
            ("临时目录", Path.GetTempPath()),
        ]);

        return sb.ToString();
    }

    private static void AppendSection(StringBuilder sb, String title, IEnumerable<(String Name, String? Value)> items)
    {
        sb.AppendLine("[" + title + "]");
        foreach (var (name, value) in items)
        {
            sb.AppendLine(name + ": " + value);
        }
        sb.AppendLine();
    }

    private static String SafeGet(Func<String> func)
    {
        try
        {
            return func();
        }
        catch (Exception ex)
        {
            return "读取失败: " + ex.Message;
        }
    }

    private static String FormatSize(UInt64 value) => value == 0 ? "0" : $"{value.ToGMK()} ({value:n0} B)";
    private static String FormatSpeed(UInt64 value) => value.ToGMK() + "/s";
    private static String FormatPercent(Double value) => (value * 100).ToString("n2", CultureInfo.InvariantCulture) + "%";
    private static String FormatNumber(Double value, String unit) => value == 0 ? "0" : value.ToString("n1", CultureInfo.InvariantCulture) + unit;

    private static String FormatDuration(Int64 milliseconds)
    {
        var span = TimeSpan.FromMilliseconds(milliseconds);
        return span.Days > 0
            ? $"{span.Days}天{span.Hours:00}:{span.Minutes:00}:{span.Seconds:00}"
            : $"{span.Hours:00}:{span.Minutes:00}:{span.Seconds:00}";
    }
}