升級自訂專案
發佈時間: 2016年4月
若您變更保存於產品不同 Visual Studio 版本間的專案檔資訊,則需要支援將舊版專案檔升級為新版。 若要支援可讓您參與 [Visual Studio 轉換精靈] 的升級,請實作 IVsProjectUpgradeViaFactory 介面。 此介面包含僅適用於複本升級的機制。 專案升級會在解決方案開啟時發生。IVsProjectUpgradeViaFactory 介面應由 Project Factory 實作,或至少從 Project Factory 取得。
使用 IVsProjectUpgrade 介面的舊機制仍受支援,但就概念而言,則是在專案開啟時升級專案系統。 因此即使已呼叫或實作 IVsProjectUpgradeViaFactory 介面,IVsProjectUpgrade 介面仍是由Visual Studio 環境呼叫。 此方法可讓您使用 IVsProjectUpgradeViaFactory 只實作升級的複本與專案部分,並委派 IVsProjectUpgrade 介面就地完成其餘的工作 (可能在新的位置)。
如需 IVsProjectUpgrade 的範例實作,請參閱 VSSDK 範例。
下列情節會伴隨專案升級發生:
若檔案是專案無法支援的較新格式,則專案必需傳回錯誤以說明此狀況。 此處假設您的產品較舊版本 (例如 Visual Studio .NET 2003) 包含用以檢查版本的程式碼。
若在 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 參數的 QEF_ReportOnly 值來修改專案檔。 專案接著需執行下列動作:
若 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。 如需 IVsProjectUpgrade::UpgradeProject 的實作,請參閱 Basic Project。
您呼叫 QueryEditFiles,並傳入 rgfQueryEdit 參數的 QEF_ReportOnly 值。
環境傳回 QER_EditOK,並因為專案檔可寫入,所以可繼續更新。
若您無法升級,請從 IVsProjectUpgrade::UpgradeProject 傳回 VS_E_PROJECTMIGRATIONFAILED。 若不需要升級或您選擇不升級,請將 IVsProjectUpgrade::UpgradeProject 呼叫視為無作業。 若您傳回 VS_E_PROJECTMIGRATIONFAILED,預留位置節點就會加入專案的解決方案中。