欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Go語(yǔ)言開(kāi)發(fā)一個(gè)智能exe文件重命名工具

 更新時(shí)間:2025年07月03日 08:54:49   作者:嘆一曲當(dāng)時(shí)只道是尋常  
在日常開(kāi)發(fā)和軟件管理中,我們經(jīng)常會(huì)遇到需要整理大量EXE文件的情況,本文將介紹如何使用Go語(yǔ)言開(kāi)發(fā)一個(gè)智能EXE文件重命名工具,需要的可以了解下

引言

在日常開(kāi)發(fā)和軟件管理中,我們經(jīng)常會(huì)遇到需要整理大量EXE文件的情況。這些文件往往有著不規(guī)范的命名,如setup.exe、installer.exe等,難以直接了解其具體內(nèi)容和版本。本文將介紹如何使用Go語(yǔ)言開(kāi)發(fā)一個(gè)智能EXE文件重命名工具,它能自動(dòng)提取文件的版本信息,并利用大模型API生成規(guī)范的命名建議。

工具功能概述

這個(gè)工具主要實(shí)現(xiàn)了以下功能:

  • 解析EXE文件的版本信息資源
  • 利用大模型API生成智能命名建議
  • 提供友好的命令行交互界面
  • 安全執(zhí)行文件重命名操作

核心技術(shù)實(shí)現(xiàn)

Windows版本信息API調(diào)用

Windows系統(tǒng)通過(guò)version.dll提供了訪問(wèn)文件版本信息的API。我們的工具使用了三個(gè)關(guān)鍵函數(shù):

  • GetFileVersionInfoSizeW - 獲取版本信息數(shù)據(jù)的大小
  • GetFileVersionInfoW - 獲取完整的版本信息數(shù)據(jù)
  • VerQueryValueW - 查詢(xún)特定的版本信息字段

在Go中調(diào)用這些API需要使用syscall包和unsafe指針操作:

var (
    versionDLL                  = syscall.NewLazyDLL("version.dll")
    procGetFileVersionInfoSizeW = versionDLL.NewProc("GetFileVersionInfoSizeW")
    procGetFileVersionInfoW     = versionDLL.NewProc("GetFileVersionInfoW")
    procVerQueryValueW          = versionDLL.NewProc("VerQueryValueW")
)

大模型API集成

工具集成了bigmodel API來(lái)生成智能命名建議(該模型免費(fèi),應(yīng)付這種場(chǎng)景綽綽有余):

cfg := openai.DefaultConfig(apiKey)
cfg.BaseURL = "https://open.bigmodel.cn/api/paas/v4/"
client := openai.NewClientWithConfig(cfg)

resp, err := client.CreateChatCompletion(
    context.Background(),
    openai.ChatCompletionRequest{
        Model: "GLM-4-Flash-250414",
        Messages: []openai.ChatCompletionMessage{
            {
                Role:    openai.ChatMessageRoleUser,
                Content: prompt,
            },
        },
        MaxTokens:   100,
        Temperature: 0.3,
    },
)

我們?cè)O(shè)計(jì)了提示詞(prompt),確保大模型返回規(guī)范的文件名:

  • 包含產(chǎn)品名稱(chēng)和版本號(hào)
  • 只使用字母、數(shù)字、中文、下劃線、連字符
  • 格式統(tǒng)一,如產(chǎn)品名_版本號(hào).exe產(chǎn)品名-版本號(hào).exe

交互式命令行界面

使用promptui庫(kù)創(chuàng)建了友好的交互界面:

// 確認(rèn)對(duì)話框
prompt := promptui.Select{
    Label: "是否根據(jù)建議重命名文件?",
    Items: []string{"是", "否"},
}

// 文本輸入框
prompt := promptui.Prompt{
    Label:     "請(qǐng)輸入新的文件名",
    Default:   suggestedName,
    AllowEdit: true,
}

完整工作流程

實(shí)際應(yīng)用示例

完整代碼

package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"unicode/utf16"
	"unsafe"

	"github.com/manifoldco/promptui"
	openai "github.com/sashabaranov/go-openai"
)

var (
	versionDLL                  = syscall.NewLazyDLL("version.dll")
	procGetFileVersionInfoSizeW = versionDLL.NewProc("GetFileVersionInfoSizeW")
	procGetFileVersionInfoW     = versionDLL.NewProc("GetFileVersionInfoW")
	procVerQueryValueW          = versionDLL.NewProc("VerQueryValueW")
)

