go 获取windows系统版本(windows api)

获取windows系统版本

项目地址

emm .... 我放在这里了

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

具体判断函数

OSVersion() 判断操作系统小节,判断逻辑都是一样的 ,可以直接跳过去看
这个函数判断了从 win nt 4 - win 11 之间的所有操作系统
但是没有写是home版本或者专业版本的判断.如果您有兴趣,可以自己添加

原理

使用windows API得到windwos的主版本号,次版本号,编译版本号,这样大概区分出windows的版本
然后根据各个版本号下的具体的属性再次细分得到是否为Server或者WorkStation

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

Windwos8.1及以上的版本API:
RtlGetNtVersionNumbers() 和 GetVersionExW() 配合使用
注:为什么这样使用:
因为GetVersionExW()在windows8.1及以上获取的主版本号,次版本号和编译版本号都是一样的 :6.2.9200
但是获取的其他信息是对的.
所以,使用RtlGetNtVersionNumbers()这个API会得到正确的版本号.

当然,中间为了获取winxp64的,使用了GetNativeSystemInfo这个API来获取cpu的架构:ARCH=386可以执行 amd64获取的数据不对.请考虑使用

支持版本

/*
    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 +
*/

具体实现

1 golang使用API需要用到一些数据类型,这里我的习惯是提取出来,这样方便使用.当然.每个人的习惯不同.
我定义了以下数据类型,不一定精确.如果有不正确的地方,请指正:

// 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 {
        // 这里转换的时候出错,则不继续执行 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 常用操作系统量

// winnt.go
package version

// 判断操作系统的量
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调用及使用的数据结构

// under_8.1version_windows.go

package version

import (
    "syscall"
    "unsafe"

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

//
// GetVersionExA 函数 (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 函数 (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("操作系统平台   :", 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     // 结构体大小, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
    MajorVersion      DWORD     // 主版本号
    MinorVersion      DWORD     // 次版本号
    BuildNumber       DWORD     // 编译版本号
    PlatformId        DWORD     // 系统支持的平台
    CSDVersion        [128]byte // 系统补丁包的名称  CSDVersion[128]// 这个128是必须的 不然就会出现"The data area passed to a system call is too small."
    ServicePackMajor  WORD      // 系统补丁包的主版本
    ServicePackMinor  WORD      // 系统补丁包的次版本
    SuiteMask         WORD      // 标识系统上的程序组
    ProductType       byte      // 标识系统类型
    Reserved          byte      // 保留,未使用
} // 这个结构在Windows 2000后出现,老版本的OSVERSIONINFO结构没有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     // 结构体大小, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
    MajorVersion      DWORD     // 主版本号
    MinorVersion      DWORD     // 次版本号
    BuildNumber       DWORD     // 编译版本号
    PlatformId        DWORD     // 系统支持的平台
    CSDVersion        [128]byte // 系统补丁包的名称  CSDVersion[128]
}

// #endregion

// Version Helper functions
// Windwos 系统版本助手(微软官方推荐此函数列表)
// docs.microsoft.com/en-us/windows/win32/sysinfo/version-helper-apis
// 但是我没用 - -

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


4 GetNativeSystemInfo() 的API的调用

go env -w GOARCH=386 时可以调用成功,但是GOARCH=amd64时调用数据是不对的,如果您发现了这个问题的解决方式,请联系我

// 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操作系统是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("架构          : ", dummyStructName.Architecture())
    // fmt.Println("处理器数量    : ", systemInformation.NumberOfProcessors)
    // fmt.Println("处理器类型    : ", systemInformation.ProcessorType)
    return systemInformation, err
}

// 参数
// 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 虚拟结构名
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  |   未知架构
        0xffff                          |
        --------------------------------|--------------------------------|
    */

    ProcessorArchitecture WORD // 已安装操作系统的处理器体系结构。
    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}

*/
/*

// 参数类型
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.两个结构使用同一块内存
    PageSize                  DWORD     // 虚拟内存页的大小
    MinimumApplicationAddress LPVOID    // 应用程序和动态链接库(DLL)可访问的最低内存地址
    MaximumApplicationAddress LPVOID    // 应用程序和动态链接库(DLL)可访问的最高内存地址
    ActiveProcessorMask       DWORD_PTR // 表示配置到系统中的处理器集的掩码
    NumberOfProcessors        DWORD     // 处理器数量
    ProcessorType             DWORD     // 处理器类型
    AllocationGranularity     DWORD     // 虚拟内存的起始地址
    ProcessorLevel            WORD      // 依赖于体系结构的处理器级别。它只能用于显示目的。要确定处理器的功能集,请使用IsProcessorFeaturePresent函数。
    ProcessorRevision         WORD      // 依赖于体系结构的处理器版本
}

// 当前系统中的中央处理器的架构
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 奔腾架构  32位处理器
        }
    case 9:
        {
            return "x64" //  (AMD or Intel)  64位处理器
        }
    case 12:
        {
            return "ARM64" // 64位处理器
        }
    case 0xffff:
        {
            return "Unknow" // 未知
        }
    default:
        {
            return "Unknow" // 未知
        }
    }
}

// 是否为64位操作系统
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("架构          : ", dummyStructName.Architecture())
    // fmt.Println("处理器数量    : ", s.NumberOfProcessors)
    // fmt.Println("处理器类型    : ", s.ProcessorType)
    return dummyStructName
}


5 GetSystemMetrics()的API的调用


// 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() 判断操作系统

// 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及以上的操作系统
    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 专业版
                    //  19041 : win10 家庭中文版
                    //  19042 : win10 家庭中文版,教育版
                    //  19043 : win10 专业版
                    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一下的系统版本
    /*
        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
// 获取系统的版本号
/*

   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("开发版本:", buildNumber)
    buildNumber &= 0xffff

    // fmt.Println("-----------------RtlGetNtVersionNumbers-----------------")
    // fmt.Println("主版本号:", majorVersion)
    // fmt.Println("次版本号:", minorVersion)
    // fmt.Println("开发版本:", buildNumber)

    return

}


结束

以上代码,如果有疑问或者代码出现失误,请您及时联系我修改

简略不精准的代码 建议参考,不要使用:

下面的代码原理很简单,就是打开cmd,获取windows的cmd的[x.x.xxxx]的版本号截取下来,然后做匹配.这样虽然也行但是无法区分是否为服务器:



// 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(技术预览版)",                                // 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 当前
        `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")
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容