(這段時間在Vista相容性講座以及後續的支援過程中積累了一些東西,很希望和大家分享,這篇文章就作一個開頭吧,我會在近期陸續發一些Vista開發相關的內容。)
自從我們開始使用電腦開始,重新啟動就一直是我們用來“解決問題”的最後紡線,應用程式的更新更是如此,很多的問題都因為從新啟動而變得簡單。但是隨著我們用的系統變得複雜,重新啟動也變得越來越讓人無法接受,你可以想象一下需要關閉20個視窗然後等待10分鐘來啟動所有的系統服務的感覺嗎?而你所更新的可能僅僅是媒體播放器的一個小小的bug。
Windows系統更新可能很多人都已經注意到了微軟的Windows更新系統的新功能,它可以允許你延遲從新啟動的操作,比如:Figure:我們可以僅僅點擊關閉,而過後再重啟
Figure:Vista中的系統更新提示Figure:Vista中的系統自動更新正在下載和安裝更新包這個功能讓的我們的系統更新變得人性化,我們不用在受電腦的脅迫而去做我們不原意的重啟了。
重啟管理器的主要功能但是,如果我們的更新更加智能化一下,可以自動的關閉我們正在啟動並執行應用程式,並且在更新完成以後自動的啟動它,那不是更好嗎?重啟管理器就是為了實現這樣的功能而設計的。先看一下我們如果使用了重啟管理器會有怎樣的效果。假設你在下班之前沒有完成一個文檔,把寫了一半的檔案留在了螢幕上;那麼如果半夜裡Word 2007需要進行更新,那麼Vista系統就會調用重啟管理器來通知Word 2007做安全關閉動作,當支援重啟管理器的Word 2007收到安全關閉的訊息的時候,它會自動將未完成的文檔儲存並關閉自己的所有視窗;當更新完成以後,重啟管理器就會通知Word 2007啟動並會協助其恢複原來的狀態;不僅僅包括未完成的文檔,還包括視窗的位置,游標的位置等所有和使用者使用環境相關的內容。同時,在我們設計更新程式的安裝包的時候我們也可以調用重啟管理器的API來嚮應用程式發出關閉和重啟訊息。
Figure:使用了重啟管理器API的安裝包會給出友好的提示我們可以很明顯的看到,重啟管理器可以協助我們提升使用者在更新應用程式的過程中的體驗,基本上使用者的工作過程不會被更新程式打擾,而可以專註於自己正在處理的工作。
如何?重啟管理器的功能Windows Vista系統已經內建了對重啟管理器的支援,系統可以在安裝更新包之前自動的嚮應用程式發出關閉訊息,並在安裝完成以後發出啟動訊息。我們的應用程式需要做的事情就是相應這些訊息並作出爭取的處理。1.註冊支援重啟管理器NativeMethods.RegisterApplicationRestart( commandLineReturnValue, //用來唯一標識目前狀態的主鍵 0); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] internal static extern uint RegisterApplicationRestart( string pszCommandline, int dwFlags); 上面所列的是c#代碼實現的RegisterApplicationRestart API的調用,RegisterApplicationRetart是用來註冊當前應用程式的系統API,調用之後,系統就知道這個應用程式會支援重啟管理器的功能;在註冊的同時我們還可以傳送一個參數commandLineRetureValue,這個參數在後面會被重啟管理器作為命令列參數返回給應用程式。 2.響應ENDSESSION_CLOSEAPP系統訊息 //private const int ENDSESSION_LOGOFF = 0x8; private const int WM_QUERYENDSESSION = 0x0011; private const int ENDSESSION_CLOSEAPP = 0x1; protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == WM_QUERYENDSESSION) { if (m.LParam.ToInt32() == ENDSESSION_CLOSEAPP) { //這裡我們可以儲存應用程式的狀態 } } }這段代碼中我們首先定義了系統訊息的靜態值,然後使用一個標準的系統訊息回應程式法來檢查我們收到的訊息是否來自重啟管理器;如果是的話,那麼我們就需要對應用程式狀態進行儲存,比如可以使用檔案,序列化,甚至資料庫進行儲存。 3.測試啟動參數,並恢複應用程式狀態private void Form1_Load(object sender, EventArgs e) { string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1) { String commandLineReturnValue = args[1]; //開始恢複應用程式狀態 } } 應用程式如果是被重啟管理器啟動的話,那麼我們可以在第二個命令列參數中獲得我們當初註冊的時候傳入的那個參數,藉助這個參數我們就可以進行程式的重新啟動。 我們可以看到,實際上重啟管理器只是定義了一個API用來註冊應用程式,和一個系統訊息來通知應用程式重啟;其他的工作都需要我們的開發人員來自己實現,這可能讓我們有點失望,但也是可以理解的,因為系統並不知道那些程式狀態是重要的,必須要恢複的;這些應該是開發人員的責任。 另外還有兩點很重要的內容,我們在實現重啟管理器的時候需要注意:1)重啟管理器的API只有在Vista的kernel32.dll中才有,所以如果你的應用程式需要提供支援,那麼必須在Vista上進行編譯;2)為了保證我們的應用程式可以在xp及一下系統上正常運行,一定要在調用RegisterApplicationRestart之前檢查系統版本,比如使用Environment.OsVersion或者GetVersionEx API,只有當版本號碼大於6.0.6000的時候才進行調用,否則會造成崩潰。
資源:1)重啟管理器示範程式,RestartManagerController, RestartManagerListner (如果需要請給我發信)2)MSDN文檔:http://msdn.microsoft.com/windowsvista
/prodinfo/what/reliability/default.aspx