go 獲取windows系統(tǒng)版本(windows api)

獲取windows系統(tǒng)版本

項目地址

emm .... 我放在這里了

https://github.com/0xAAFF/WindowsVersion

具體判斷函數(shù)

OSVersion() 判斷操作系統(tǒng)小節(jié),判斷邏輯都是一樣的 ,可以直接跳過去看
這個函數(shù)判斷了從 win nt 4 - win 11 之間的所有操作系統(tǒng)
但是沒有寫是home版本或者專業(yè)版本的判斷.如果您有興趣,可以自己添加

原理

使用windows API得到windwos的主版本號,次版本號,編譯版本號,這樣大概區(qū)分出windows的版本
然后根據(jù)各個版本號下的具體的屬性再次細(xì)分得到是否為Server或者WorkStation

Windows8.1以下版本的API:
GetVersionExW()

Windwos8.1及以上的版本API:
RtlGetNtVersionNumbers() 和 GetVersionExW() 配合使用
注:為什么這樣使用:
因為GetVersionExW()在windows8.1及以上獲取的主版本號,次版本號和編譯版本號都是一樣的 :6.2.9200
但是獲取的其他信息是對的.
所以,使用RtlGetNtVersionNumbers()這個API會得到正確的版本號.

當(dāng)然,中間為了獲取winxp64的,使用了GetNativeSystemInfo這個API來獲取cpu的架構(gòu):ARCH=386可以執(zhí)行 amd64獲取的數(shù)據(jù)不對.請考慮使用

支持版本

/*
    Windows NT 4
    Windows 95
    Windows 98
    Windows Me
    Windows 2000
    Windows XP
    Windows XP 64
    Windows Server 2003
    Windows Server 2003 R2
    Windwos Vista
    Windows Server 2008
    Windwos 7
    Windows Server 2008 R2
    Windwos 8
    Windows Server 2012
    Windows 8.1
    Windows Server 2012 R2
    Windows 10
    Windows Server 2016
    Windows Server 2019
    Windows 11
    Windows 11 +
*/

具體實現(xiàn)

1 golang使用API需要用到一些數(shù)據(jù)類型,這里我的習(xí)慣是提取出來,這樣方便使用.當(dāng)然.每個人的習(xí)慣不同.
我定義了以下數(shù)據(jù)類型,不一定精確.如果有不正確的地方,請指正:

// go_type.go
package winapi_type

import (
    "syscall"
    "unicode/utf16"
    "unsafe"
)

type HANDLE uintptr
type HMODULE uintptr
type LPVOID uintptr
type WORD uint16
type DWORD uint32
type DWORD_PTR uintptr // 不確定
type ULong uint32
type HRESULT uint32 // blog.csdn.net/ixsea/article/details/7272909
type LPBYTE *byte
type LPDWORD *uint32
type LPWSTR *uint16
type LMSTR *uint16

// type WCHAR = wchar_t
// type wchar_t = uint16

// UTF16toString converts a pointer to a UTF16 string into a Go string.
func UTF16toString(p *uint16) string {
    return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:])
}

func StrPtr(s string) uintptr {
    systemNameUTF16String, err := syscall.UTF16PtrFromString(s)
    if err == nil {
        // 這里轉(zhuǎn)換的時候出錯,則不繼續(xù)執(zhí)行 OR 賦值用本地的
        tmp := utf16.Encode([]rune("\x00"))
        systemNameUTF16String = &tmp[0]
    }

    return uintptr(unsafe.Pointer(systemNameUTF16String))
}

func CharsPtr(s string) uintptr {
    bPtr, err := syscall.BytePtrFromString(s)
    if err != nil {
        return uintptr(0) // 這么寫肯定不太對 @TODO
    }
    return uintptr(unsafe.Pointer(bPtr))
}

func IntPtr(n int) uintptr {
    return uintptr(n)
}

2 常用操作系統(tǒng)量

// winnt.go
package version

