golang 获取exe、dll、apk 版本号

codyguo · · 2026 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

//聽golang聽实现读取exe聽dll聽apk聽版本号
package聽main

import聽(
聽聽聽聽"flag"
聽聽聽聽"fmt"
聽聽聽聽"log"
聽聽聽聽"os"
聽聽聽聽"path/filepath"
)

import聽(
聽聽聽聽"github.com/lunny/axmlParser"
)

var聽(
聽聽聽聽file聽fileInfo
)

const聽(
聽聽聽聽MZ聽聽聽聽聽聽聽=聽"MZ"
聽聽聽聽PE聽聽聽聽聽聽聽=聽"PE"
聽聽聽聽RSRC聽聽聽聽聽=聽".rsrc"
聽聽聽聽TYPET聽聽聽聽=聽16
聽聽聽聽PEOFFSET聽=聽64
聽聽聽聽MACHINE聽聽=聽332
聽聽聽聽DEFAULT聽聽=聽`C:\Windows\System32\cmd.exe`
)

type聽fileInfo聽struct聽{
聽聽聽聽FilePath聽string
聽聽聽聽Version聽聽string
聽聽聽聽Debug聽聽聽聽bool
}

func聽(f聽*fileInfo)聽checkError(err聽error)聽{
聽聽聽聽if聽err聽!=聽nil聽{
聽聽聽聽聽聽聽聽log.Fatalln(err)
聽聽聽聽}
}

