1. 程式人生 > >獲取Windows系統版本號

獲取Windows系統版本號

前言

由於前段時間比較忙,一直沒有來跟大家分享交流技術,實在是抱歉,往後我會不定時跟大家分享一些C++技術。

廢話

有些東西看似簡單,但坑多著呢,所以大家還是要多親自嘗試,不要眼高手低。

核心程式碼

//讀取作業系統的名稱
string GetSystemName()
{
	SYSTEM_INFO info;        //用SYSTEM_INFO結構判斷64位AMD處理器 
	GetSystemInfo(&info);    //呼叫GetSystemInfo函式填充結構 
	OSVERSIONINFOEX os; 
	os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);   

	string osname = "unknown OperatingSystem.";

	if(GetVersionEx((OSVERSIONINFO *)&os))
	{ 
		//下面根據版本資訊判斷作業系統名稱 
		switch(os.dwMajorVersion)//判斷主版本號
		{
		case 4:
			switch(os.dwMinorVersion)//判斷次版本號 
			{ 
			case 0:
				if(os.dwPlatformId==VER_PLATFORM_WIN32_NT)
					osname = "Microsoft Windows NT 4.0"; //1996年7月釋出 
				else if(os.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
					osname = "Microsoft Windows 95";
				break;
			case 10:
				osname = "Microsoft Windows 98";
				break;
			case 90:
				osname = "Microsoft Windows Me";
				break;
			}
			break;

		case 5:
			switch(os.dwMinorVersion)	//再比較dwMinorVersion的值
			{ 
			case 0:
				osname = "Microsoft Windows 2000";//1999年12月釋出
				break;

			case 1:
				osname = "Microsoft Windows XP";//2001年8月釋出
				break;

			case 2:
				if(os.wProductType==VER_NT_WORKSTATION 
					&& info.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
				{
					osname = "Microsoft Windows XP Professional x64 Edition";
				}
				else if(GetSystemMetrics(SM_SERVERR2)==0)
					osname = "Microsoft Windows Server 2003";//2003年3月釋出 
				else if(GetSystemMetrics(SM_SERVERR2)!=0)
					osname = "Microsoft Windows Server 2003 R2";
				break;
			}
			break;

		case 6:
			switch(os.dwMinorVersion)
			{
			case 0:
				if(os.wProductType == VER_NT_WORKSTATION)
					osname = "Microsoft Windows Vista";
				else
					osname = "Microsoft Windows Server 2008";//伺服器版本 
				break;
			case 1:
				if(os.wProductType == VER_NT_WORKSTATION)
					osname = "Microsoft Windows 7";
				else
					osname = "Microsoft Windows Server 2008 R2";
				break;
			case 2:
				if(os.wProductType == VER_NT_WORKSTATION)
					osname = "Microsoft Windows 8";
				else
					osname = "Microsoft Windows Server 2012";
				break;
			case 3:
				if(os.wProductType == VER_NT_WORKSTATION)
					osname = "Microsoft Windows 8.1";
				else
					osname = "Microsoft Windows Server 2012 R2";
				break;
			}
			break;

		case 10:
			switch(os.dwMinorVersion)
			{
			case 0:
				if(os.wProductType == VER_NT_WORKSTATION)
					osname = "Microsoft Windows 10";
				else
					osname = "Microsoft Windows Server 2016 Technical Preview";//伺服器版本 
				break;
			}
			break;
		}
	}//if(GetVersionEx((OSVERSIONINFO *)&os))
	//https://msdn.microsoft.com/en-us/library/ms724832.aspx
	return osname;
} 
注意事項

現在系統升級很快,這對軟體開發人員來說是個打擊,測試起來太麻煩,要考慮的相容性問題也越來越多,坑也越來越多。。。
雖然核心程式碼就一個函式:GetVersionEx,但是Win8.1和Win10獲取到的版本缺一直是6.2(Win8)
仔細閱讀微軟說明:https://msdn.microsoft.com/en-us/library/ms724832.aspx 細心的朋友可以從中找到答案
我用國語講一下出現這個問題的原因:簡單講就是相容問題。可以通過修改manifest檔案解決,也可以採用新的API來獲取版本號。
由於新的API在低版本作業系統沒有,還要特別處理,我們乾脆使用修改manifest檔案的方法,提高程式自身的相容性,從而得到正確的系統版本資訊。

<?xml version="1.0" encoding="UTF-8"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
        <application> 
            <!-- Windows 10 --> 
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
        </application> 
    </compatibility>
</assembly> 
將以上內容儲存為compatibility.xml,留著備用。
實戰

問題和解決方法也介紹差不多了,下面演示一下如何正確使用。
新建一個基於對話方塊的MFC專案,然後新增如下圖所示程式碼,執行結果如下

很明顯。是有問題的,本來win8.1系統,它說是win8的,下面說一下解決辦法。
程式碼不變,只需要把專案屬性設定一下就好了
配置目標那裡選則所有配置,配置屬性->清單工具->輸入和輸出-附加清單檔案 填寫compatibility.xml,並把這個檔案拷貝到專案原始碼目錄。
具體設定如下圖所示:


設定儲存後,重新生成一下,然後執行,結果如下:


很明顯,已經是win8.1了,將程式拷貝到Win10機器上,獲取到的也正確。

可以獲取作業系統版本,MAC地址,本地IP地址,以及判定是否為網咖。核心我已經封裝成類了。