123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- //go:build windows
- // +build windows
- package comm
- import (
- "context"
- "crypto/md5"
- "crypto/rand"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "net"
- "strings"
- "unsafe"
- "github.com/StackExchange/wmi"
- "golang.org/x/sys/windows"
- )
- func GetPhysicalID() string {
- var ids []string
- mac := getMACAddress()
- if len(mac) < 1 {
- mac = "mac"
- }
- ids = append(ids, mac)
- guid, _ := getMachineGuid()
- if len(guid) < 1 {
- guid = "guid"
- }
- ids = append(ids, guid)
- cpuinfo, err := getCPUInfo()
- cpus := []string{}
- if err == nil {
- for _, c := range cpuinfo {
- cpus = append(cpus, c.VendorID+c.PhysicalID)
- }
- }
- cpu := "cpu"
- if len(cpu) > 0 {
- cpu = strings.Join(cpus, ",")
- }
- ids = append(ids, cpu)
- idsstr := strings.Join(ids, "|")
- return idsstr
- }
- func getMACAddress() string {
- netInterfaces, err := net.Interfaces()
- if err != nil {
- return ""
- }
- for i := 0; i < len(netInterfaces); i++ {
- //fmt.Println(netInterfaces[i])
- if (netInterfaces[i].Flags&net.FlagUp) != 0 && (netInterfaces[i].Flags&net.FlagLoopback) == 0 {
- addrs, _ := netInterfaces[i].Addrs()
- for _, address := range addrs {
- ipnet, ok := address.(*net.IPNet)
- //fmt.Println(ipnet.IP)
- if ok && ipnet.IP.IsGlobalUnicast() {
- // 如果IP是全局单拨地址,则返回MAC地址
- return netInterfaces[i].HardwareAddr.String()
- }
- }
- }
- }
- return ""
- }
- type cpuInfo struct {
- CPU int32 `json:"cpu"`
- VendorID string `json:"vendorId"`
- PhysicalID string `json:"physicalId"`
- }
- type win32_Processor struct {
- Manufacturer string
- ProcessorID *string
- }
- func getCPUInfo() ([]cpuInfo, error) {
- var ret []cpuInfo
- var dst []win32_Processor
- q := wmi.CreateQuery(&dst, "")
- fmt.Println(q)
- if err := wmiQuery(q, &dst); err != nil {
- return ret, err
- }
- var procID string
- for i, l := range dst {
- procID = ""
- if l.ProcessorID != nil {
- procID = *l.ProcessorID
- }
- cpu := cpuInfo{
- CPU: int32(i),
- VendorID: l.Manufacturer,
- PhysicalID: procID,
- }
- ret = append(ret, cpu)
- }
- return ret, nil
- }
- // WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
- func wmiQuery(query string, dst interface{}, connectServerArgs ...interface{}) error {
- ctx := context.Background()
- if _, ok := ctx.Deadline(); !ok {
- ctxTimeout, cancel := context.WithTimeout(ctx, 3000000000) //超时时间3s
- defer cancel()
- ctx = ctxTimeout
- }
- errChan := make(chan error, 1)
- go func() {
- errChan <- wmi.Query(query, dst, connectServerArgs...)
- }()
- select {
- case <-ctx.Done():
- return ctx.Err()
- case err := <-errChan:
- return err
- }
- }
- func getMachineGuid() (string, error) {
- // there has been reports of issues on 32bit using golang.org/x/sys/windows/registry, see https://github.com/shirou/gopsutil/pull/312#issuecomment-277422612
- // for rationale of using windows.RegOpenKeyEx/RegQueryValueEx instead of registry.OpenKey/GetStringValue
- var h windows.Handle
- err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Cryptography`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
- if err != nil {
- return "", err
- }
- defer windows.RegCloseKey(h)
- const windowsRegBufLen = 74 // len(`{`) + len(`abcdefgh-1234-456789012-123345456671` * 2) + len(`}`) // 2 == bytes/UTF16
- const uuidLen = 36
- var regBuf [windowsRegBufLen]uint16
- bufLen := uint32(windowsRegBufLen)
- var valType uint32
- err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`MachineGuid`), nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen)
- if err != nil {
- return "", err
- }
- hostID := windows.UTF16ToString(regBuf[:])
- hostIDLen := len(hostID)
- if hostIDLen != uuidLen {
- return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
- }
- return hostID, nil
- }
- // 生成32位md5字串
- func GetMd5String(s string, upper bool, half bool) string {
- h := md5.New()
- h.Write([]byte(s))
- result := hex.EncodeToString(h.Sum(nil))
- if upper == true {
- result = strings.ToUpper(result)
- }
- if half == true {
- result = result[8:24]
- }
- return result
- }
- // 利用随机数生成Guid字串
- func UniqueId() string {
- b := make([]byte, 48)
- if _, err := rand.Read(b); err != nil {
- return ""
- }
- return GetMd5String(base64.URLEncoding.EncodeToString(b), true, false)
- }
- func GetDeviceHash() string {
- //校验设备
- id := GetPhysicalID()
- if len(id) < 1 {
- return ""
- }
- return GetMd5String(id, true, true)
- }
|