// 檢查BIG_MODEL_KEY環(huán)境變量
func checkBigModelKey() error {
	key := os.Getenv("BIG_MODEL_KEY")
	if key != "" {
		return nil // 已經(jīng)設(shè)置了
	}

	fmt.Println("未找到BIG_MODEL_KEY環(huán)境變量,請(qǐng)手動(dòng)設(shè)置。例如:set BIG_MODEL_KEY=你的API密鑰")
	return fmt.Errorf("未設(shè)置BIG_MODEL_KEY環(huán)境變量")
}

func utf16PtrFromString(s string) *uint16 {
	u := utf16.Encode([]rune(s + "\x00"))
	return &u[0]
}

// Windows API方式獲取版本信息
func GetFileVersionInfoAPI(path string) (map[string]string, error) {
	info := make(map[string]string)
	pPath := utf16PtrFromString(path)
	var handle uint32
	size, _, _ := procGetFileVersionInfoSizeW.Call(
		uintptr(unsafe.Pointer(pPath)),
		uintptr(unsafe.Pointer(&handle)),
	)
	if size == 0 {
		return nil, fmt.Errorf("GetFileVersionInfoSizeW failed")
	}
	buf := make([]byte, size)
	ret, _, _ := procGetFileVersionInfoW.Call(
		uintptr(unsafe.Pointer(pPath)),
		0,
		uintptr(size),
		uintptr(unsafe.Pointer(&buf[0])),
	)
	if ret == 0 {
		return nil, fmt.Errorf("GetFileVersionInfoW failed")
	}

	// 查詢(xún)語(yǔ)言和代碼頁(yè)
	var transPtr uintptr
	var transLen uint32
	subBlock := utf16PtrFromString(`\VarFileInfo\Translation`)
	ret, _, _ = procVerQueryValueW.Call(
		uintptr(unsafe.Pointer(&buf[0])),
		uintptr(unsafe.Pointer(subBlock)),
		uintptr(unsafe.Pointer(&transPtr)),
		uintptr(unsafe.Pointer(&transLen)),
	)
	if ret == 0 || transLen < 4 {
		return nil, fmt.Errorf("VerQueryValueW Translation failed")
	}
	lang := *(*uint16)(unsafe.Pointer(transPtr))
	codepage := *(*uint16)(unsafe.Pointer(transPtr + 2))
	langCode := fmt.Sprintf("%04x%04x", lang, codepage)

	fields := []string{
		"FileDescription",
		"FileVersion",
		"ProductName",
		"ProductVersion",
		"LegalCopyright",
		"OriginalFilename",
		"InternalName",
		"CompanyName",
		"Comments",
	}

	for _, field := range fields {
		block := fmt.Sprintf(`\StringFileInfo\%s\%s`, langCode, field)
		blockPtr := utf16PtrFromString(block)
		var valuePtr uintptr
		var valueLen uint32
		ret, _, _ := procVerQueryValueW.Call(
			uintptr(unsafe.Pointer(&buf[0])),
			uintptr(unsafe.Pointer(blockPtr)),
			uintptr(unsafe.Pointer(&valuePtr)),
			uintptr(unsafe.Pointer(&valueLen)),
		)
		if ret != 0 && valueLen > 0 {
			val := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(valuePtr))[:valueLen])
			info[field] = val
		}
	}
	return info, nil
}

func getAPIKey() string {
	key := os.Getenv("BIG_MODEL_KEY")
	if key != "" {
		return key
	}
	fmt.Print("請(qǐng)輸入百川大模型 API KEY(BIG_MODEL_KEY):")
	var input string
	fmt.Scanln(&input)
	return strings.TrimSpace(input)
}

