Golang跨平台获取DLL文件版本和产品版本信息的方法
Golang跨平台获取DLL文件版本和产品版本信息的方法
package main
import (
"fmt"
"io/ioutil"
"log"
"bytes"
"os"
)
func main() {
content, err := ioutil.ReadFile("F:/tesdll/Microsoft.AspNetCore.Authentication.Abstractions.dll")
if err != nil {
log.Fatal(err)
}
}
通过读取 DLL 信息,我应该能够获取 DLL 文件版本和产品版本。 这应该在 Windows 和 Linux 系统上无缝运行。
提前感谢
更多关于Golang跨平台获取DLL文件版本和产品版本信息的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我的代码将在Linux机器上运行,但正在读取dll文件…
更多关于Golang跨平台获取DLL文件版本和产品版本信息的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
您可以检查内容中该信息所在的位置。 每个DLL内部都包含一个称为StringFileInfo的特殊信息,然后搜索诸如ProductVersion和FileVersion之类的标签。
在这种情况下,我指的是动态加载的库(作为 .so 文件)
Selvin_Thangadurai:
应该在Windows和Linux上无缝运行。
Linux不使用DLL…
非常感谢 Yamil_Bracho
以下是跨平台获取DLL文件版本和产品版本信息的方法。可以使用debug/pe包解析Windows PE文件格式,这在Windows和Linux上都能正常工作:
package main
import (
"debug/pe"
"encoding/binary"
"fmt"
"log"
"os"
"strings"
)
// VS_VERSION_INFO结构体
type VS_VERSION_INFO struct {
Length uint16
ValueLength uint16
Type uint16
Key [16]uint16
}
// StringFileInfo结构体
type StringFileInfo struct {
Length uint16
ValueLength uint16
Type uint16
Key [16]uint16
Padding uint16
Children []StringTable
}
// StringTable结构体
type StringTable struct {
Length uint16
ValueLength uint16
Type uint16
Key [16]uint16
Padding uint16
Children []String
}
// String结构体
type String struct {
Length uint16
ValueLength uint16
Type uint16
Key []uint16
Padding uint16
Value []uint16
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go <dll_file>")
return
}
filePath := os.Args[1]
versionInfo, err := getDLLVersionInfo(filePath)
if err != nil {
log.Fatal(err)
}
fmt.Printf("文件版本: %s\n", versionInfo["FileVersion"])
fmt.Printf("产品版本: %s\n", versionInfo["ProductVersion"])
fmt.Printf("产品名称: %s\n", versionInfo["ProductName"])
fmt.Printf("文件描述: %s\n", versionInfo["FileDescription"])
fmt.Printf("公司名称: %s\n", versionInfo["CompanyName"])
}
func getDLLVersionInfo(filePath string) (map[string]string, error) {
file, err := pe.Open(filePath)
if err != nil {
return nil, fmt.Errorf("打开PE文件失败: %v", err)
}
defer file.Close()
// 查找.rsrc段
var rsrcSection *pe.Section
for _, section := range file.Sections {
if section.Name == ".rsrc\x00\x00\x00" {
rsrcSection = section
break
}
}
if rsrcSection == nil {
return nil, fmt.Errorf("未找到.rsrc段")
}
// 读取.rsrc段数据
rsrcData := make([]byte, rsrcSection.Size)
_, err = file.Seek(int64(rsrcSection.Offset), 0)
if err != nil {
return nil, fmt.Errorf("读取.rsrc段失败: %v", err)
}
_, err = file.File.Read(rsrcData)
if err != nil {
return nil, fmt.Errorf("读取.rsrc数据失败: %v", err)
}
// 查找版本信息资源
versionInfo, err := findVersionInfo(rsrcData)
if err != nil {
return nil, err
}
return parseVersionInfo(versionInfo)
}
func findVersionInfo(rsrcData []byte) ([]byte, error) {
// 简化的版本信息查找逻辑
// 在实际应用中需要完整解析资源目录结构
vsVersionInfoSignature := []byte("VS_VERSION_INFO")
for i := 0; i < len(rsrcData)-len(vsVersionInfoSignature); i++ {
if bytes.Equal(rsrcData[i:i+len(vsVersionInfoSignature)], vsVersionInfoSignature) {
// 找到版本信息块,返回整个块
start := i - 6 // VS_VERSION_INFO结构体开始位置
if start < 0 {
start = 0
}
// 读取块长度
if start+2 > len(rsrcData) {
return nil, fmt.Errorf("无效的版本信息块")
}
length := binary.LittleEndian.Uint16(rsrcData[start:])
if start+int(length) > len(rsrcData) {
return nil, fmt.Errorf("版本信息块长度超出范围")
}
return rsrcData[start : start+int(length)], nil
}
}
return nil, fmt.Errorf("未找到版本信息")
}
func parseVersionInfo(data []byte) (map[string]string, error) {
result := make(map[string]string)
if len(data) < 6 {
return nil, fmt.Errorf("版本信息数据过短")
}
// 解析VS_VERSION_INFO
var vs VS_VERSION_INFO
vs.Length = binary.LittleEndian.Uint16(data[0:])
vs.ValueLength = binary.LittleEndian.Uint16(data[2:])
vs.Type = binary.LittleEndian.Uint16(data[4:])
// 查找StringFileInfo
stringFileInfoPos := 6 + 32 // VS_VERSION_INFO头部 + Key
if stringFileInfoPos+4 > len(data) {
return nil, fmt.Errorf("StringFileInfo位置超出范围")
}
// 简化的字符串解析
// 在实际应用中需要完整解析StringFileInfo和StringTable结构
content := string(data)
// 查找常见的版本信息字段
fields := []string{
"FileVersion",
"ProductVersion",
"ProductName",
"FileDescription",
"CompanyName",
}
for _, field := range fields {
if value := extractStringValue(content, field); value != "" {
result[field] = value
}
}
return result, nil
}
func extractStringValue(content, field string) string {
prefix := field + "\x00"
start := strings.Index(content, prefix)
if start == -1 {
return ""
}
valueStart := start + len(prefix)
end := strings.Index(content[valueStart:], "\x00")
if end == -1 {
return ""
}
return strings.TrimSpace(content[valueStart : valueStart+end])
}
// 辅助函数:比较字节切片
func bytes.Equal(a, b []byte) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
使用方法:
go run main.go Microsoft.AspNetCore.Authentication.Abstractions.dll
这个实现:
- 使用
debug/pe包解析PE文件格式 - 查找.rsrc资源段中的版本信息
- 解析VS_VERSION_INFO结构获取版本数据
- 在Windows和Linux上都能运行
注意:这是一个简化版本,完整的版本信息解析需要处理PE文件资源目录的完整结构。对于生产环境,建议使用更成熟的第三方库如github.com/josephspurrier/goversioninfo。

