golang獲取exe、dll、apk版本號(hào)-創(chuàng)新互聯(lián)

// golang 實(shí)現(xiàn)讀取exe dll apk 版本號(hào)
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錯(cuò)誤,找不到 MZ.", f.FilePath)
    }

    peOffset := f.unpack([]byte{buffer[60], buffer[61], buffer[62], buffer[63]})
    if peOffset < PEOFFSET {
        log.Fatalln("peOffset 讀取錯(cuò)誤.", f.FilePath)
    }

    // 讀取從文件開(kāi)頭移位到 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錯(cuò)誤,找不到 PE.", f.FilePath)
    }

    machine := f.unpack([]byte{buffer[4], buffer[5]})
    if machine != MACHINE {
        log.Fatalln("machine 讀取錯(cuò)誤.", f.FilePath)
    }

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

    // 讀取從當(dāng)前位置移位到 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錯(cuò)誤,找不到 .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]})

    // 讀取從文件開(kāi)頭位置移位到 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錯(cuò)誤,找不到 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版本號(hào),請(qǐng)重新輸入程序路徑.", file.FilePath)
    }

    switch {
    case file.Debug:
        fmt.Printf("%s 的版本號(hào)為: ", file.FilePath)
    case file.FilePath == DEFAULT:
        flag.PrintDefaults()
        fmt.Printf("%s 的版本號(hào)為: ", file.FilePath)
    }

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

成都創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來(lái)公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過(guò)去的十載時(shí)間我們累計(jì)服務(wù)了上千家以及全國(guó)政企客戶,如成都主動(dòng)防護(hù)網(wǎng)等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過(guò)硬的技術(shù)實(shí)力獲得客戶的一致贊賞。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

文章題目:golang獲取exe、dll、apk版本號(hào)-創(chuàng)新互聯(lián)
文章網(wǎng)址:http://muchs.cn/article22/dgejjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航企業(yè)建站、小程序開(kāi)發(fā)、移動(dòng)網(wǎng)站建設(shè)、定制網(wǎng)站、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)