初始提交
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 editgpu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
97
README.md
Normal file
97
README.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# ⚠️ 重要声明 ⚠️
|
||||
|
||||
> # 🚨 免责声明
|
||||
>
|
||||
> ## 本工具仅供学习交流使用!
|
||||
>
|
||||
> ### 请勿用于任何商业用途、违法用途或对他人造成损害的用途!
|
||||
>
|
||||
> **使用本工具所造成的一切后果,由使用者自行承担!**
|
||||
>
|
||||
> - 修改注册表可能导致系统不稳定、驱动异常、设备无法识别等问题
|
||||
> - 请在操作前自行备份注册表与重要数据
|
||||
> - 操作需谨慎,风险自负
|
||||
|
||||
---
|
||||
|
||||
# 显卡名称修改工具 (GPU Rename)
|
||||
|
||||
一个用于修改 Windows 系统显卡显示名称的 Go 命令行小工具。
|
||||
|
||||
## ✨ 功能特性
|
||||
|
||||
- 自动枚举当前**实际连接**的物理显卡(PCI 总线),过滤掉幽灵设备与虚拟显示适配器
|
||||
- 显卡数量 > 1 时,列出列表供用户选择
|
||||
- 支持自定义显卡显示名称
|
||||
- 修改完成后自动验证结果
|
||||
- 修改成功后提示重启机器
|
||||
|
||||
## 🖥️ 运行环境
|
||||
|
||||
- Windows 7 / 8 / 10 / 11
|
||||
- 需要 **管理员权限** 运行(修改注册表 HKLM 需要)
|
||||
|
||||
## 📦 编译
|
||||
|
||||
```bash
|
||||
# 使用 Go 1.21+ 编译
|
||||
go mod tidy
|
||||
go build -o editgpu.exe .
|
||||
```
|
||||
|
||||
或直接使用已编译好的 `editgpu.exe`。
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
1. **右键** 以管理员身份运行 `editgpu.exe`
|
||||
2. 程序自动检测物理显卡:
|
||||
|
||||
- 只有 1 块显卡:直接选中
|
||||
- 多块显卡:输入序号选择要修改的显卡
|
||||
|
||||
3. 输入新的显卡名称(直接回车可取消)
|
||||
4. 程序自动修改注册表并验证
|
||||
5. 看到「修改成功」提示后,**重启电脑**使修改完全生效
|
||||
|
||||
## ⚙️ 工作原理
|
||||
|
||||
程序通过 Windows SetupAPI 枚举当前存在的显卡设备:
|
||||
|
||||
1. 使用 `DIGCF_PRESENT` 标志只获取当前实际连接的设备,排除历史遗留的幽灵设备
|
||||
2. 通过 `SPDRP_ENUMERATOR_NAME == "PCI"` 过滤,只保留物理显卡,排除虚拟显示适配器
|
||||
3. 获取设备实例 ID,映射到注册表路径 `HKLM\SYSTEM\CurrentControlSet\Enum\...`
|
||||
4. 修改该路径下的 `DeviceDesc` 注册表值
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
editgpu/
|
||||
├── main.go # 主程序源码
|
||||
├── go.mod # Go 模块配置
|
||||
├── go.sum # 依赖校验文件
|
||||
└── README.md # 本说明文档
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
**Q:提示「请以管理员身份运行」?**
|
||||
A:修改注册表需要管理员权限,请右键选择「以管理员身份运行」。
|
||||
|
||||
**Q:修改后设备管理器不显示新名称?**
|
||||
A:请重启电脑,重启后设备管理器会刷新显示新名称。
|
||||
|
||||
**Q:修改名称会影响显卡性能吗?**
|
||||
A:不会,仅修改显示名称,不影响硬件本身与驱动功能。
|
||||
|
||||
**Q:如何恢复原始名称?**
|
||||
A:重新运行本工具,输入原始显卡名称再次修改即可;或到设备管理器卸载设备后重新扫描硬件。
|
||||
|
||||
---
|
||||
|
||||
# ⚠️ 再次提醒 ⚠️
|
||||
|
||||
> ## 本工具仅供学习交流使用
|
||||
>
|
||||
> ### 因使用本工具产生的一切后果,由使用者自行承担!
|
||||
>
|
||||
> #### 请勿将本工具用于非法用途、商业用途或损害他人利益!
|
||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module editgpu
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require golang.org/x/sys v0.47.0
|
||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
261
main.go
Normal file
261
main.go
Normal 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')
|
||||
}
|
||||
Reference in New Issue
Block a user