How to: 使用 Interop 組件匯出設定
VSPackage 可以匯出設定,從Visual Studio整合式的開發環境 (IDE)。 IDE 會使用 VSPackage 實作的IVsUserSettings介面。 如果封裝還提供IVsUserSettingsQuery介面,然後在IVsUserSettingsQuery介面用來判斷要如何儲存 VSPackage 的組態。
![]() |
---|
管理套件架構 (MPF) 提供一組受管理的類別,可讓您方便建立 Visual Studio 的副檔名。若要執行這項工作使用 MPF,請參閱How to: 使用受管理的封裝架構匯出設定。 |
若要實作在 VSPackage 上的設定匯出
實作基本支援Visual Studio設定的機制。
登錄 VSPackage 為支援的設定機制,藉由定義一或多個自訂設定的點。
如需詳細資訊,請參閱 保存的設定。
宣告會實作 VSPackage IVsUserSettings。 如有需要,也可以實作 VSPackage IVsUserSettingsQuery介面。 例如:
public class MyPackage : IVsPackage, IVsUserSettings, IVsUserSettingsQuery
確保 VSPackage 實作的QueryInterface方法提供IVsUserSettings介面的呼叫時IID_IVsUserSettings。
(選擇性) QueryInterface可以提供IVsUserSettingsQuery介面的呼叫時IID_IVsUserSettingsQuery介面。
STDMETHODIMP MyPackage::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj) { if (ppvObj == NULL) return E_POINTER; *ppvObj = NULL; if (riid == IID_IUnknown) *ppvObj = (LPVOID)(IUnknown *)(IClassFactory*)this; else if (riid == IID_IClassFactory) *ppvObj = (LPVOID)(IClassFactory *)this; else if (riid == IID_IVsPackage) *ppvObj = (LPVOID)(IVsPackage *)this; else if (riid == IID_IVsPersistSolutionOpts) *ppvObj = (LPVOID)(IVsPersistSolutionOpts *)this; else if (riid == IID_IVsPersistSolutionProps) *ppvObj = (LPVOID)(IVsPersistSolutionProps *)this; else if (riid == IID_IVsComponentSelectorProvider) *ppvObj = (LPVOID)(IVsComponentSelectorProvider *)this; else if (riid == IID_IVsUserSettings) *ppvObj = (LPVOID)(IVsUserSettings *)this; else if (riid == IID_IVsUserSettingsQuery) *ppvObj = (LPVOID)(IVsUserSettingsQuery *)this; if (*ppvObj) { AddRef(); return NOERROR; } return E_NOINTERFACE; }
此外,也可以提醒匯出特定的設定需要的 IDE。
VSPackage 可以條件式地儲存自訂設定點狀態定義的設定。 例如,儲存只有當使用者明確指出要儲存的設定。
如此一來, IVsUserSettingsQuery必須實作介面。
如果未實作的 VSPackage IVsUserSettingsQuery,其所有狀態資訊會都儲存在設定匯出過程。
VSPackage 可以支援一個以上的自訂設定端點 ([設定] 類別)。 實作NeedExport方法必須檢查提供的自訂設定的點 GUID] 或 [設定] 類別引數,來判斷特定群組的設定必須先儲存。
在下面範例中,VSPackage 會永遠要求會保留,其命令列的狀態,但只會儲存它的快速鍵繫結的狀態,已設定一個旗標,則會要求。
設定檔中寫入設定資料。
若要支援匯出的設定值,VSPackage 必須實作ExportSettings方法。
實作必須處理由 IDE 時,該自訂設定點類別的 GUID 傳入的引數和IVsSettingsWriter介面。
VSPackage 可以支援一個以上的自訂設定端點 ([設定] 類別)。 在 [範例所示, ExportSettings方法會呼叫要保存的命令列狀態保存的按鍵繫結狀態相較於不同的實作。
VSPackage 必須使用所提供IVsSettingsWriter介面,以將資料儲存至設定檔。
interface IVsSettingsWriter : IUnknown
{
HRESULT WriteSettingString( LPCOLESTR pszSettingName, LPCOLESTR pszSettingValue);
HRESULT WriteSettingLong( LPCOLESTR pszSettingName, long lSettingValue);
HRESULT WriteSettingBoolean( LPCOLESTR pszSettingName, BOOL fSettingValue);
HRESULT WriteSettingBytes( LPCOLESTR pszSettingName, BYTE *pSettingValue, long lDataLength);
HRESULT WriteSettingAttribute( LPCOLESTR pszSettingName, LPCOLESTR pszAttributeName, LPCOLESTR pszSettingValue);
HRESULT WriteSettingXml( IUnknown *pIXMLDOMNode);
HRESULT WriteSettingXmlFromString( LPCOLESTR szXML);
HRESULT ReportError( LPCOLESTR pszError, VSSETTINGSERRORTYPES dwErrorType);
};
值為pszSettingName引數提供給IVsSettingsWriter介面必須唯一地識別儲存某個設定分類在各資料元素。
注意事項
因為 IDE 會使用它的 GUID 及值,名稱必須是唯一的自訂設定點內pszSettingName來識別每一個儲存設定。如果多個IVsSettingsWriter會呼叫相同的值為pszSettingName,就會覆寫原來的值來設定檔中。
設定檔支援隨機資料存取。 因此,順序讀取和寫入設定作業並不重要。
所示的實作,匯出和匯入命令列的狀態 (ExportSettings_CommandBar 和ImportSettings_CommandBar) 例所示。
如果實作可以將資料對應到其中一個四個支援的格式,沒有任何限制,有關的很多,或可以撰寫哪些類型的資料。
注意事項
除了明確的書面且根本不需要的資料ExportSettings的實作中,設定 API 也會儲存Visual Studio版本資訊。針對這些設定匯入期間所產生的 ide 版本,就可以比較已儲存的設定。
範例
下列範例會示範如何匯入和匯出設定的資料。
// --------------------------------------------------------------------------
// IVsUserSettings methods used for configuration export.
// Delegate to the right shell object based on the category GUID.
// --------------------------------------------------------------------------
static const WCHAR c_szFirstSettingName[] = L"FirstSettingName";
static const WCHAR c_szRandomTrashBytes[] = L"RandomTrashBytes";
static const WCHAR c_szRandomTrashLength[] = L"RandomTrashLength";
static const WCHAR c_szBreakPointWindow[] = L"Breakpoints Window";
// Export Settings.
STDMETHOD(NeedExport)(WCHAR* pszCategoryGUID, BOOL *pfNeedExport)
{
if (!pfNeedExport)
return E_INVALIDARG;
CLSID clsidCategory;
HRESULT hr= S_OK;
hr = CLSIDFromString(pszCategoryGUID, &clsidCategory);
IfFailGo(hr);
if (GUID_Profiles_CommandBars == clsidCategory) {
*pfNeedExport = TRUE; //Always export Command Bar Configuration
}else if (GUID_Profiles_KeyBindings == clsidCategory) {
*pfNeedExport = FALSE; //By Default don't export key bindings
if (m_fMake_Permanent)
*pfNeedExport = TRUE; //Export if user wants current configuration saved.
}else{
hr = E_UNEXPECTED;
}
Error:
return hr;
}
STDMETHOD(ExportSettings)(WCHAR *pszCategoryGUID, IVsSettingsWriter *pSettings)
{
CLSID clsidCategory;
HRESULT hr;
hr = CLSIDFromString(pszCategoryGUID, &clsidCategory);
IfFailGo(hr);
// Delegate to the right internal implementation based on
// the requested category.
if (GUID_Profiles_CommandBars == clsidCategory) {
hr = ExportSettings_CommandBars(pSettings);
}else if (GUID_Profiles_KeyBindings == clsidCategory) {
hr = ExportSettings_KeyBindings(pSettings);
}else{
hr = E_UNEXPECTED;
}
Error:
return hr;
};
HRESULT ExportSettings_CommandBars(IVsSettingsWriter *pSettings)
{
if (!pSettings)
return E_INVALIDARG;
hr = pSettings->WriteSettingString(c_szFirstSettingName, L"Value1");
IfFailGo(hr);
int cRandomTrash = 12345;
BYTE *pRandomTrash = (BYTE *)VSAlloc(cRandomTrash);
if (pRandomTrash){
hr = pSettings->WriteSettingBytes(c_szRandomTrashBytes, pRandomTrash, cRandomTrash);
IfFailGo(hr);
hr = pSettings->WriteSettingLong(c_szRandomTrashLength, cRandomTrash);
IfFailGo(hr);
}
Error:
return hr;
};
HRESULT ExportSettings_KeyBindings(IVsSettingsWriter *pSettings)
{
if (!pSettings)
return E_INVALIDARG;
hr = pSettings->WriteSettingString(c_szBreakPointWindow, L"Ctrl + Alt + B");
IfFailGo(hr);
Error:
return hr;
};
STDMETHOD(ImportSettings)(WCHAR *pszCategoryGUID, IVsSettingsReader *pSettings, UserSettingsFlags flags, BOOL *pfRestartRequired)
{
CLSID clsidCategory;
HRESULT hr;
hr = CLSIDFromString(pszCategoryGUID, &clsidCategory);
IfFailGo(hr);
// Delegate to the right internal implementation based on
// the requested category.
if (GUID_Profiles_CommandBars == clsidCategory)
{
hr = ImportSettings_CommandBars(, pSettings, flags, pfRestartRequired);
}
else if (GUID_Profiles_KeyBindings == clsidCategory)
{
hr = ImportSettings_KeyBindings( pSettings, flags, pfRestartRequired);
}
else
{
hr = E_UNEXPECTED;
}
Error:
return hr;
};
// Import Settings.
HRESULT ImportSettings_CommandBars(IVsSettingsReader *pSettings, UserSettingsFlags flags, BOOL *pfRestartRequired)
{
if (!pSettings)
return E_INVALIDARG;
if (pfRestartRequired)
{
*pfRestartRequired = FALSE; //Nobody should require a restart!!
}
CComBSTR bstrFirstSettingName;
long lTrashLength = 0;
BYTE *pTrashBytes = NULL;
// Determines whether to treat import as an additive operation, or a reset all settings operation.
BOOL fResetCompletely = FALSE;
if (flags & USF_ResetOnImport)
fResetCompletely = TRUE;
hr = pSettings->ReadSettingString(c_szFirstSettingName, &bstrFirstSettingName);
IfFailGo(hr);
hr = pSettings->ReadSettingLong(c_szRandomTrashLength, &lTrashLength);
IfFailGo(hr);
if (lTrashLength > 0)
{
pTrashBytes = (BYTE*)VSAlloc(lTrashLength);
IfNullMemGo(pTrashBytes);
long lDataRead = 0;
hr = pSettings->ReadSettingBytes(c_szRandomTrashLength, pTrashBytes, &lDataRead, lTrashLength);
IfFailGo(hr);
if (lDataRead != lTrashLength)
{
hr = E_UNEXPECTED;
goto Error;
}
}
// Note: before returning, these settings should immediately
// be applied to your personal settings store,
// whether in the registry or the file system.
// This write-through cache methodology is essential to to work
// in multi-instance IDE scenarios.
hr = UpdateState_CommandBar(bstrFirstSettingName,lTrashLength,pTrashBytes,lDataRead);
Error:
return hr;
};
HRESULT ImportSettings_KeyBindings(IVsSettingsReader *pSettings, UserSettingsFlags flags, BOOL *pfRestartRequired)
{
if (!pSettings)
return E_INVALIDARG;
if (pfRestartRequired)
{
*pfRestartRequired = FALSE; //Nobody should require a restart!!
}
CComBSTR bstrBreakPointWindow;
// Determines whether import can be treated as an additive
// operation, or a reset all settings operation.
BOOL fResetCompletely = FALSE;
if (flags & USF_ResetOnImport)
fResetCompletely = TRUE;
hr = pSettings->ReadSettingString(c_szBreakPointWindow, &bstrBreakPointWindow);
IfFailGo(hr);
// Note: Before returning, these settings should immediately
// be applied to your personal settings
// store, whether in the registry or the file system.
// This write-through cache methodology is essential to allow us
// to work in multi-instance IDE scenarios.
hr = UpdateState_KeyBindings(bstrBreakPointWindow);
Error:
return hr;
}