共用方式為


專案子類型的初始化順序

環境藉由呼叫 CreateProject 的基底專案 Factory 實作來建構專案。 當環境判斷專案檔案副檔名的專案類型 GUID 清單不是空白時,開始建構專案子類型。 專案檔案副檔名和專案 GUID 指定專案是 Visual Basic 或 Visual C# 專案類型。 例如:.vbproj 副檔名和 {F184B08F-C81C-45F6-A57F-5ABD9991F28F} 識別 Visual Basic 專案。

環境的專案子類型初始化

下列程序詳細說明由多個專案子類型彙總的專案系統初始化順序。

  1. 環境呼叫基底專案的 CreateProject,而專案剖析其專案檔案時,它發現彙總專案類型 GUID 清單不是 null。 專案不再直接建立其專案。

  2. 專案呼叫 SVsCreateAggregateProject 服務上的 QueryService,以使用環境的 CreateAggregateProject 方法實作來建立專案子類型。 在這個方法中,環境從最外層的專案子類型開始逐步執行專案類型 GUID 清單,同時對 PreCreateForOuterSetInnerProjectInitializeForOuter 方法的實作進行遞迴函式呼叫。

    下面詳細介紹初始化步驟。

    1. 環境的 CreateAggregateProject 方法實作使用下列函式宣告呼叫 HrCreateInnerProj 方法:

      <CodeContentPlaceHolder>0

      第一次呼叫此函式時,也就是對於最外層的專案子類型,參數 pOuterpOwner 會作為 null 傳入,而且函式將最外層的專案子類型 IUnknown 設定為 pOuter

    2. 接下來,環境使用清單中的第二個專案類型 GUID 來呼叫 HrCreateInnerProj 函式。 此 GUID 對應於彙總順序中逐步進入基底專案的第二個內部專案子類型。

    3. pOuter 現在指向最外層專案子類型的 IUnknownHrCreateInnerProj 呼叫 PreCreateForOuter 的實作,然後呼叫 SetInnerProject 的實作。 在 PreCreateForOuter 方法中,您傳入最外層專案子類型 pOuter 的控制 IUnknown。 擁有的專案 (內部專案子類型) 必須在這裡建立其彙總專案物件。 在 SetInnerProject 方法實作中,您傳遞一個指向正在彙總之內部專案的 IUnknown 指標。 這兩種方法會建立匯總物件,並且您的實作需要遵循 COM 彙總規則,以確保專案子類型不會保有本身的參考計數。

    4. HrCreateInnerProj 呼叫您的 PreCreateForOuter 實作。 在此方法中,專案子類型會執行其初始化工作。 例如,您可以在 InitializeForOuter 中註冊方案事件。

    5. 以遞歸方式呼叫 HrCreateInnerProj,直至到達清單中的最後一個 GUID (基底專案) 為止。 對於每個呼叫,都會重複步驟 c 到 d。 pOuter 指向每個彙總層級的最外層專案子類型 IUnknown

範例

下列範例以 CreateAggregateProject 方法的近似表示形式詳細說明由環境實作的程式設計過程。 程式碼只是一個範例;未預期作為編譯用途,而且為了清楚起見,所有錯誤檢查都已刪除。

HRESULT CreateAggregateProject
(
    LPCOLESTR lpstrGuids,
    LPCOLESTR pszFilename,
    LPCOLESTR pszLocation,
    LPCOLESTR pszName,
    VSCREATEPROJFLAGS grfCreateFlags,
    REFIID iidProject,
    void **ppvProject)
{
    HRESULT hr = NOERROR;
    CComPtr<IUnknown> srpunkProj;
    CComPtr<IVsAggregatableProject> srpAggProject;
    CComBSTR bstrGuids = lpstrGuids;
    BOOL fCanceled = FALSE;
    *ppvProject = NULL;

    HrCreateInnerProj(
         bstrGuids, NULL, NULL, pszFilename, pszLocation,
         pszName, grfCreateFlags, &srpunkProj, &fCanceled);
    srpunkProj->QueryInterface(
        IID_IVsAggregatableProject, (void **)&srpAggProject));
    srpAggProject->OnAggregationComplete();
    srpunkProj->QueryInterface(iidProject, ppvProject);
}

HRESULT HrCreateInnerProj
(
    WCHAR *pwszGuids,
    IUnknown *pOuter,
    IVsAggregatableProject *pOwner,
    LPCOLESTR pszFilename,
    LPCOLESTR pszLocation,
    LPCOLESTR pszName,
    VSCREATEPROJFLAGS grfCreateFlags,
    IUnknown **ppInner,
    BOOL *pfCanceled
)
{
    HRESULT hr = NOERROR;
    CComPtr<IUnknown> srpInner;
    CComPtr<IVsAggregatableProject> srpAggInner;
    CComPtr<IVsProjectFactory> srpProjectFactory;
    CComPtr<IVsAggregatableProjectFactory> srpAggPF;
    GUID guid = GUID_NULL;
    WCHAR *pwszNextGuids = wcschr(pwszGuids, L';');
    WCHAR wszText[_MAX_PATH+150] = L"";

    if (pwszNextGuids)
    {
        *pwszNextGuids++ = 0;
    }

    CLSIDFromString(pwszGuids, &guid);
    GetProjectTypeMgr()->HrGetProjectFactoryOfGuid(
        guid, &srpProjectFactory);
    srpProjectFactory->QueryInterface(
        IID_IVsAggregatableProjectFactory,
        (void **)&srpAggPF);
    srpAggPF->PreCreateForOuter(pOuter, &srpInner);
    srpInner->QueryInterface(
        IID_IVsAggregatableProject, (void **)&srpAggInner);

    if (pOwner)
    {
        IfFailGo(pOwner->SetInnerProject(srpInner));
    }

    if (pwszNextGuids)
    {
        CComPtr<IUnknown> srpNextInner;
        HrCreateInnerProj(
            pwszNextGuids, pOuter ? pOuter : srpInner,
            srpAggInner, pszFilename, pszLocation, pszName,
            grfCreateFlags, &srpNextInner, pfCanceled);
    }

    return srpAggInner->InitializeForOuter(
        pszFilename, pszLocation, pszName, grfCreateFlags,
        IID_IUnknown, (void **)ppInner, pfCanceled);
}