// 判斷操作系統(tǒng)的量
var (
    PROCESSOR_ARCHITECTURE_INTEL          = 0
    PROCESSOR_ARCHITECTURE_MIPS           = 1
    PROCESSOR_ARCHITECTURE_ALPHA          = 2
    PROCESSOR_ARCHITECTURE_PPC            = 3
    PROCESSOR_ARCHITECTURE_SHX            = 4
    PROCESSOR_ARCHITECTURE_ARM            = 5
    PROCESSOR_ARCHITECTURE_IA64           = 6
    PROCESSOR_ARCHITECTURE_ALPHA64        = 7
    PROCESSOR_ARCHITECTURE_MSIL           = 8
    PROCESSOR_ARCHITECTURE_AMD64          = 9
    PROCESSOR_ARCHITECTURE_IA32_ON_WIN64  = 10
    PROCESSOR_ARCHITECTURE_NEUTRAL        = 11
    PROCESSOR_ARCHITECTURE_ARM64          = 12
    PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 = 13
    PROCESSOR_ARCHITECTURE_IA32_ON_ARM64  = 14

    PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF

    PRODUCT_UNDEFINED = 0x00000000

    PRODUCT_ULTIMATE                     = 0x00000001
    PRODUCT_HOME_BASIC                   = 0x00000002
    PRODUCT_HOME_PREMIUM                 = 0x00000003
    PRODUCT_ENTERPRISE                   = 0x00000004
    PRODUCT_HOME_BASIC_N                 = 0x00000005
    PRODUCT_BUSINESS                     = 0x00000006
    PRODUCT_STANDARD_SERVER              = 0x00000007
    PRODUCT_DATACENTER_SERVER            = 0x00000008
    PRODUCT_SMALLBUSINESS_SERVER         = 0x00000009
    PRODUCT_ENTERPRISE_SERVER            = 0x0000000A
    PRODUCT_STARTER                      = 0x0000000B
    PRODUCT_DATACENTER_SERVER_CORE       = 0x0000000C
    PRODUCT_STANDARD_SERVER_CORE         = 0x0000000D
    PRODUCT_ENTERPRISE_SERVER_CORE       = 0x0000000E
    PRODUCT_ENTERPRISE_SERVER_IA64       = 0x0000000F
    PRODUCT_BUSINESS_N                   = 0x00000010
    PRODUCT_WEB_SERVER                   = 0x00000011
    PRODUCT_CLUSTER_SERVER               = 0x00000012
    PRODUCT_HOME_SERVER                  = 0x00000013
    PRODUCT_STORAGE_EXPRESS_SERVER       = 0x00000014
    PRODUCT_STORAGE_STANDARD_SERVER      = 0x00000015
    PRODUCT_STORAGE_WORKGROUP_SERVER     = 0x00000016
    PRODUCT_STORAGE_ENTERPRISE_SERVER    = 0x00000017
    PRODUCT_SERVER_FOR_SMALLBUSINESS     = 0x00000018
    PRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019

    PRODUCT_UNLICENSED = uint64(0xABCDABCD)

    VER_PLATFORM_WIN32s        = 0
    VER_PLATFORM_WIN32_WINDOWS = 1
    VER_PLATFORM_WIN32_NT      = 2

    VER_NT_WORKSTATION       = 0x0000001
    VER_NT_DOMAIN_CONTROLLER = 0x0000002
    VER_NT_SERVER            = 0x0000003

    //#if(_WIN32_WINNT >= 0x0501)
    SM_TABLETPC    = 86
    SM_MEDIACENTER = 87
    SM_STARTER     = 88
    SM_SERVERR2    = 89
    //#endif /* _WIN32_WINNT >= 0x0501 */

)


3 GetVersionExW 的API調(diào)用及使用的數(shù)據(jù)結(jié)構(gòu)

// under_8.1version_windows.go

package version

import (
    "syscall"
    "unsafe"

    . "wxw.test.x/system/windows/winapi_type"
)

//
// GetVersionExA 函數(shù) (sysinfoapi.h)
// Kernel32.lib
// 最低支持 Windows 2000 Professional/Server [desktop apps | UWP apps]
// docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa

// #region GetVersionExW 函數(shù) (sysinfoapi.h)
// docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexw
/*
Kernel32.dll
GetVersionExW function (sysinfoapi.h)
NOT_BUILD_WINDOWS_DEPRECATE BOOL GetVersionExW(
  [in, out] LPOSVERSIONINFOW lpVersionInformation
);
*/
func GetVersionExW() (OSVersionInfoExA, error) {

    //csdVer := make([]byte, 128)
    var osVersionInfoExA OSVersionInfoExA
    // osVersionInfoExA := OSVersionInfoExA{
    //  //CSDVersion: csdVer, //uintptr(unsafe.Pointer(&csdVer[0])), //StrPtr(csdVer), //csdVer[:128], //uintptr(unsafe.Pointer(&csdVer[0])),
    // }
    osVersionInfoExA.OSVersionInfoSize = DWORD(unsafe.Sizeof(osVersionInfoExA))

    kernel32 := syscall.NewLazyDLL("Kernel32.dll")
    procGetVersionExW := kernel32.NewProc("GetVersionExA")
    _, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(&osVersionInfoExA)))
    //v, vv, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(&osVersionInfoExA)))
    // fmt.Println(v)
    // fmt.Println(vv)
    // fmt.Println(err)
    if err != nil && err.Error() == "The operation completed successfully." {
        err = nil
    }

    // fmt.Println("-----------------GetVersionExW-----------------")
    // fmt.Printf("%#v \n", osVersionInfoExA)
    // fmt.Println("主版本        :", osVersionInfoExA.MajorVersion)
    // fmt.Println("次版本        :", osVersionInfoExA.MinorVersion)
    // fmt.Println("編譯版本      :", osVersionInfoExA.BuildNumber)
    // fmt.Println("操作系統(tǒng)平臺   :", osVersionInfoExA.PlatformId)
    // fmt.Println("SP(主)       :", osVersionInfoExA.MajorVersion)
    // fmt.Println("SP(次)       :", osVersionInfoExA.ServicePackMinor)

    return osVersionInfoExA, err
}

// # endregion

// #region OSVERSIONINFOEXA structure
// docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexa
/*
typedef struct _OSVERSIONINFOEXA {
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  CHAR  szCSDVersion[128];
  WORD  wServicePackMajor;
  WORD  wServicePackMinor;
  WORD  wSuiteMask;
  BYTE  wProductType;
  BYTE  wReserved;
} OSVERSIONINFOEXA, *POSVERSIONINFOEXA, *LPOSVERSIONINFOEXA;
*/

type OSVersionInfoExA struct {
    OSVersionInfoSize DWORD     // 結(jié)構(gòu)體大小, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
    MajorVersion      DWORD     // 主版本號
    MinorVersion      DWORD     // 次版本號
    BuildNumber       DWORD     // 編譯版本號
    PlatformId        DWORD     // 系統(tǒng)支持的平臺
    CSDVersion        [128]byte // 系統(tǒng)補(bǔ)丁包的名稱  CSDVersion[128]// 這個128是必須的 不然就會出現(xiàn)"The data area passed to a system call is too small."
    ServicePackMajor  WORD      // 系統(tǒng)補(bǔ)丁包的主版本
    ServicePackMinor  WORD      // 系統(tǒng)補(bǔ)丁包的次版本
    SuiteMask         WORD      // 標(biāo)識系統(tǒng)上的程序組
    ProductType       byte      // 標(biāo)識系統(tǒng)類型
    Reserved          byte      // 保留,未使用
} // 這個結(jié)構(gòu)在Windows 2000后出現(xiàn),老版本的OSVERSIONINFO結(jié)構(gòu)沒有wServicePackMajor、wServicePackMinor、wSuiteMask、wProductType和wReserved這幾個成員。

// #endregion

// #region  OSVERSIONINFOA
// OSVERSIONINFOA structure (winnt.h)
// docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoa
/*
typedef struct _OSVERSIONINFOA {
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  CHAR  szCSDVersion[128];
} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA;
*/
type OSVersionInfoA struct {
    OSVersionInfoSize DWORD     // 結(jié)構(gòu)體大小, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
    MajorVersion      DWORD     // 主版本號
    MinorVersion      DWORD     // 次版本號
    BuildNumber       DWORD     // 編譯版本號
    PlatformId        DWORD     // 系統(tǒng)支持的平臺
    CSDVersion        [128]byte // 系統(tǒng)補(bǔ)丁包的名稱  CSDVersion[128]
}