func GetRenameSuggestion(info map[string]string, originalName string) (string, error) {
	apiKey := getAPIKey()
	if apiKey == "" {
		return "", fmt.Errorf("未提供 BIG_MODEL_KEY")
	}

	cfg := openai.DefaultConfig(apiKey)
	cfg.BaseURL = "https://open.bigmodel.cn/api/paas/v4/"
	client := openai.NewClientWithConfig(cfg)

	prompt := fmt.Sprintf(`請(qǐng)根據(jù)以下EXE文件的版本信息,給出一個(gè)簡(jiǎn)潔、規(guī)范的文件重命名建議。
原始文件名: %s

版本信息:
- 文件描述: %s
- 文件版本: %s
- 產(chǎn)品名稱(chēng): %s
- 產(chǎn)品版本: %s
- 版權(quán)信息: %s
- 原始文件名: %s
- 內(nèi)部名稱(chēng): %s
- 公司名稱(chēng): %s
- 注釋: %s

重命名要求:
1. 使用中文或英文,簡(jiǎn)潔明了
2. 包含產(chǎn)品名稱(chēng)和版本號(hào)
3. 避免特殊字符,只使用字母、數(shù)字、中文、下劃線、連字符
4. 格式建議: 產(chǎn)品名_版本號(hào).exe 或 產(chǎn)品名-版本號(hào).exe
5. 如果產(chǎn)品名包含特殊字符,請(qǐng)適當(dāng)簡(jiǎn)化

請(qǐng)只返回重命名后的文件名(包含.exe擴(kuò)展名),不要其他解釋。`,
		originalName,
		getValueOrDefault(info, "FileDescription"),
		getValueOrDefault(info, "FileVersion"),
		getValueOrDefault(info, "ProductName"),
		getValueOrDefault(info, "ProductVersion"),
		getValueOrDefault(info, "LegalCopyright"),
		getValueOrDefault(info, "OriginalFilename"),
		getValueOrDefault(info, "InternalName"),
		getValueOrDefault(info, "CompanyName"),
		getValueOrDefault(info, "Comments"))

	resp, err := client.CreateChatCompletion(
		context.Background(),
		openai.ChatCompletionRequest{
			Model: "GLM-4-Flash-250414",
			Messages: []openai.ChatCompletionMessage{
				{
					Role:    openai.ChatMessageRoleUser,
					Content: prompt,
				},
			},
			MaxTokens:   100,
			Temperature: 0.3,
		},
	)
	if err != nil {
		return "", fmt.Errorf("API調(diào)用失敗: %w", err)
	}
	if len(resp.Choices) == 0 {
		return "", fmt.Errorf("未返回有效響應(yīng)")
	}
	suggestion := strings.TrimSpace(resp.Choices[0].Message.Content)
	return suggestion, nil
}

func getValueOrDefault(info map[string]string, key string) string {
	if value, exists := info[key]; exists && value != "" {
		return value
	}
	return "(無(wú))"
}

// 確認(rèn)是否重命名
func confirmRename() bool {
	prompt := promptui.Select{
		Label: "是否根據(jù)建議重命名文件?",
		Items: []string{"是", "否"},
	}

	_, result, err := prompt.Run()
	if err != nil {
		fmt.Printf("選擇失敗: %v\n", err)
		return false
	}

	return result == "是"
}

// 輸入新文件名
func inputNewFileName(suggestedName string) string {
	prompt := promptui.Prompt{
		Label:     "請(qǐng)輸入新的文件名",
		Default:   suggestedName,
		AllowEdit: true,
	}

	result, err := prompt.Run()
	if err != nil {
		fmt.Printf("輸入失敗: %v\n", err)
		return ""
	}

	return result
}

// 重命名文件
func renameFile(oldPath, newName string) error {
	dir := filepath.Dir(oldPath)
	newPath := filepath.Join(dir, newName)

	// 檢查新文件名是否已存在
	if _, err := os.Stat(newPath); err == nil {
		return fmt.Errorf("文件 %s 已存在", newName)
	}

	// 執(zhí)行重命名
	err := os.Rename(oldPath, newPath)
	if err != nil {
		return fmt.Errorf("重命名失敗: %w", err)
	}

	fmt.Printf("文件已重命名為: %s\n", newName)
	return nil
}

func main() {
	// 檢查BIG_MODEL_KEY
	if err := checkBigModelKey(); err != nil {
		return
	}

	if len(os.Args) < 2 {
		fmt.Println("請(qǐng)指定EXE文件路徑")
		fmt.Println("示例: .\\exeRename.exe your_file.exe")
		return
	}

	exePath := os.Args[1]
	info, err := GetFileVersionInfoAPI(exePath)
	if err != nil {
		fmt.Printf("錯(cuò)誤: %v\n", err)
		return
	}

	// 顯示版本信息
	fmt.Println("=== 版本信息 ===")
	fields := []string{"FileDescription", "FileVersion", "ProductName", "ProductVersion", "LegalCopyright", "OriginalFilename", "InternalName", "CompanyName", "Comments"}
	for _, field := range fields {
		value := info[field]
		if value == "" {
			value = "(無(wú))"
		}
		fmt.Printf("%-20s: %s\n", field, value)
	}

	// 獲取原始文件名(不含路徑)
	originalName := exePath
	if lastSlash := strings.LastIndex(exePath, "\\"); lastSlash != -1 {
		originalName = exePath[lastSlash+1:]
	}
	if lastSlash := strings.LastIndex(originalName, "/"); lastSlash != -1 {
		originalName = originalName[lastSlash+1:]
	}

	// 獲取重命名建議
	fmt.Println("\n=== 智能重命名建議 ===")
	suggestion, err := GetRenameSuggestion(info, originalName)
	if err != nil {
		fmt.Printf("獲取重命名建議失敗: %v\n", err)
		fmt.Println("請(qǐng)確保已設(shè)置環(huán)境變量 OPENAI_API_KEY")
		return
	}

	fmt.Printf("原始文件名: %s\n", originalName)
	fmt.Printf("建議重命名: %s\n", suggestion)

	// 詢(xún)問(wèn)是否重命名
	if confirmRename() {
		// 輸入新文件名
		newName := inputNewFileName(suggestion)
		if newName != "" {
			// 執(zhí)行重命名
			if err := renameFile(exePath, newName); err != nil {
				fmt.Printf("重命名失敗: %v\n", err)
			}
		}
	}
}

