diff --git a/docs/api/packages/fileutil.md b/docs/api/packages/fileutil.md index 129bbe0..f2af62d 100644 --- a/docs/api/packages/fileutil.md +++ b/docs/api/packages/fileutil.md @@ -52,7 +52,7 @@ import ( - [ReadFile](#ReadFile) - [ChunkRead](#ChunkRead) - [ParallelChunkRead](#ParallelChunkRead) - +- [GetVersion](#Version)
## 文档 @@ -1076,4 +1076,34 @@ func main() { // Jim,21,male // 2 } +``` +### GetExeDllVersion + +

返回exe,dll文件版本号(仅Window平台).

+ +函数签名: + +```go +func GetExeDllVersion(filePath string) (string, error) +``` + +示例:[运行](https://go.dev/play/p/s_Tl7lZoAaY) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/fileutil" +) + +func main() { + v, err := fileutil.GetExeDllVersion(`C:\Program Files\Tencent\WeChat\WeChat.exe`) + if err != nil { + panic(err) + } + fmt.Println(v) + // Output: + // 3.9.10.19 +} ``` \ No newline at end of file diff --git a/docs/api/packages/random.md b/docs/api/packages/random.md index 895f1ba..9c17959 100644 --- a/docs/api/packages/random.md +++ b/docs/api/packages/random.md @@ -40,6 +40,7 @@ import ( - [RandStringSlice](#RandStringSlice) - [RandBool](#RandBool) - [RandBoolSlice](#RandBoolSlice) +- [RandNumLen](#RandNumLen)
@@ -522,4 +523,29 @@ func main() { result := random.RandBoolSlice(2) fmt.Println(result) // [true false] (random) } +``` +### RandNumLen + +

生成指定长度的随机数

+ +函数签名: + +```go +func RandNumLen(len int) int +``` + +实例:[运行](https://go.dev/play/p/o-VSjPjnILI) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/random" +) + +func main() { + i := random.RandNumLen(2) + fmt.Println(i) +} ``` \ No newline at end of file diff --git a/fileutil/file.go b/fileutil/file.go index 585b080..cb72c19 100644 --- a/fileutil/file.go +++ b/fileutil/file.go @@ -14,6 +14,7 @@ import ( "encoding/csv" "errors" "fmt" + "github.com/duke-git/lancet/v2/validator" "io" "io/fs" "net/http" @@ -23,8 +24,6 @@ import ( "sort" "strings" "sync" - - "github.com/duke-git/lancet/v2/validator" ) // FileReader is a reader supporting offset seeking and reading one diff --git a/fileutil/file_windows.go b/fileutil/file_windows.go new file mode 100644 index 0000000..fd41b1a --- /dev/null +++ b/fileutil/file_windows.go @@ -0,0 +1,81 @@ +//go:build windows + +package fileutil + +import ( + "fmt" + "syscall" + "unsafe" +) + +// tagVS_FIXEDFILEINFO 参考结构体https://learn.microsoft.com/zh-cn/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo +type tagVS_FIXEDFILEINFO struct { + Signature uint32 + StructVersion uint32 + FileVersionMS uint32 + FileVersionLS uint32 + ProductVersionMS uint32 + ProductVersionLS uint32 + FileFlagsMask uint32 + FileFlags uint32 + FileOS uint32 + FileType uint32 + FileSubtype uint32 + FileDateMS uint32 + FileDateLS uint32 +} + +// GetExeDllVersion 获取exe或dll文件的版本信息 +func GetExeDllVersion(filePath string) (string, error) { + // 加载系统dll + versionDLL := syscall.NewLazyDLL("version.dll") + getFileVersionInfoSize := versionDLL.NewProc("GetFileVersionInfoSizeW") + getFileVersionInfo := versionDLL.NewProc("GetFileVersionInfoW") + verQueryValue := versionDLL.NewProc("VerQueryValueW") + + // 转换路径为UTF-16 + filePathPtr, err := syscall.UTF16PtrFromString(filePath) + if err != nil { + return "", fmt.Errorf("unable to convert file path to UTF-16: %w", err) + } + + // 获取version信息大小 + size, _, err := getFileVersionInfoSize.Call( + uintptr(unsafe.Pointer(filePathPtr)), + 0, + ) + if size == 0 { + return "", fmt.Errorf("unable to obtain version information size: %v", err) + } + + // 加载version信息 + data := make([]byte, size) + ret, _, err := getFileVersionInfo.Call(uintptr(unsafe.Pointer(filePathPtr)), 0, size, uintptr(unsafe.Pointer(&data[0]))) + if ret == 0 { + return "", fmt.Errorf("unable to obtain version information: %v", err) + } + + // 查询version信息 + var fixedInfo *tagVS_FIXEDFILEINFO + var fixedInfoLen uint32 + u16, err := syscall.UTF16PtrFromString(`\`) + if err != nil { + return "", fmt.Errorf("unable to convert file path to UTF-16: %w", err) + } + ret, _, err = verQueryValue.Call( + uintptr(unsafe.Pointer(&data[0])), + uintptr(unsafe.Pointer(u16)), + uintptr(unsafe.Pointer(&fixedInfo)), + uintptr(unsafe.Pointer(&fixedInfoLen)), + ) + if ret == 0 { + return "", fmt.Errorf("unable to query version information: %v", err) + } + + // 转换结构体 + major := fixedInfo.FileVersionMS >> 16 + minor := fixedInfo.FileVersionMS & 0xFFFF + build := fixedInfo.FileVersionLS >> 16 + revision := fixedInfo.FileVersionLS & 0xFFFF + return fmt.Sprintf("%d.%d.%d.%d", major, minor, build, revision), nil +} diff --git a/fileutil/file_windows_test.go b/fileutil/file_windows_test.go new file mode 100644 index 0000000..d6f7ac4 --- /dev/null +++ b/fileutil/file_windows_test.go @@ -0,0 +1,13 @@ +//go:build windows + +package fileutil + +import "testing" + +func TestGetExeDllVersion(t *testing.T) { + v, err := GetExeDllVersion(`C:\Windows\System32\cmd.exe`) + if err != nil { + t.Error(err) + } + t.Log(v) +} diff --git a/go.mod b/go.mod index e5be56c..cca26aa 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.18 require ( golang.org/x/exp v0.0.0-20221208152030-732eee02a75a + golang.org/x/sys v0.5.0 golang.org/x/text v0.9.0 ) diff --git a/go.sum b/go.sum index 931837d..f1ac8c7 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ golang.org/x/exp v0.0.0-20221208152030-732eee02a75a h1:4iLhBPcpqFmylhnkbY3W0ONLUYYkDAW9xMFLfxgsvCw= golang.org/x/exp v0.0.0-20221208152030-732eee02a75a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= diff --git a/random/random.go b/random/random.go index 5192382..9d7dc5f 100644 --- a/random/random.go +++ b/random/random.go @@ -327,3 +327,12 @@ func UUIdV4() (string, error) { return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil } + +// RandNumLen 生成一个长度为len的随机数 +// Play: https://go.dev/play/p/jpIalcD5rMo +func RandNumLen(len int) int { + m := int(math.Pow10(len) - 1) + i := int(math.Pow10(len - 1)) + ret := rand.Intn(m-i+1) + i + return ret +} diff --git a/random/random_test.go b/random/random_test.go index f7df09d..9f0f5e0 100644 --- a/random/random_test.go +++ b/random/random_test.go @@ -3,6 +3,7 @@ package random import ( "reflect" "regexp" + "strconv" "testing" "github.com/duke-git/lancet/v2/internal" @@ -361,3 +362,9 @@ func TestRandBoolSlice(t *testing.T) { } }) } +func TestRandNumLen(t *testing.T) { + t.Parallel() + randi := RandNumLen(6) + assert := internal.NewAssert(t, "TestRandNumLen") + assert.Equal(6, len(strconv.Itoa(randi))) +}