// #endregion

// Version Helper functions
// Windwos 系統(tǒng)版本助手(微軟官方推薦此函數(shù)列表)
// docs.microsoft.com/en-us/windows/win32/sysinfo/version-helper-apis
// 但是我沒用 - -

// IsWow64Process函數(shù)
// GetNativeSystemInfo function (sysinfoapi.h)
// docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo


4 GetNativeSystemInfo() 的API的調(diào)用

go env -w GOARCH=386 時可以調(diào)用成功,但是GOARCH=amd64時調(diào)用數(shù)據(jù)是不對的,如果您發(fā)現(xiàn)了這個問題的解決方式,請聯(lián)系我

// systeminfo_windows.go
package version

import (
    "syscall"
    "unsafe"

    . "x.test.x/system/windows/winapi_type" // 這里我手動修改了下,請在您的項目中注意引用
)

// api dll
// Kernel32.dll
// Kernel32 := syscall.NewLazyDLL("kernel32.dll")

// 判斷windwos操作系統(tǒng)是32位還是64位
// GetNativeSystemInfo function (sysinfoapi.h)
// docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo

/*
void GetNativeSystemInfo(
  [out] LPSYSTEM_INFO lpSystemInfo
);
*/
func GetNativeSystemInfo() (*SystemInfo, error) {
    kernel32 := syscall.NewLazyDLL("kernel32.dll")
    procGetNativeSystemInfo := kernel32.NewProc("GetNativeSystemInfo")
    systemInformation := &SystemInfo{}
    _, _, err := procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(systemInformation)))
    if err != nil && err.Error() == "The operation completed successfully." {
        err = nil
    }

    // fmt.Println(err)
    // fmt.Printf("%#v \n", systemInformation)
    // fmt.Printf("%#v \n", systemInformation.DummyUnionName)

    // dummyStructName := (*DummyStructName)(unsafe.Pointer(&systemInformation.DummyUnionName))
    // fmt.Printf("dummyStructName : %#v \n", dummyStructName)
    // fmt.Println("架構(gòu)          : ", dummyStructName.Architecture())
    // fmt.Println("處理器數(shù)量    : ", systemInformation.NumberOfProcessors)
    // fmt.Println("處理器類型    : ", systemInformation.ProcessorType)
    return systemInformation, err
}

// 參數(shù)
// SYSTEM_INFO structure (sysinfoapi.h)
// docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
/*

// DUMMYUNIONNAME
/*
struct {
    WORD wProcessorArchitecture;
    WORD wReserved;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
*/

// DummyStructName 虛擬結(jié)構(gòu)名
type DummyStructName struct {
    /*
        ProcessorArchitecture 值和說明
        --------------------------------|--------------------------------|
        Value                           |   Meaning
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_AMD64    |   x64 (AMD or Intel)
        9                               |
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_ARM      |   ARM
        5                               |
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_ARM64    |   ARM64
        12                              |
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_IA64     |   Intel Itanium-based
        6                               |
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_INTEL    |   x86
        0                               |
        --------------------------------|--------------------------------|
        PROCESSOR_ARCHITECTURE_UNKNOWN  |   未知架構(gòu)
        0xffff                          |
        --------------------------------|--------------------------------|
    */

    ProcessorArchitecture WORD // 已安裝操作系統(tǒng)的處理器體系結(jié)構(gòu)。
    Reserved              WORD
}

// OemId
type OemId struct {
    OemId DWORD
}

