package main import ( "bufio" "fmt" "os" "strings" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) // 显卡类 GUID var gpuClassGUID = windows.GUID{ Data1: 0x4d36e968, Data2: 0xe325, Data3: 0x11ce, Data4: [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}, } // GPUInfo 保存一张显卡的信息 type GPUInfo struct { Name string // 显示名称 Path string // 注册表枚举路径(HKLM\SYSTEM\CurrentControlSet\Enum\...) ID string // 设备实例 ID } func main() { fmt.Println("============================================") fmt.Println(" 显卡名称修改工具 (GPU Rename) ") fmt.Println("============================================") fmt.Println() // 1. 枚举当前实际存在的物理显卡 gpus, err := enumerateGPUs() if err != nil { fmt.Printf("错误:枚举显卡失败 - %v\n", err) fmt.Println("提示:请以管理员身份运行本程序。") waitEnter() return } if len(gpus) == 0 { fmt.Println("错误:未检测到任何物理显卡设备。") waitEnter() return } // 2. 选择目标显卡 var target GPUInfo if len(gpus) > 1 { fmt.Printf("检测到 %d 块物理显卡,请选择要修改的显卡:\n", len(gpus)) for i, g := range gpus { fmt.Printf(" [%d] %s\n", i+1, g.Name) } fmt.Println() target, err = chooseGPU(gpus) if err != nil { fmt.Printf("错误:%v\n", err) waitEnter() return } } else { target = gpus[0] fmt.Printf("检测到 1 块物理显卡:%s\n\n", target.Name) } fmt.Printf("当前选中显卡:%s\n", target.Name) fmt.Printf("设备实例 ID:%s\n\n", target.ID) // 3. 输入新名称 newName := readNewName() if newName == "" { fmt.Println("已取消操作。") waitEnter() return } fmt.Printf("即将把显卡名称修改为:%s\n", newName) // 4. 执行修改 if err := renameGPU(target, newName); err != nil { fmt.Printf("错误:修改失败 - %v\n", err) fmt.Println("请确认已使用管理员权限运行。") waitEnter() return } fmt.Println("修改已写入注册表,正在验证...") // 5. 验证修改结果 verifyName, err := verifyGPU(target) if err != nil { fmt.Printf("警告:验证时发生错误 - %v\n", err) } else if verifyName == newName { fmt.Println("验证通过:显卡名称已成功修改为指定值。") } else { fmt.Printf("警告:验证结果与预期不一致,当前值为:%s\n", verifyName) fmt.Println(" 部分设备可能需要重启后才会在设备管理器中刷新。") } fmt.Println() fmt.Println("============================================") fmt.Println(" 修改成功!请重启机器以使修改完全生效。 ") fmt.Println("============================================") waitEnter() } // enumerateGPUs 使用 SetupAPI 枚举当前实际存在的物理显卡。 // 使用 DIGCF_PRESENT 标志,只列出真正连接在机器上的设备, // 并过滤掉虚拟显示适配器(无物理设备对象名)。 func enumerateGPUs() ([]GPUInfo, error) { // 只枚举当前存在的设备(DIGCF_PRESENT) devSet, err := windows.SetupDiGetClassDevsEx( &gpuClassGUID, "", 0, windows.DIGCF_PRESENT, 0, "", ) if err != nil { return nil, err } defer windows.SetupDiDestroyDeviceInfoList(devSet) var gpus []GPUInfo for i := 0; ; i++ { devInfo, err := windows.SetupDiEnumDeviceInfo(devSet, i) if err != nil { break // 枚举完毕 } // 过滤:只保留物理显卡(PCI 总线上的设备), // 排除 ROOT\SWD 等虚拟显示适配器。 enumerator := "" if v, err := windows.SetupDiGetDeviceRegistryProperty(devSet, devInfo, windows.SPDRP_ENUMERATOR_NAME); err == nil { if s, ok := v.(string); ok { enumerator = s } } if !strings.EqualFold(enumerator, "PCI") { continue } // 获取实例 ID instanceID, err := windows.SetupDiGetDeviceInstanceId(devSet, devInfo) if err != nil { continue } // 获取显示名称(优先 FriendlyName,其次 DeviceDesc) name := getDeviceName(devSet, devInfo, instanceID) gpus = append(gpus, GPUInfo{ Name: name, Path: instanceIDToRegPath(instanceID), ID: instanceID, }) } return gpus, nil } // getDeviceName 获取设备显示名称,优先 FriendlyName,回退到 DeviceDesc func getDeviceName(devSet windows.DevInfo, devInfo *windows.DevInfoData, fallback string) string { if v, err := windows.SetupDiGetDeviceRegistryProperty(devSet, devInfo, windows.SPDRP_FRIENDLYNAME); err == nil { if s, ok := v.(string); ok && strings.TrimSpace(s) != "" { return s } } if v, err := windows.SetupDiGetDeviceRegistryProperty(devSet, devInfo, windows.SPDRP_DEVICEDESC); err == nil { if s, ok := v.(string); ok && strings.TrimSpace(s) != "" { return cleanDeviceDesc(s) } } return fallback } // instanceIDToRegPath 将设备实例 ID 转换为注册表枚举路径。 // 例如 PCI\VEN_10DE&DEV_1DB1...\4&31024D2F&0&0018 // -> SYSTEM\CurrentControlSet\Enum\PCI\VEN_10DE&DEV_1DB1...\4&31024D2F&0&0018 func instanceIDToRegPath(instanceID string) string { return `SYSTEM\CurrentControlSet\Enum\` + instanceID } // cleanDeviceDesc 去掉 DeviceDesc 中的 INF 引用前缀,只保留可读名称 func cleanDeviceDesc(desc string) string { if idx := strings.LastIndex(desc, ";"); idx >= 0 && idx < len(desc)-1 { return desc[idx+1:] } return desc } // getDeviceDesc 读取注册表中的 DeviceDesc func getDeviceDesc(regPath string) (string, error) { k, err := registry.OpenKey(registry.LOCAL_MACHINE, regPath, registry.QUERY_VALUE) if err != nil { return "", err } defer k.Close() v, _, err := k.GetStringValue("DeviceDesc") return v, err } // chooseGPU 让用户从列表中选择一块显卡 func chooseGPU(gpus []GPUInfo) (GPUInfo, error) { reader := bufio.NewReader(os.Stdin) for { fmt.Printf("请输入显卡序号 (1-%d):", len(gpus)) input, _ := reader.ReadString('\n') input = strings.TrimSpace(input) var idx int if _, err := fmt.Sscanf(input, "%d", &idx); err != nil { fmt.Println("输入无效,请输入数字。") continue } if idx < 1 || idx > len(gpus) { fmt.Printf("序号超出范围,请输入 1-%d。\n", len(gpus)) continue } return gpus[idx-1], nil } } // readNewName 读取用户输入的新名称 func readNewName() string { reader := bufio.NewReader(os.Stdin) fmt.Print("请输入新的显卡名称(直接回车取消):") input, _ := reader.ReadString('\n') return strings.TrimSpace(input) } // renameGPU 修改注册表中的 DeviceDesc func renameGPU(g GPUInfo, newName string) error { k, err := registry.OpenKey(registry.LOCAL_MACHINE, g.Path, registry.SET_VALUE) if err != nil { return err } defer k.Close() return k.SetStringValue("DeviceDesc", newName) } // verifyGPU 重新读取 DeviceDesc 进行验证 func verifyGPU(g GPUInfo) (string, error) { desc, err := getDeviceDesc(g.Path) if err != nil { return "", err } return cleanDeviceDesc(desc), nil } // waitEnter 等待用户按键后退出 func waitEnter() { fmt.Println() fmt.Print("按回车键退出...") bufio.NewReader(os.Stdin).ReadString('\n') }