golang 擷取exe、dll、apk 版本號碼

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
通過go擷取exe、dll、apk版本號碼,支援誇平台,可交叉編譯。
換了個帳號,審核下。我把另一個帳號的文章都會刪掉。

</pre><pre name="code" class="plain">
// golang 實現讀取exe dll apk 版本號碼package mainimport (    "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)}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.