目的
在本次實驗中,你將了解到如何:
• 使用兼容模式來圍繞版本 來檢測錯誤
• 正確的檢測最小支持的操作系統版本
• 檢測功能而不用檢測操作系統版本
系統需求
若要完成本次實驗, 你必須包含以下組件:
• Microsoft Visual Studio 2008 (配置在Windows 7中 )
• Microsoft Windows 7
• Microsoft Windows 7 SDK
練習: 了 解版本檢測
在本次練習中,您將學到如何開發一個檢測最低操作系統版本的應用程序 ,使其能夠在更新版本的操作系統上很好的運行。正確的方法就是偽裝安裝的真實的操作系 統的版本。接下來,你將修改應用程序的代碼,使其能夠在其他的操作系統版本上進行工作 。最終,你將修改代碼來檢測功能的有效性,而不是檢測操作系統的版本。
任務 1 –檢查並編譯下面的應用程序片段
1.定位到VersionCheck解決方案的文件夾中 。
2.在Visual Studio 2008中打開VersionCheck解決方案。
3.請確認編譯的 設置是Debug/x86:
4.在解決方案浏覽器中:
a.右鍵點擊 VersionCheckNativeBroken 項目
b.選擇設置為起始項目
5.在VersionCheckNativeBroken.cpp文件中,定位到_tWinMain函數(文件的最頂部)。
6.請注意GetVersionEx是如何獲取操作系統版本的。
7.請注意比較,它是如何使應用程序只能運行在版本號為5.1的操作系統(Microsoft Windows XP)上的。如果不是,它將打開一個消息窗體。
8.編譯並運行應用程序。
9.請注意彈出的消息窗體:
任務 2 –使用兼容模式來模擬版本信息
1.定位到應用程序文件夾中的.exe文件。它應該是位於 <solution_dir>\VersionCheckNativeBroken\Release目錄下。
2.右鍵點擊VersionCheckNativeBroken.exe文件,並且選擇屬性。
3.點擊兼容性標簽:
4.選擇以兼容模式運行這個應用程序復選框。
5.在下拉菜單中,選擇“Windows XP (Service Pack 3).”
6.點擊OK 。
7.運行這個應用程序。你將會看到,現在應用程序就能運行了。
8.重復步 驟1-6,但是這次,清空兼容模式的復選框。那麼將在下次任務運行的時候,取消兼容模式。
幫助
請注意,這不是最佳的解決方案,我們強烈建議修改應用程序來正確檢 測操作系統和未失敗的應用程序。
任務 3 –修改應用程序,使 其正確的檢測最低支持的操作系統版本
1.定位到VersionCheckNativeBroken.cpp文件 。
2.在_tWinMain上面,添加下面的函數聲明:
C++
BOOL TestMinimumOSRequirement();
3.定位到_tWinMain函數,並且使用調用 TestMinimumOSRequirement()函數的代碼,來替換版本檢測代碼。最終的結果應該是:
C++
// Program entry point
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
// Instead of using GetVersion/GetVersionEx, use
// VerifyVersionInfo to test for
// minimum OS requirements
if (!TestMinimumOSRequirement())
{
MessageBox(NULL,
_T("Windows XP SP2 or later is required."),
_T("Wrong OS version."), MB_OK | MB_ICONERROR);
return 1;
}
// Initialize common controls (for progress bar)
InitCommonControls();
// Show the dialog with a dialog template resource
IDD_VERSIONCHECKNATIVE_DIALOG
DialogBox(hInstance,
MAKEINTRESOURCE(IDD_VERSIONCHECKNATIVE_DIALOG), 0,
DlgMainProc);
return 0;
}
4.使用下面的代碼添加TestMinimumOSRequirement函數:
C++
// Check minimum OS requirement
// This function returns TRUE if OS is XP SP2 or later
// (for example Windows Vista, Windows 7)
BOOL TestMinimumOSRequirement()
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
int op=VER_GREATER_EQUAL;
// Initialize the OSVERSIONINFOEX structure.
ZeroMemory (&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 1; // Windows XP
osvi.wServicePackMajor = 2; // Service Pack 2
osvi.wServicePackMinor = 0;
// Initialize the condition mask.
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );
// Perform the test.
return VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
dwlConditionMask);
}
5.編譯並運行應用程序。你將會發現現在應用程序能夠正常的運行在Windows 7中了。
任務 4 –檢查功能而不是檢查版本
在這個任務中,你將學到如何去檢測某個Windows 功能是否存在,而不是去依賴於檢測操 作系統的版本來確定該功能是否存在。那麼即使這個功能是早先的操作系統中後期添加的, 我們也能使應用程序運行並使用這些功能。Microsoft計劃在未來向Windows Vista中添加兩 個Windows 7的特性:Direct2D/DirectWrite 和 Ribbon。
1.定位到Timer.cpp文件中的CTimer::Set函數。
2.請注意,CTimer::Set函數調用了SetWaitableTimer,而SetWaitableTimer至少在 Windows 2000之上才有用。
3.在這個函數中,將代碼中注釋的部分取消注釋。
4.在文件的最開始的位置,將注釋的代碼取消注釋。
C++
typedef BOOL (WINAPI *SetWaitableTimerExProc)(
__in HANDLE hTimer,
__in const LARGE_INTEGER *lpDueTime,
__in LONG lPeriod,
__in PTIMERAPCROUTINE pfnCompletionRoutine,
__in LPVOID lpArgToCompletionRoutine,
__in PREASON_CONTEXT WakeContext,
__in ULONG TolerableDelay
);
5.請注意,我們使用了GetModuleHandle()來獲取kernel32.dll的句柄。kernel32.dll總 是會被加載到進程中的。如果你正在使用一個還沒有被加載的模塊,那麼就需要使用 LoadLibrary()來獲取模塊的句柄了。
6.請注意,我們使用了GetProcAddress()來獲取函數的地址,並且將返回值轉換到函數指 針(SetWaitableTimerExProc)。
7.如果GetProcAddress()返回一個空值,那麼就代表在kernel32.dll 中沒有找到 SetWaitableTimerEx函數。那麼我們就必須使用SetWaitableTimer函數來代替它。這樣能確 保應用程序能夠始終使用當前Windows版本中沒有包含的功能(精簡的功能)。
8.編譯並運行應用程序。
9.請注意,應用程序將顯示出是否正在使用新的計時器API(SetWaitableTimerEx):
注意
在一個應用程序的展現層整合邏輯,就好像我們這裡展示的,是一個十分不好的軟件設計 體驗。這樣不容易測試,整合問題和發現一些其他的設計原則。
我們將這些原則中斷,並在Windows消息循環中整合我們的邏輯,來保證我們的例子簡潔 干淨。在實際的應用程序中,將我們的邏輯放入到獨立的類中,最好使用Model View Presenter (MVP)或者類似的途徑。我們鼓勵你去使用MVP並且使用其設計原則,這樣能夠幫 助你更輕松的編寫易維護易測試的應用程序。