初始提交

This commit is contained in:
2026-08-26 18:48:17 +08:00
commit 3c6ff7d205
5 changed files with 386 additions and 0 deletions

261
main.go Normal file
View File

@@ -0,0 +1,261 @@
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')
}