/*

    When `go env -w GOARCH=amd64`: NumberOfProcessors:0x10000,ProcessorType:0x7e050006,(Error.不是太清楚這個什么原因):
    &version.SystemInfo{DummyUnionName:0x100000000009, PageSize:0x10000, MinimumApplicationAddress:0x7ffffffeffff, MaximumApplicationAddress:0xff, ActiveProcessorMask:0x21d800000008, NumberOfProcessors:0x10000, ProcessorType:0x7e050006, AllocationGranularity:0x0, ProcessorLevel:0x0, ProcessorRevision:0x0}


    When `go env -w GOARCH=386`  : NumberOfProcessors:0x8, ProcessorType:0x21d8 (correct 這個才是正確的):
    &version.SystemInfo{DummyUnionName:0x9, PageSize:0x1000, MinimumApplicationAddress:0x10000, MaximumApplicationAddress:0xfffeffff, ActiveProcessorMask:0xff, NumberOfProcessors:0x8, ProcessorType:0x21d8, AllocationGranularity:0x10000, ProcessorLevel:0x6, ProcessorRevision:0x7e05}

*/
/*

// 參數(shù)類型
typedef struct _SYSTEM_INFO {
    union {
      DWORD dwOemId;
      struct {
        WORD wProcessorArchitecture;
        WORD wReserved;
      } DUMMYSTRUCTNAME;
    } DUMMYUNIONNAME;
    DWORD     dwPageSize;
    LPVOID    lpMinimumApplicationAddress;
    LPVOID    lpMaximumApplicationAddress;
    DWORD_PTR dwActiveProcessorMask;
    DWORD     dwNumberOfProcessors;
    DWORD     dwProcessorType;
    DWORD     dwAllocationGranularity;
    WORD      wProcessorLevel;
    WORD      wProcessorRevision;
  } SYSTEM_INFO, *LPSYSTEM_INFO;
*/
type SystemInfo struct {
    DummyUnionName            uintptr   //DummyUnionName Or OemId ,one of this Use Same Memory.兩個結(jié)構(gòu)使用同一塊內(nèi)存
    PageSize                  DWORD     // 虛擬內(nèi)存頁的大小
    MinimumApplicationAddress LPVOID    // 應(yīng)用程序和動態(tài)鏈接庫(DLL)可訪問的最低內(nèi)存地址
    MaximumApplicationAddress LPVOID    // 應(yīng)用程序和動態(tài)鏈接庫(DLL)可訪問的最高內(nèi)存地址
    ActiveProcessorMask       DWORD_PTR // 表示配置到系統(tǒng)中的處理器集的掩碼
    NumberOfProcessors        DWORD     // 處理器數(shù)量
    ProcessorType             DWORD     // 處理器類型
    AllocationGranularity     DWORD     // 虛擬內(nèi)存的起始地址
    ProcessorLevel            WORD      // 依賴于體系結(jié)構(gòu)的處理器級別。它只能用于顯示目的。要確定處理器的功能集,請使用IsProcessorFeaturePresent函數(shù)。
    ProcessorRevision         WORD      // 依賴于體系結(jié)構(gòu)的處理器版本
}

// 當(dāng)前系統(tǒng)中的中央處理器的架構(gòu)
func (d *DummyStructName) Architecture() string {
    switch d.ProcessorArchitecture {
    case 0:
        {
            return "x86" // 32位
        }
    case 5:
        {
            return "ARM" // 32位
        }
    case 6:
        {
            return "Itanium" //Intel  Itanium-based // Intel 奔騰架構(gòu)  32位處理器
        }
    case 9:
        {
            return "x64" //  (AMD or Intel)  64位處理器
        }
    case 12:
        {
            return "ARM64" // 64位處理器
        }
    case 0xffff:
        {
            return "Unknow" // 未知
        }
    default:
        {
            return "Unknow" // 未知
        }
    }
}

// 是否為64位操作系統(tǒng)
func (d *DummyStructName) IsWin64() bool {
    return d.ProcessorArchitecture == WORD(PROCESSOR_ARCHITECTURE_AMD64) || d.ProcessorArchitecture == WORD(PROCESSOR_ARCHITECTURE_IA64)
}

