分享
  1. 首页
  2. 文章

golang 获取exe、dll、apk 版本号

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

通过go获取exe、dll、apk版本号,支持夸平台,可交叉编译。

一点都不爽,修改一个格式还要审核一下,浪费心情。

// 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)
}

版权声明:本文为博主原创文章,未经博主允许不得转载。


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

本文来自:CSDN博客

感谢作者:guoxiao219

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

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

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

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