使用Go语言获取Windows系统信息:从CPU到电池的全维度监控

在系统监控、设备管理或自动化运维场景中,获取操作系统的详细信息是一项基础且重要的工作。Go语言凭借其跨平台特性和简洁的语法,成为开发这类工具的理想选择。本文将详细介绍如何使用Go语言获取Windows系统的全方位信息,包括操作系统、CPU、内存、磁盘、网络、BIOS、主板及电池状态等。

技术准备:核心库介绍

要实现Windows系统信息的获取,我们主要依赖两个关键库:

  • gopsutil:一个跨平台的系统监控库,支持CPU、内存、磁盘、网络等基础信息的获取,简化了跨平台开发的复杂度。
  • go-ole:用于访问Windows的COM接口,通过它可以调用WMI(Windows Management Instrumentation)服务,获取BIOS、主板、电池等硬件级信息。

安装依赖:

bash 复制代码
go get github.com/shirou/gopsutil/v3
go get github.com/go-ole/go-ole

数据结构设计:统一信息组织方式

为了清晰地组织和输出系统信息,我们定义了一套结构化的数据模型,将不同类型的信息分类存储:

go 复制代码
// 系统信息总结构体
type SystemInfo struct {
	OSInfo      OSInfo        `json:"os_info"`      // 操作系统信息
	UserInfo    UserInfo      `json:"user_info"`    // 当前用户信息
	CPUInfo     CPUInfo       `json:"cpu_info"`     // CPU信息
	MemoryInfo  MemoryInfo    `json:"memory_info"`  // 内存信息
	DiskInfo    []DiskInfo    `json:"disk_info"`    // 磁盘信息
	NetworkInfo []NetworkInfo `json:"network_info"` // 网络信息
	BiosInfo    BiosInfo      `json:"bios_info"`    // BIOS信息
	Motherboard Motherboard   `json:"motherboard"`  // 主板信息
	BatteryInfo *BatteryInfo  `json:"battery_info"` // 电池信息(仅笔记本)
}

// 嵌套的子结构体(示例)
type OSInfo struct {
	Name          string    `json:"name"`           // 系统名称
	Version       string    `json:"version"`        // 系统版本
	Build         string    `json:"build"`          // 系统构建号
	Platform      string    `json:"platform"`       // 平台
	KernelVersion string    `json:"kernel_version"` // 内核版本
	BootTime      time.Time `json:"boot_time"`      // 启动时间
	Uptime        string    `json:"uptime"`         // 运行时长
}

这些结构体通过JSON标签序列化后,可直接输出为易读的JSON格式,便于后续处理和展示。

核心实现:分模块获取信息

1. 操作系统信息获取

通过gopsutil/host包可以轻松获取操作系统的基础信息,包括名称、版本、启动时间等:

go 复制代码
func getOSInfo() OSInfo {
	hostInfo, _ := host.Info()
	bootTime := time.Unix(int64(hostInfo.BootTime), 0) // 转换启动时间为time.Time
	uptime := time.Since(bootTime).Round(time.Second)  // 计算运行时长

	return OSInfo{
		Name:          hostInfo.OS,
		Version:       hostInfo.PlatformVersion,
		Build:         hostInfo.KernelVersion,
		Platform:      hostInfo.Platform,
		KernelVersion: hostInfo.KernelVersion,
		BootTime:      bootTime,
		Uptime:        uptime.String(),
	}
}

2. 当前用户信息

使用Go标准库的os/useros包获取当前登录用户的用户名和家目录:

go 复制代码
func getUserInfo() UserInfo {
	currentUser, err := user.Current()
	if err != nil {
		return UserInfo{Username: "unknown", HomeDir: "unknown"}
	}

	homeDir, err := os.UserHomeDir()
	if err != nil {
		homeDir = "unknown"
	}

	return UserInfo{
		Username: currentUser.Username,
		HomeDir:  homeDir,
	}
}

3. CPU信息获取

gopsutil/cpu包提供了CPU的详细信息,包括型号、核心数、主频等:

go 复制代码
func getCPUInfo() CPUInfo {
	cpuInfos, _ := cpu.Info()
	logicalCores, _ := cpu.Counts(true) // 逻辑核心数

	if len(cpuInfos) == 0 {
		return CPUInfo{}
	}
	info := cpuInfos[0]

	return CPUInfo{
		ModelName:     info.ModelName,    // 例如:Intel(R) Core(TM) i7-10700K
		PhysicalCores: int(info.Cores),   // 物理核心数
		LogicalCores:  logicalCores,      // 逻辑核心数(考虑超线程)
		Mhz:           info.Mhz,          // 主频(MHz)
		VendorID:      info.VendorID,     // 厂商ID(例如:GenuineIntel)
	}
}