//聽获取exe聽dll版本
func聽(f聽*fileInfo)聽GetExeVersion()聽(err聽error)聽{
聽聽聽聽file,聽err聽:=聽os.Open(f.FilePath)
聽聽聽聽f.checkError(err)

聽聽聽聽//聽第一次读取64聽byte
聽聽聽聽buffer聽:=聽make([]byte,聽64)
聽聽聽聽_,聽err聽=聽file.Read(buffer)
聽聽聽聽f.checkError(err)
聽聽聽聽defer聽file.Close()

聽聽聽聽str聽:=聽string(buffer[0])聽+聽string(buffer[1])
聽聽聽聽if聽str聽!=聽MZ聽{
聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽MZ.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽peOffset聽:=聽f.unpack([]byte{buffer[60],聽buffer[61],聽buffer[62],聽buffer[63]})
聽聽聽聽if聽peOffset聽<聽PEOFFSET聽{
聽聽聽聽聽聽聽聽log.Fatalln("peOffset聽读取错误.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽//聽读取从文件开头移位到聽peOffset,第二次读取聽24聽byte
聽聽聽聽_,聽err聽=聽file.Seek(int64(peOffset),聽0)
聽聽聽聽buffer聽=聽make([]byte,聽24)
聽聽聽聽_,聽err聽=聽file.Read(buffer)
聽聽聽聽f.checkError(err)

聽聽聽聽str聽=聽string(buffer[0])聽+聽string(buffer[1])
聽聽聽聽if聽str聽!=聽PE聽{
聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽PE.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽machine聽:=聽f.unpack([]byte{buffer[4],聽buffer[5]})
聽聽聽聽if聽machine聽!=聽MACHINE聽{
聽聽聽聽聽聽聽聽log.Fatalln("machine聽读取错误.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽noSections聽:=聽f.unpack([]byte{buffer[6],聽buffer[7]})
聽聽聽聽optHdrSize聽:=聽f.unpack([]byte{buffer[20],聽buffer[21]})

聽聽聽聽//聽读取从当前位置移位到聽optHdrSize,第三次读取聽40聽byte
聽聽聽聽file.Seek(int64(optHdrSize),聽1)
聽聽聽聽resFound聽:=聽false
聽聽聽聽for聽i聽:=聽0;聽i聽<聽int(noSections);聽i++聽{
聽聽聽聽聽聽聽聽buffer聽=聽make([]byte,聽40)
聽聽聽聽聽聽聽聽file.Read(buffer)
聽聽聽聽聽聽聽聽str聽=聽string(buffer[0])聽+聽string(buffer[1])聽+聽string(buffer[2])聽+聽string(buffer[3])聽+聽string(buffer[4])
聽聽聽聽聽聽聽聽if聽str聽==聽RSRC聽{
聽聽聽聽聽聽聽聽聽聽聽聽resFound聽=聽true
聽聽聽聽聽聽聽聽聽聽聽聽break
聽聽聽聽聽聽聽聽}
聽聽聽聽}
聽聽聽聽if聽!resFound聽{
聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽.rsrc.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽infoVirt聽:=聽f.unpack([]byte{buffer[12],聽buffer[13],聽buffer[14],聽buffer[15]})
聽聽聽聽infoSize聽:=聽f.unpack([]byte{buffer[16],聽buffer[17],聽buffer[18],聽buffer[19]})
聽聽聽聽infoOff聽:=聽f.unpack([]byte{buffer[20],聽buffer[21],聽buffer[22],聽buffer[23]})

聽聽聽聽//聽读取从文件开头位置移位到聽infoOff,第四次读取聽infoSize聽byte
聽聽聽聽file.Seek(int64(infoOff),聽0)
聽聽聽聽buffer聽=聽make([]byte,聽infoSize)
聽聽聽聽_,聽err聽=聽file.Read(buffer)
聽聽聽聽f.checkError(err)

聽聽聽聽nameEntries聽:=聽f.unpack([]byte{buffer[12],聽buffer[13]})
聽聽聽聽idEntries聽:=聽f.unpack([]byte{buffer[14],聽buffer[15]})

聽聽聽聽var聽infoFound聽bool
聽聽聽聽var聽subOff,聽i聽int64
聽聽聽聽for聽i聽=聽0;聽i聽<聽(nameEntries聽+聽idEntries);聽i++聽{
聽聽聽聽聽聽聽聽typeT聽:=聽f.unpack([]byte{buffer[i*8+16],聽buffer[i*8+17],聽buffer[i*8+18],聽buffer[i*8+19]})
聽聽聽聽聽聽聽聽if聽typeT聽==聽TYPET聽{
聽聽聽聽聽聽聽聽聽聽聽聽infoFound聽=聽true
聽聽聽聽聽聽聽聽聽聽聽聽subOff聽=聽int64(f.unpack([]byte{buffer[i*8+20],聽buffer[i*8+21],聽buffer[i*8+22],聽buffer[i*8+23]}))
聽聽聽聽聽聽聽聽聽聽聽聽break
聽聽聽聽聽聽聽聽}
聽聽聽聽}
聽聽聽聽if聽!infoFound聽{
聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽typeT聽==聽16.",聽f.FilePath)
聽聽聽聽}

聽聽聽聽subOff聽=聽subOff聽&聽0x7fffffff
聽聽聽聽infoOff聽=聽f.unpack([]byte{buffer[subOff+20],聽buffer[subOff+21],聽buffer[subOff+22],聽buffer[subOff+23]})聽//offset聽of聽first聽FILEINFO
聽聽聽聽infoOff聽=聽infoOff聽&聽0x7fffffff
聽聽聽聽infoOff聽=聽f.unpack([]byte{buffer[infoOff+20],聽buffer[infoOff+21],聽buffer[infoOff+22],聽buffer[infoOff+23]})聽//offset聽to聽data
聽聽聽聽dataOff聽:=聽f.unpack([]byte{buffer[infoOff],聽buffer[infoOff+1],聽buffer[infoOff+2],聽buffer[infoOff+3]})
聽聽聽聽dataOff聽=聽dataOff聽-聽infoVirt

聽聽聽聽version1聽:=聽f.unpack([]byte{buffer[dataOff+48],聽buffer[dataOff+48+1]})
聽聽聽聽version2聽:=聽f.unpack([]byte{buffer[dataOff+48+2],聽buffer[dataOff+48+3]})
聽聽聽聽version3聽:=聽f.unpack([]byte{buffer[dataOff+48+4],聽buffer[dataOff+48+5]})
聽聽聽聽version4聽:=聽f.unpack([]byte{buffer[dataOff+48+6],聽buffer[dataOff+48+7]})

聽聽聽聽version聽:=聽fmt.Sprintf("%d.%d.%d.%d",聽version2,聽version1,聽version4,聽version3)
聽聽聽聽f.Version聽=聽version

聽聽聽聽return聽nil
}

func聽(f聽*fileInfo)聽unpack(b聽[]byte)聽(num聽int64)聽{
聽聽聽聽for聽i聽:=聽0;聽i聽<聽len(b);聽i++聽{
聽聽聽聽聽聽聽聽num聽=聽256*num聽+聽int64((b[len(b)-1-i]聽&聽0xff))
聽聽聽聽}
聽聽聽聽return
}

//聽获取聽apk聽版本
func聽(f聽*fileInfo)聽GetApkVersion()聽(err聽error)聽{
聽聽聽聽listener聽:=聽new(axmlParser.AppNameListener)
聽聽聽聽_,聽err聽=聽axmlParser.ParseApk(f.FilePath,聽listener)
聽聽聽聽f.checkError(err)

聽聽聽聽f.Version聽=聽listener.VersionName
聽聽聽聽return聽nil
}

func聽init()聽{
聽聽聽聽flag.StringVar(&file.FilePath,聽"path",聽DEFAULT,聽"Get聽exe聽or聽dll聽or聽apk聽version聽information.")
聽聽聽聽flag.BoolVar(&file.Debug,聽"d",聽false,聽"if聽true聽print聽exe聽or聽dll聽file聽name.")
}

func聽main()聽{
聽聽聽聽flag.Parse()

聽聽聽聽suffix聽:=聽filepath.Ext(file.FilePath)
聽聽聽聽switch聽suffix聽{
聽聽聽聽case聽".exe",聽".dll":
聽聽聽聽聽聽聽聽file.GetExeVersion()
聽聽聽聽case聽".apk":
聽聽聽聽聽聽聽聽file.GetApkVersion()
聽聽聽聽default:
聽聽聽聽聽聽聽聽log.Fatalln("仅能获取exe、dll、apk版本号,请重新输入程序路径.",聽file.FilePath)
聽聽聽聽}

聽聽聽聽switch聽{
聽聽聽聽case聽file.Debug:
聽聽聽聽聽聽聽聽fmt.Printf("%s聽的版本号为:聽",聽file.FilePath)
聽聽聽聽case聽file.FilePath聽==聽DEFAULT:
聽聽聽聽聽聽聽聽flag.PrintDefaults()
聽聽聽聽聽聽聽聽fmt.Printf("%s聽的版本号为:聽",聽file.FilePath)
聽聽聽聽}

聽聽聽聽fmt.Printf("%s",聽file.Version)
}


本文出自 “CodyGuo” 博客,请务必保留此出处http://codyguo.blog.51cto.com/10440635/1700347


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:codyguo

查看原文:golang 获取exe、dll、apk 版本号

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2026 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传