// 處理器類型
// PROCESSOR_INTEL_386      (386)
// PROCESSOR_INTEL_486      (486)
// PROCESSOR_INTEL_PENTIUM  (586)
// PROCESSOR_INTEL_IA64     (2200)
// PROCESSOR_AMD_X8664      (8664)
// PROCESSOR_ARM            (Reserved)
func (s *SystemInfo) GetProcessorType() string {
    switch s.ProcessorType {
    case 386: // 0x0182
        {
            return "386"
        }
    case 486: // 0x01E6
        {
            return "486"
        }
    case 586: // 0x024A
        {
            return "Pentium" // "奔騰"
        }
    case 2200: // 0x0898
        {
            return "Itanium" //"安騰"
        }
    case 8664: // 0x21D8
        {
            return "X8664" //
        }
        // case xxx{ return "ARM" }
    default:
        {
            return "Unknow"
        }
    }
}

func (s *SystemInfo) GetDummyStructName() *DummyStructName {
    dummyStructName := (*DummyStructName)(unsafe.Pointer(&s.DummyUnionName))
    // fmt.Printf("dummyStructName : %#v \n", dummyStructName)
    // fmt.Println("架構(gòu)          : ", dummyStructName.Architecture())
    // fmt.Println("處理器數(shù)量    : ", s.NumberOfProcessors)
    // fmt.Println("處理器類型    : ", s.ProcessorType)
    return dummyStructName
}


5 GetSystemMetrics()的API的調(diào)用


// system_metrics_windows.go

package version

import (
    "syscall"
)

// GetSystemMetrics function (winuser.h)
// User32.dll
// docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics
/*
int GetSystemMetrics(
  [in] int nIndex
);
*/

func GetSystemMetrics(index int) (int, error) {
    user32 := syscall.NewLazyDLL("User32.dll")
    procGetSystemMetrics := user32.NewProc("GetSystemMetrics")
    v, _, err := procGetSystemMetrics.Call(uintptr(index))
    // fmt.Printf("%#v \n", v)
    // fmt.Println(err)
    return int(v), err

}


6 OSVersion() 判斷操作系統(tǒng)

// osversion_windows.go

package version

import (
    "syscall"
    "unsafe"
)