到此這篇關(guān)于使用Go語(yǔ)言開(kāi)發(fā)一個(gè)智能exe文件重命名工具的文章就介紹到這了,更多相關(guān)Go文件重命名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GoLand一鍵上傳項(xiàng)目到遠(yuǎn)程服務(wù)器的方法步驟

    GoLand一鍵上傳項(xiàng)目到遠(yuǎn)程服務(wù)器的方法步驟

    我們開(kāi)發(fā)項(xiàng)目常常將項(xiàng)目上傳到linux遠(yuǎn)程服務(wù)器上來(lái)運(yùn)行,本文主要介紹了GoLand一鍵上傳項(xiàng)目到遠(yuǎn)程服務(wù)器的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Go語(yǔ)言HTTPServer開(kāi)發(fā)的六種方式小結(jié)

    Go語(yǔ)言HTTPServer開(kāi)發(fā)的六種方式小結(jié)

    Golang的Server開(kāi)發(fā)顯得非常簡(jiǎn)單,有很多種方式,本文就介紹了Go語(yǔ)言HTTPServer開(kāi)發(fā)的六種方式,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-11-11
  • Golang中函數(shù)的使用方法詳解

    Golang中函數(shù)的使用方法詳解

    這篇文章主要詳細(xì)介紹了Golang中函數(shù)的使用方法,文中有詳細(xì)的示例代碼,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • golang實(shí)現(xiàn)aes-cbc-256加密解密功能

    golang實(shí)現(xiàn)aes-cbc-256加密解密功能

    這篇文章主要介紹了golang實(shí)現(xiàn)aes-cbc-256加密解密功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Golang中自定義json序列化時(shí)間格式的示例代碼

    Golang中自定義json序列化時(shí)間格式的示例代碼

    Go語(yǔ)言作為一個(gè)由Google開(kāi)發(fā),號(hào)稱(chēng)互聯(lián)網(wǎng)的C語(yǔ)言的語(yǔ)言,自然也對(duì)JSON格式支持很好,下面這篇文章主要介紹了關(guān)于Golang中自定義json序列化時(shí)間格式的相關(guān)內(nèi)容,下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧
    2024-08-08
  • golang中validator包的使用教程

    golang中validator包的使用教程

    Validator 實(shí)際上是一個(gè)驗(yàn)證工具,屬于 golang 的第三方包,這個(gè)包中使用了各種反射技巧來(lái)提供了各種校驗(yàn)和約束數(shù)據(jù)的方式方法,下面就跟隨小編一起來(lái)學(xué)習(xí)一下validator包的使用吧
    2023-09-09
  • go zero微服務(wù)高在請(qǐng)求量下如何優(yōu)化

    go zero微服務(wù)高在請(qǐng)求量下如何優(yōu)化

    這篇文章主要為大家介紹了go zero微服務(wù)高在請(qǐng)求量下的優(yōu)化處理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • golang實(shí)現(xiàn)LRU緩存淘汰算法的示例代碼

    golang實(shí)現(xiàn)LRU緩存淘汰算法的示例代碼

    這篇文章主要介紹了golang實(shí)現(xiàn)LRU緩存淘汰算法的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • 關(guān)于golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接的問(wèn)題

    關(guān)于golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接的問(wèn)題

    這篇文章主要介紹了golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Go語(yǔ)言等待組sync.WaitGrou的使用示例

    Go語(yǔ)言等待組sync.WaitGrou的使用示例

    本文主要介紹了Go語(yǔ)言等待組sync.WaitGrou的使用示例,sync.WaitGroup只有3個(gè)方法,Add(),Done(),Wait(),下面就來(lái)具體的介紹一下如何使用,感興趣的可以了解一下
    2024-08-08

最新評(píng)論