4. 内存信息获取

通过gopsutil/mem获取内存总量、可用量及使用率,并转换为GB单位便于阅读:

go 复制代码
func getMemoryInfo() MemoryInfo {
	memInfo, _ := mem.VirtualMemory()
	return MemoryInfo{
		TotalGB:      float64(memInfo.Total) / 1024 / 1024 / 1024,  // 总内存(GB)
		AvailableGB:  float64(memInfo.Available) / 1024 / 1024 / 1024, // 可用内存(GB)
		UsedGB:       float64(memInfo.Used) / 1024 / 1024 / 1024,   // 已用内存(GB)
		UsagePercent: memInfo.UsedPercent,  // 使用率(%)
	}
}

5. 磁盘信息获取

遍历所有磁盘分区,获取每个分区的设备名、挂载点及容量信息:

go 复制代码
func getDiskInfo() []DiskInfo {
	partitions, _ := disk.Partitions(true) // 获取所有分区(包括虚拟分区)
	var diskInfos []DiskInfo

	for _, part := range partitions {
		usage, err := disk.Usage(part.Mountpoint)
		if err != nil {
			continue // 跳过无法访问的分区
		}

		diskInfos = append(diskInfos, DiskInfo{
			Device:       part.Device,     // 设备名(例如:C:\\)
			Mountpoint:   part.Mountpoint, // 挂载点
			FSType:       part.Fstype,     // 文件系统(例如:NTFS)
			TotalGB:      float64(usage.Total) / 1024 / 1024 / 1024,
			FreeGB:       float64(usage.Free) / 1024 / 1024 / 1024,
			UsedGB:       float64(usage.Used) / 1024 / 1024 / 1024,
			UsagePercent: usage.UsedPercent,
		})
	}
	return diskInfos
}

6. 网络信息获取

通过标准库net获取网卡信息(名称、MAC地址、IP地址),并通过WMI查询网关地址:

go 复制代码
func getNetworkInfo() []NetworkInfo {
	ifaces, _ := net.Interfaces() // 获取所有网络接口
	var netInfos []NetworkInfo

	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // 跳过未启用的网卡
		}

		// 提取IPv4和IPv6地址
		var ipv4, ipv6 []string
		addrs, _ := iface.Addrs()
		for _, addr := range addrs {
			ipNet, ok := addr.(*net.IPNet)
			if !ok {
				continue
			}
			ip := ipNet.IP.String()
			if ipNet.IP.To4() != nil {
				ipv4 = append(ipv4, ip)
			} else {
				ipv6 = append(ipv6, ip)
			}
		}

		// 通过WMI获取网关
		gateway := getGateway(iface.Name)

		netInfos = append(netInfos, NetworkInfo{
			Name:    iface.Name,
			MAC:     iface.HardwareAddr.String(),
			IPv4:    ipv4,
			IPv6:    ipv6,
			Gateway: gateway,
		})
	}
	return netInfos
}

7. BIOS与主板信息(基于WMI)

Windows的硬件信息(如BIOS、主板)需要通过WMI查询。我们封装了通用的WMI查询函数:

go 复制代码
// 通用WMI查询函数
func queryWMI(query string) ([]map[string]interface{}, error) {
	service, err := createWMIService() // 创建WMI服务连接
	if err != nil || service == nil {
		return nil, err
	}
	defer service.Release()

	// 执行查询并解析结果(省略具体实现)
	// ...
}

// 获取BIOS信息
func getBiosInfo() BiosInfo {
	data, _ := queryWMI("SELECT Manufacturer, Version, ReleaseDate FROM Win32_BIOS")
	if len(data) == 0 {
		return BiosInfo{}
	}
	return BiosInfo{
		Manufacturer: getStringFromMap(data[0], "Manufacturer"),
		Version:      getStringFromMap(data[0], "Version"),
		ReleaseDate:  getStringFromMap(data[0], "ReleaseDate"),
	}
}

// 获取主板信息
func getMotherboardInfo() Motherboard {
	data, _ := queryWMI("SELECT Manufacturer, Product FROM Win32_BaseBoard")
	if len(data) == 0 {
		return Motherboard{}
	}
	return Motherboard{
		Manufacturer: getStringFromMap(data[0], "Manufacturer"),
		Model:        getStringFromMap(data[0], "Product"),
	}
}