/*
    Windows NT 4
    Windows 95
    Windows 98
    Windows Me
    Windows 2000
    Windows XP
    Windows XP 64
    Windows Server 2003
    Windows Server 2003 R2
    Windwos Vista
    Windows Server 2008
    Windwos 7
    Windows Server 2008 R2
    Windwos 8
    Windows Server 2012
    Windows 8.1
    Windows Server 2012 R2
    Windows 10
    Windows Server 2016
    Windows Server 2019
    Windows 11
    Windows 11 +
*/
func OSVersion() (string, error) {
    // 以下代碼獲取windows8.1及以上的操作系統(tǒng)
    majorVersion, minorVersion, buildNumber := RtlGetNtVersionNumbers()
    // fmt.Printf("majorVersion:%d ,minorVersion:%d ,buildNumber:%d \n", majorVersion, minorVersion, buildNumber)

    o, err := GetVersionExW()
    if err != nil {
        // fmt.Println("GetVersionExW : ", err)
        return "", err
    }

    /*
        Windows 8.1
        Windows 10
        Windows Server 2016
        Windows Server 2019
        Windows 11
        Windows 11 +
    */
    // GetVersionExW : win8.1+ :> 6.2.9200 ()
    if majorVersion > 6 || (majorVersion == 6 && minorVersion >= 3) { // win8plus

        if majorVersion == 6 && minorVersion >= 3 {
            // Win8.1       : 6.3.9600
            // Windows Server 2012
            if o.ProductType == byte(VER_NT_WORKSTATION) {
                return "Windows 8.1", nil
            } else {
                // fmt.Println("o.ProductType :", o.ProductType)
                return "Windows Server 2012 R2", nil
            }
        } else if majorVersion == 10 && minorVersion == 0 {
            // Win 10       :10.0.19042
            // WinSer 2019  :10.0.17763
            // Win 11       :10.0.22000
            if o.ProductType == byte(VER_NT_WORKSTATION) {
                if buildNumber >= 22000 {
                    return "Windows 11", nil
                } else { // if buildNumber >= 18363 {
                    //  18363 : Win10 專業(yè)版
                    //  19041 : win10 家庭中文版
                    //  19042 : win10 家庭中文版,教育版
                    //  19043 : win10 專業(yè)版
                    return "Windows 10", nil
                }
            } else {
                if buildNumber >= 17763 {
                    return "Windows Server 2019", nil
                } else if buildNumber >= 14393 {
                    return "Windows Server 2016", nil
                }
            }
        } else {
            return "Windows 11 +", nil
        }
    }

    // 以下代碼獲取windows 8.1一下的系統(tǒng)版本
    /*
        Windows NT 4
        Windows 95
        Windows 98
        Windows Me
        Windows 2000
        Windows XP
        Windows XP 64
        Windows Server 2003
        Windows Server 2003 R2
        Windwos Vista
        Windows Server 2008
        Windwos 7
        Windows Server 2008 R2
        Windwos 8
        Windows Server 2012
    */

    s, err := GetNativeSystemInfo()
    if err != nil {
        return "", nil
    }
    u := s.GetDummyStructName()
    switch o.MajorVersion {
    case 4:
        {
            switch o.MinorVersion {
            case 0:
                {
                    if int(o.PlatformId) == VER_PLATFORM_WIN32_NT {
                        return "Windows NT 4", nil
                    } else if int(o.PlatformId) == VER_PLATFORM_WIN32_WINDOWS {
                        return "Windows 95", nil
                    }
                }
            case 10:
                {
                    return "Windows 98", nil
                }
            case 90:
                {
                    return "Windows Me", nil
                }
            }
        }
    case 5:
        {
            switch o.MinorVersion {
            case 0:
                {
                    return "Windows 2000", nil
                }
            case 1:
                {
                    return "Windows XP", nil
                }
            case 2:
                {
                    r2, err := GetSystemMetrics(SM_SERVERR2)
                    if err != nil {
                        return "", err
                    }

                    if o.ProductType == byte(VER_NT_WORKSTATION) && u.IsWin64() {
                        return "Windows XP 64", nil
                    } else if r2 == 0 {
                        return "Windows Server 2003", nil
                    } else if r2 != 0 {
                        return "Windows Server 2003 R2", nil
                    }
                }

            }
        }
    case 6:
        {
            switch o.MinorVersion {
            case 0:
                {
                    if o.ProductType == byte(VER_NT_WORKSTATION) {
                        return "Windwos Vista", nil
                    } else {
                        return "Windows Server 2008", nil
                    }
                }
            case 1:
                {
                    if o.ProductType == byte(VER_NT_WORKSTATION) {
                        return "Windwos 7", nil
                    } else {
                        return "Windows Server 2008 R2", nil
                    }
                }
            case 2:
                {
                    if o.ProductType == byte(VER_NT_WORKSTATION) {
                        return "Windwos 8", nil
                    } else {
                        return "Windows Server 2012", nil
                    }
                }
            }
        }
    }
    return "windows", nil
}

// Dll: ntdll.dll
// RtlGetNtVersionNumbers
// 獲取系統(tǒng)的版本號
/*

   HINSTANCE hinst = LoadLibrary("ntdll.dll");
   DWORD dwMajor,dwMinor,dwBuildNumber;
   NTPROC proc = (NTPROC)GetProcAddress(hinst,"RtlGetNtVersionNumbers");
   proc(&dwMajor,&dwMinor,&dwBuildNumber);
   dwBuildNumber&=0xffff;
*/
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
    //var majorVersion, minorVersion, buildNumber uint32
    ntdll := syscall.NewLazyDLL("ntdll.dll")
    procRtlGetNtVersionNumbers := ntdll.NewProc("RtlGetNtVersionNumbers")
    //v, vv, err := procRtlGetNtVersionNumbers.Call(
    procRtlGetNtVersionNumbers.Call(
        uintptr(unsafe.Pointer(&majorVersion)),
        uintptr(unsafe.Pointer(&minorVersion)),
        uintptr(unsafe.Pointer(&buildNumber)),
    )
    // fmt.Printf("%#v \n", v)
    // fmt.Printf("%#v \n", vv)
    // fmt.Printf("%#v \n", err)
    // fmt.Println("開發(fā)版本:", buildNumber)
    buildNumber &= 0xffff

    // fmt.Println("-----------------RtlGetNtVersionNumbers-----------------")
    // fmt.Println("主版本號:", majorVersion)
    // fmt.Println("次版本號:", minorVersion)
    // fmt.Println("開發(fā)版本:", buildNumber)

    return

}


