目的
在本次實驗中,您將學到如何:
• 圍繞版本問題,使用兼容模 式來檢測錯誤
• 正確的檢測最低的操作系統版本
• 檢測功能而不用檢測操作系統版本
系統需求
若完成本次實驗,您 必須包含以下幾個組件:
• Microsoft Visual Studio 2008
• Microsoft Windows 7
練習: 了解版本檢測
在本次練習中,您將學到如何開發一個檢測最低操作系統版 本的應用程序,使其能夠在更新版本的操作系統上很好的運行。正確的方法就是偽裝安裝的 真實的操作系統的版本。接下來,你將修改應用程序的代碼,使其能夠在其他的操作系統版 本上進行工作。最終,你將修改代碼來檢測功能的有效性,而不是檢測操作系統的版本。
任務 1 –檢查並編譯下面的應用程序片段
1.指向VersionCheck解決方 案所在的文件夾
2.在Visual Studio 2008中打開VersionCheck解決方案。
3. 請確認編譯的設置是Debug/x86:
4.在解決 方案浏覽器中,右鍵點擊VersionCheckManagedBroken項目,並且選擇設置為啟動項目。
5.導航到Program.cs文件中的Main方法。
6.請注意Environment.OSVersion是如何獲取操作系統版本的。同時,也請注意比較,它 是如何使應用程序只能運行在版本號為5.1的操作系統(Microsoft Windows XP)上的。如果 不是,它將打開一個消息窗體。
7.編譯並且運行應用程序。
8.請注意下面的消息窗體:
當心
兼容模式並不適用於托管代碼的應用程序。但是,如果你的應用程序是混合的(本地代碼 和托管代碼),並且你是使用調用本地代碼的方式來檢測操作系統的版本,那麼,設置兼容 模式應該能夠有一定的幫助。
你可以參考本地代碼的檢測版本的HOL來獲取更多信息。
任務 2 –修改應用程序,以便正確的檢測最小操作系統版本
1.指向Program.cs文件。
2.修改Main方法,使用下面的代碼來替換檢查版本的代碼:
C#
// This code checks if the OS is at least Windows XP
if (Environment.OSVersion.Version < new Version(5, 1))
{
MessageBox.Show("Windows XP or later required.",
"Incompatible Operating System", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
3.請注意,我們將!=操作符改為了<,它可以允許應用程序在更新版本的操作系統中運 行。
4.編譯並運行應用程序。你需要注意,應用程序現在已經可以在Windows 7上正常的運行 了。
任務 3 –檢查功能而不是檢查版本
在這個任務中,你將學到如何去檢測某個Windows 功能是否存在,而不是去依賴於檢測操 作系統的版本來確定該功能是否存在。那麼即使這個功能是早先的操作系統中後期添加的, 我們也能使應用程序運行並使用這些功能。Microsoft計劃在未來向Windows Vista中添加兩 個Windows 7的特性:Direct2D/DirectWrite 和 Ribbon。
1.指向到WaitableTimer.cs中的Start函數。
2.請注意,Start函數現在調用了SetWaitableTimer,而SetWaitableTimer至少在Windows 2000之上才有用。
3.使用下面的代碼來替換Start函數中的代碼:
注意:SetWaitableTimerEx P/Invoke函數聲明和其他的P/Invoke相關的代碼,都是在 Win32.cs中預先寫好並且可用的。
C#
public void Start(long dueTime, int period)
{
ReasonContext rc = new ReasonContext();
rc.Version = 0;
rc.Flags = 1;
rc.SimpleReasonString = "MyTimer";
try
{
// Use Windows 7 version if possible
if (!Win32.SetWaitableTimerEx(_hTimer, ref dueTime, period,
IntPtr.Zero, IntPtr.Zero, ref rc, 5000))
throw new Win32Exception (Marshal.GetLastWin32Error(),
"SetWaitableTimerEx failed.");
IsCoalescingtimer = true;
}
catch (EntryPointNotFoundException)
{
IsCoalescingtimer = false;
// Otherwise, use prior version
if (!Win32.SetWaitableTimer (_hTimer, ref dueTime, period,
IntPtr.Zero, IntPtr.Zero, false))
throw new Win32Exception(Marshal.GetLastWin32Error(), "SetWaitableTimer failed.");
}
_waiterThread = new Thread(WaiterThreadProc);
_waiterThread.Name = "Waiter thread for WaitableTimer";
_waiterThread.Start();
}
幫助
請注意,我們首先通過P/Invoke調用了SetWaitableTimerEx。這個函數,在Windows 7中 有過介紹,它是支持調用時間偏差容錯,以確保Windows能夠整合多個計時器,來使CPU占用 更少並且節省更多能量。
如果在kernel32.dll中沒有這個函數,那麼調用將拋出一個 EntryPointNotFoundException異常。所以,我們使用早一些的SetWaitableTimer函數。這個 函數允許應用程序運行在不包含這個功能(使用精簡的功能)的Windows版本中,而不是根本 就不能運行。
4.編譯並運行應用程序。
5.請注意,應用程序將顯示出是否當前使用了新的計時器API(SetWaitableTimerEx):
注意
在一個應用程序的展現層整合邏輯,就好像我們這裡展示的,是一個十分不好的軟件設計 體驗。這樣不容易測試,整合問題和發現一些其他的設計原則。
我們將這些原則中斷,並在Windows消息循環中整合我們的邏輯,來保證我們的例子簡潔 干淨。在實際的應用程序中,將我們的邏輯放入到獨立的類中,最好使用Model View Presenter (MVP)或者類似的途徑。我們鼓勵你去使用MVP並且使用其設計原則,這樣能夠幫 助你更輕松的編寫易維護易測試的應用程序。