升級專案
將專案模型從一個版本的 Visual Studio 變更為下一個版本,這項作業可能需要將專案和解決方案升級,才能在較新版本上執行。 Visual Studio SDK 提供的介面可用來在您自己的專案中實作升級支援。
升級策略
若要支援升級,您的專案系統實作必須定義與實作升級策略。 在確定策略時,您可以選擇支援並存 (SxS) 備份、複製備份或兩者。
SxS 備份表示專案只會複製需要就地升級的檔案,並新增適當的檔名尾碼,例如 “.old”。
複製備份表示專案會將所有專案項目複製到使用者提供的備份位置。 然後升級原始專案位置上的相關檔案。
升級的運作方式
在較早版本的 Visual Studio 中建立的解決方案開啟時,IDE 會檢查解決方案檔,以判斷是否需要升級解決方案檔。 如果需要升級,系統會自動啟動升級精靈 以引導使用者完成升級程序。
當解決方案需要升級時,它會查詢每個專案處理站的升級策略。 此策略會判斷專案處理站是否支援複製備份或 SxS 備份。 此資訊會傳送至 升級精靈,其會收集備份所需的資訊,並將適用的選項呈現給使用者。
多專案解決方案
如果解決方案包含多個專案且升級策略不同,例如當僅支援 SxS 備份的 C++ 專案和僅支援複製備份的 Web 專案時,專案處理站必須協商升級策略。
解決方案會查詢每個專案處理站的 IVsProjectUpgradeViaFactory。 然後它會呼叫 UpgradeProject_CheckOnly 來查看全域專案檔是否需要升級,並判斷支援的升級策略。 接著會叫用升級精靈。
使用者完成精靈之後,UpgradeProject 會在每個專案處理站上呼叫以執行實際的升級。 為了加速備份,IVsProjectUpgradeViaFactory 方法會提供 SVsUpgradeLogger 服務來記錄升級程式的詳細資料。 無法快取此服務。
更新所有相關的全域檔案之後,每個專案處理站都可以選擇具現化專案。 專案實作必須支援 IVsProjectUpgrade。 接著會呼叫 UpgradeProject 方法升級所有相關專案項目。
注意
UpgradeProject 方法不提供 SVsUpgradeLogger 服務。 呼叫 QueryService 即可取得此服務。
最佳做法
使用 SVsQueryEditQuerySave 服務來檢查您是否可以在編輯檔案之前編輯檔案,並在儲存檔案之前先儲存檔案。 這有助於備份和升級實作處理原始檔控制下的專案檔、權限不足的檔案等。
在備份和升級的所有階段期間使用 SVsUpgradeLogger 服務,以提供升級程序成功或失敗的相關資訊。
如需備份和升級專案的詳細資訊,請參閱 vsshell2.idl 中的 IVsProjectUpgrade 註解。
升級自訂專案
若您變更保存於產品不同 Visual Studio 版本間的專案檔資訊,則需要支援將舊版專案檔升級為新版。 若要支援可讓您參與 Visual Studio 轉換精靈的升級,請實作 IVsProjectUpgradeViaFactory 介面。 此介面包含僅適用於複本升級的機制。 專案升級會在解決方案開啟時發生。 IVsProjectUpgradeViaFactory 介面應由 Project Factory 實作,或至少從 Project Factory 取得。
使用 IVsProjectUpgrade 介面的舊機制仍受支援,但就概念而言,則是在專案開啟時升級專案系統。 因此即使已呼叫或實作 IVsProjectUpgradeViaFactory 介面,Visual Studio 環境仍會呼叫 IVsProjectUpgrade 介面。 此方法可讓您使用 IVsProjectUpgradeViaFactory 只實作升級的複本與專案部分,並委派 IVsProjectUpgrade 介面就地完成其餘的工作 (可能在新的位置)。
如需 IVsProjectUpgrade 的範例實作,請參閱 VSSDK 範例。
下列情節會伴隨專案升級發生:
若檔案是專案無法支援的較新格式,則專案必需傳回錯誤以說明此狀況。 這假定舊版本的產品包含用於檢查版本的程式碼。
若在 UpgradeProject 方法中指定 PUVFF_SXSBACKUP 旗標,會在專案開啟前以就地升級的方式實作升級。
若在 UpgradeProject 方法中指定 PUVFF_COPYBACKUP 旗標,會以複本升級的方式實作升級。
若在 UpgradeProject 呼叫中指定 UPF_SILENTMIGRATE 旗標,環境則會在專案開啟後提示使用者,以就地升級方式來升級專案檔。 例如,環境會在使用者開啟舊版解決方案時,提示使用者進行升級。
若未在 UpgradeProject 呼叫中指定 UPF_SILENTMIGRATE 旗標,則您必須提示使用者升級專案檔。
下列為升級提示訊息的範例。
「專案 '%1' 是由舊版 Visual Studio 建立。 若您使用此版本的 Visual Studio 開啟專案,可能無法再使用舊版 Visual Studio 加以開啟。 仍要繼續開啟此專案嗎?」
實作 IVsProjectUpgradeViaFactory
實作 IVsProjectUpgradeViaFactory 介面的方法 (尤其是您 Project Factory 實作中的 UpgradeProject 方法),或讓實作可從您的 Project Factory 實作加以呼叫。
若您想在解決方案開啟時執行就地升級,請提供旗標 PUVFF_SXSBACKUP 作為您 UpgradeProject 實作中的
VSPUVF_FLAGS
參數。若您想在解決方案開啟時執行就地升級,請提供旗標 PUVFF_COPYBACKUP 作為您 UpgradeProject 實作中的
VSPUVF_FLAGS
參數。若是使用 IVsQueryEditQuerySave2 的步驟 2 與 3 (實際的檔案升級步驟),可依下方<實作
IVsProjectUpgade
>章節所述加以實作,也可將實際的檔案升級委派給 IVsProjectUpgrade。使用 IVsUpgradeLogger 的方法,為 [Visual Studio 移轉精靈] 的使用者張貼升級相關訊息。
IVsFileUpgrade 介面的用途是實作任何需要在專案升級時發生的檔案升級種類。 此介面並非從 IVsProjectUpgradeViaFactory 呼叫,但會用作升級專案系統內檔案的機制,而主要專案系統可能不會直接察覺到。 比方說,若處理編譯器相關檔案和內容的開發小組與處理其餘專案系統的開發小組不同,就會發生此狀況。
IVsProjectUpgrade 實作
如果您的專案系統只實作 IVsProjectUpgrade,就無法參與 Visual Studio 轉換精靈。 不過,即使您實作 IVsProjectUpgradeViaFactory 介面,仍可將檔案升級委派給 IVsProjectUpgrade 實作。
實作 IVsProjectUpgrade
當使用者嘗試開啟專案時,環境會在專案開啟後、使用者可對專案進行任何動作前,呼叫 UpgradeProject 方法 若已提示使用者升級解決方案,則會將 UPF_SILENTMIGRATE 旗標傳入
grfUpgradeFlags
參數。 如果使用者直接開啟專案,例如使用 [新增現有專案] 命令,則不會傳遞 UPF_SILENTMIGRATE 旗標,而且專案需要提示使用者升級。為了回應 UpgradeProject 呼叫,專案必須評估專案檔是否已升級。 若專案不需要將專案類型升級至新版,則可以只傳回 S_OK 旗標。
若專案需要將專案類型升級至新版,則必須判斷是否可以透過呼叫 QueryEditFiles 方法並傳入
rgfQueryEdit
參數的 tagVSQueryEditFlags 值來修改專案檔。 專案接著需執行下列動作:若
pfEditCanceled
參數中傳回的VSQueryEditResult
值為 QER_EditOK,即表示專案檔可寫入,所以可繼續更新。若
pfEditCanceled
參數中傳回的VSQueryEditResult
值為 QER_EditNotOK,且VSQueryEditResult
值有 QER_ReadOnlyNotUnderScc 位元集,則 UpgradeProject 會因為使用者必須自行解決權限問題,而必需傳回失敗。 專案接著應執行下列動作:呼叫 ReportErrorInfo 並將 VS_E_PROJECTMIGRATIONFAILED 錯誤碼傳回至 IVsProjectUpgrade,向使用者報告錯誤。
若
VSQueryEditResult
值為 QER_EditNotOK,且VSQueryEditResultFlags
值有 QER_ReadOnlyUnderScc 位元集,則應透過呼叫 QueryEditFiles 簽出專案檔(QEF_ForceEdit_NoPrompting、QEF_DisallowInMemoryEdits、...)。
若對專案檔的 QueryEditFiles 呼叫導致檔案簽出,並擷取到最新版本,則會先將專案卸載再將其重新載入。 一旦建立專案的另一個執行個體,就會再次呼叫 UpgradeProject 方法。 在第二次呼叫時,專案檔即可寫入磁碟。建議專案使用 .OLD 副檔名以先前格式儲存專案檔複本,變更其必要升級,然後以新格式儲存專案檔。 同樣地,若升級程序的任一部分失敗,此方法必須傳回 VS_E_PROJECTMIGRATIONFAILED 以表示失敗。 這會導致專案從方案總管卸載。
請務必了解在對 QueryEditFiles 方法 (指定 ReportOnly 的值) 的呼叫傳回 QER_EditNotOK 與 QER_ReadOnlyUnderScc 旗標的案例中,該環境發生的完整程序。
使用者嘗試開啟專案檔。
環境呼叫您的 CanCreateProject 實作。
若 CanCreateProject 傳回
true
,則環境會呼叫您的 CanCreateProject 實作。環境呼叫您的 Load 實作,以開啟檔案並將專案物件初始化,例如 Project1。
環境呼叫您的
IVsProjectUpgrade::UpgradeProject
實作,以判斷是否需要升級專案檔。您呼叫 QueryEditFiles,並傳入
rgfQueryEdit
參數的 QEF_ReportOnly 值。環境為
VSQueryEditResult
傳回 QER_EditNotOK,且 QER_ReadOnlyUnderScc 位元設定於VSQueryEditResultFlags
。您的 IVsProjectUpgrade 實作呼叫
IVsQueryEditQuerySave::QueryEditFiles
(QEF_ForceEdit_NoPrompting、QEF_DisallowInMemoryEdits)。
此呼叫可能導致您的專案檔新複本簽出、擷取到最新版本,且需要重新載入您的專案檔。 此時會發生下列兩種情況之一:
若您處理自己的專案重新載入,則環境會呼叫您的 ReloadItem (VSITEMID_ROOT) 實作。 當您收到此呼叫時,請重新載入專案的第一個執行個體 (Project1),並繼續升級專案檔。 若您為 GetProperty (VSHPROPID_HandlesOwnReload) 傳回
true
,環境便知道您會處理自己的專案重新載入。若您未處理自己的專案重新載入,則為 GetProperty (VSHPROPID_HandlesOwnReload) 傳回
false
。 在此情況下,在 QueryEditFiles(QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits) 傳回之前 ,環境會建立另一個新專案執行個體,例如 Project2,如下所示:環境對您的第一個專案物件 (Project1) 呼叫 Close,讓此物件處於非使用中狀態。
環境呼叫您的
IVsProjectFactory::CreateProject
實作,以建立您的專案的第二個執行個體 (Project2)。環境呼叫您的
IPersistFileFormat::Load
實作,以開啟檔案並將第二個專案物件 (Project2) 初始化。環境第二次呼叫
IVsProjectUpgrade::UpgradeProject
,以判斷是否應升級專案物件。 不過,此呼叫會在專案新的第二個執行個體 (Project2) 執行。 此為在解決方案中開啟的專案。注意
您的第一個專案執行個體 (Project1) 處於非使用中狀態,因此必須從 UpgradeProject 實作的第一個呼叫傳回 S_OK。
您呼叫 QueryEditFiles,並傳入
rgfQueryEdit
參數的 QEF_ReportOnly 值。環境傳回 QER_EditOK,並因為專案檔可寫入,所以可繼續更新。
若您無法升級,請從 IVsProjectUpgrade::UpgradeProject
傳回 VS_E_PROJECTMIGRATIONFAILED。 若不需要升級或您選擇不升級,請將 IVsProjectUpgrade::UpgradeProject
呼叫視為無作業。 若您傳回 VS_E_PROJECTMIGRATIONFAILED,預留位置節點就會加入專案的解決方案中。
升級專案項目
如果您在未實作的專案系統中新增或管理項目,您可能需要參與專案升級程序。 Crystal Reports 是可新增至專案系統的項目範例。
一般而言,專案項目實作者想要利用已經完全具現化和升級的專案,因為他們必須知道專案參考是什麼,以及有哪些其他專案屬性才能做出升級決策。
取得專案升級通知
在您的專案項目實作中設定 SolutionOrProjectUpgrading 旗標 (定義於 vsshell80.idl) 中。 這會導致當 Visual Studio 殼層判斷專案系統正在進行升級時,使您的專案項目 VSPackage 自動載入。
透過 AdviseSolutionEvents 方法建議 IVsSolutionEventsProjectUpgrade 介面。
在專案系統實作完成升級作業並建立新的升級專案之後,就會引發 IVsSolutionEventsProjectUpgrade 介面。 視案例而定,IVsSolutionEventsProjectUpgrade 介面會在 OnAfterOpenSolution、OnAfterOpenProject 或 OnAfterLoadProject 方法之後引發。
升級專案項目檔
您必須仔細管理專案項目實作中的檔案備份程序。 這特別適用於並存備份,其中 UpgradeProject 方法的
fUpgradeFlag
參數設定為 PUVFF_SXSBACKUP,其中已備份的檔案放在指定為 “.old” 的檔案旁邊。 升級專案時,比系統時間還舊的備份檔案可以指定為過時。 此外,除非您採取特定步驟來避免這種情況發生,否則可能會覆寫那些檔案。當專案項目收到專案升級的通知時,仍會顯示 Visual Studio 轉換精靈。 因此,您應該使用 IVsUpgradeLogger 介面的方法 ,將升級訊息提供給精靈 UI。