結(jié)束

以上代碼,如果有疑問或者代碼出現(xiàn)失誤,請您及時聯(lián)系我修改

簡略不精準(zhǔn)的代碼 建議參考,不要使用:

下面的代碼原理很簡單,就是打開cmd,獲取windows的cmd的[x.x.xxxx]的版本號截取下來,然后做匹配.這樣雖然也行但是無法區(qū)分是否為服務(wù)器:



// OSVersion 獲取windows版本號
func OSVersion() (string, error) {
    // www.lifewire.com/what-version-of-windows-do-i-have-2624927 And bing.com search Images
    versionNumbers := map[string]string{
        `5.0`:            "Win 2000",                                     // Win2000    Microsoft Windows 2000 [Version 5.00.2195]
        `5.1`:            "Win XP",                                       // WinXP 32   Microsoft Windows XP [Version 5.1.2600]     Windows XP is the name given to Windows version 5.1.
        `5.2`:            "Win XP_64/Win Server 2003/Win Server 2003 R2", // WinXP 64   Microsoft Windows XP [Version 5.2]          Windows version 5.2.
        `6.0`:            "Win Vista/Win Server 2008",                    // Win Vista  Microsoft Windows [Version 6.0.6000]        Windows Vista is the name given to Windows version 6.0.
        `6.1`:            "Win 7/Win Server 2008 R2",                     // Win7       Microsoft Windows [Version 6.1.7601]        Windows 7     is the name given to Windows version 6.1.
        `6.2`:            "Win 8/Win Server 2012",                        // Win8       Microsoft Windows [Version 6.2.9200]        Windows 8     is the name given to Windows version 6.2.
        `6.3`:            "Win 8.1/Win Server 2012 R2/Win Phone 8.1",     // Win8.1     Microsoft Windows [Version 6.3.9600]        Windows 8.1   is the name given to Windows version 6.3.
        `6.4`:            "Win 10(技術(shù)預(yù)覽版)",                                // Win8.1     Microsoft Windows [Version 6.3.9600]        Windows 8.1   is the name given to Windows version 6.3.
        `10.0.22000.282`: "Win 11",                                       // Win 11 當(dāng)前
        `10.0`:           "Win 10/Win 11",                                // Win10      Microsoft Windows [Version 10.0.18363.1316] Windows 10    is the name given to Windows version 10.0 and is the latest version of Windows.
    }
    //Microsoft Windows [版本 6.1.7601]           Win7
    //Microsoft Windows [版本 10.0.18363.1316]    Win 10
    //Microsoft Windows [版本 10.0.17763.1935]    Win Server 2019

    cmd := exec.Command("cmd.exe")
    out, _ := cmd.StdoutPipe()
    buffer := bytes.NewBuffer(make([]byte, 0))
    cmd.Start()
    buffer.ReadFrom(out)
    cmdText, err := buffer.ReadString(']')
    cmd.Wait()

    if err != nil {
        return "", err
    }

    point := strings.Index(cmdText, "[")
    if point < 0 {
        return "", fmt.Errorf("cmd text error:[no '['] =>%s", cmdText)
    }
    cmdText = cmdText[point:]
    point = strings.Index(cmdText, " ")
    if point < 0 {
        return "", fmt.Errorf("cmd text error:[no '['] =>%s", cmdText)
    }
    cmdText = cmdText[point+1 : len(cmdText)-1]
    for key, _ := range versionNumbers {
        if strings.HasPrefix(cmdText, key) {
            return versionNumbers[key], nil
        }
    }
    return "", fmt.Errorf("can not support this windows version")
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容