8. 电池信息(针对笔记本)

通过WMI查询Win32_Battery类获取电池状态:

go 复制代码
func getBatteryInfo() *BatteryInfo {
	data, _ := queryWMI(`SELECT DesignCapacity, FullChargeCapacity, 
		CurrentCapacity, EstimatedChargeRemaining, Status FROM Win32_Battery`)
	if len(data) == 0 {
		return nil // 台式机可能无电池,返回nil
	}

	item := data[0]
	status := ""
	switch getIntFromMap(item, "Status") {
	case 1:
		status = "放电中"
	case 2:
		status = "充电中"
	case 3:
		status = "充满电"
	default:
		status = "未知"
	}

	return &BatteryInfo{
		DesignCapacity:     getIntFromMap(item, "DesignCapacity"),
		FullChargeCapacity: getIntFromMap(item, "FullChargeCapacity"),
		CurrentCapacity:    getIntFromMap(item, "CurrentCapacity"),
		ChargePercent:      getIntFromMap(item, "EstimatedChargeRemaining"),
		Status:             status,
	}
}

整合与输出

main函数中整合所有信息,并序列化为JSON输出:

go 复制代码
func main() {
	ole.CoInitialize(0) // 初始化COM(WMI依赖)
	defer ole.CoUninitialize()

	// 收集所有系统信息
	sysInfo := SystemInfo{
		OSInfo:      getOSInfo(),
		UserInfo:    getUserInfo(),
		CPUInfo:     getCPUInfo(),
		MemoryInfo:  getMemoryInfo(),
		DiskInfo:    getDiskInfo(),
		NetworkInfo: getNetworkInfo(),
		BiosInfo:    getBiosInfo(),
		Motherboard: getMotherboardInfo(),
		BatteryInfo: getBatteryInfo(),
	}

	// 输出为格式化的JSON
	jsonData, _ := json.MarshalIndent(sysInfo, "", "  ")
	fmt.Println(string(jsonData))
}

运行结果示例

执行程序后,会输出类似以下的JSON结果(简化版):

json 复制代码
{
  "os_info": {
    "name": "Microsoft Windows 10 Pro",
    "version": "10.0.19045",
    "boot_time": "2023-10-01T08:30:00+08:00",
    "uptime": "5h30m0s"
  },
  "cpu_info": {
    "model_name": "Intel(R) Core(TM) i7-10700K",
    "physical_cores": 8,
    "logical_cores": 16,
    "mhz": 3800.0
  },
  "memory_info": {
    "total_gb": 31.9,
    "available_gb": 15.2,
    "usage_percent": 52.4
  }
  // ... 其他信息省略
}

总结

本文通过Go语言结合gopsutilgo-ole库,实现了Windows系统全方位信息的获取。核心思路是:

  1. 利用gopsutil获取跨平台通用信息(CPU、内存、磁盘等);
  2. 通过WMI(借助go-ole)获取Windows特有的硬件信息(BIOS、主板、电池等);
  3. 用结构化数据模型组织信息,最终输出为易读的JSON格式。

这种方案既利用了gopsutil的便捷性,又通过WMI补充了Windows特有的硬件细节,适合开发Windows系统监控工具、设备管理软件等场景。如需扩展,可进一步查询WMI的其他类(如Win32_VideoController获取显卡信息),实现更全面的系统监控。

相关推荐
郝学胜-神的一滴4 分钟前
对于类似std::shared_ptr但有可能空悬的指针使用std::weak_ptr: Effective Modern C++ 条款20
开发语言·c++·程序人生·系统架构
limnade7 分钟前
falsk windows 服务器部署-解决服务器外无法访问
服务器·windows·flask·智能路由器
KS、zheng16 分钟前
【DOCKER】Windows Server 2016 Datacenter离线安装Docker引擎
windows·docker·容器
linux修理工25 分钟前
使用 SecureCRT 连接华为 eNSP 模拟器的方法
服务器·开发语言·php
若水晴空初如梦32 分钟前
QT聊天项目DAY17
开发语言·qt
Murphy_lx44 分钟前
C++ stdset 与 stdmultiset 深度比较
开发语言·c++
LZQqqqqo1 小时前
C# 事件Event
开发语言·c#
样子20181 小时前
PHP 之使用HTMLPurifier过滤XSS
开发语言·前端·php·xss
C_Liu_2 小时前
从C语言到C++:拥抱面向对象编程的全新世界
c语言·开发语言·c++