How to: 使用 Interop 組件匯入設定
VSPackage 可匯入設定值來源Visual Studio整合式的開發環境 (IDE)。 IDE 會使用 VSPackage 實作的IVsUserSettings介面,以決定要如何擷取 VSPackage 的組態。
注意事項 |
---|
管理套件架構 (MPF) 提供一組受管理的類別,可讓您方便建立 Visual Studio 的副檔名。若要執行這項工作使用 MPF,請參閱How to: 使用受管理的封裝架構來匯入設定。 |
若要實作在 VSPackage 上的設定匯入
實作基本支援Visual Studio設定的機制。
登錄 VSPackage 為支援的設定機制,藉由定義一或多個自訂設定的點。
如需詳細資訊,請參閱 保存的設定。
宣告會實作 VSPackage IVsUserSettings介面,舉個例說:
public class MyPackage : IVsPackage, IVsUserSettings, IVsUserSettingsQuery
確保 VSPackage 實作的QueryInterface方法提供IVsUserSettings介面的呼叫時IID_IVsUserSettings。 例如:
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; }
擷取設定資訊。
若要支援擷取設定資訊,就必須實作 VSPackage ImportSettings方法。
若要讀取的資料,VSPackage 實作的IVsUserSettings介面必須使用兩個 ide 傳入的引數: 該自訂設定點類別的 GUID 及IVsSettingsReader介面。
實作 VSPackage ImportSettings方法必須檢查傳入的 GUID] 類別,然後選擇正確的機制,來擷取狀態。
在 [範例所示, ImportSettings方法會呼叫不同的實作來擷取命令列狀態,相較於擷取索引鍵繫結狀態。
VSPackage 必須使用所提供IVsSettingsReader介面,以擷取設定檔的資料。
注意事項 如果此類設定變更為函式的Visual Studio版本、 VSPackage 實作的ImportSettings的方法必須使用ReadFileVersion才能讀取資料,以檢查 IDE 版本的方法。
此介面提供方法來讀取設定檔中的不同資料型別。
interface IVsSettingsReader : IUnknown
{
HRESULT ReadSettingString(WCHAR *pszSettingName, BSTR *pbstrSettingValue);
HRESULT ReadSettingLong(WCHAR *pszSettingName, long *plSettingValue);
HRESULT ReadSettingBoolean(WCHAR *pszSettingName, BOOL *pfSettingValue);
HRESULT ReadSettingAttribute(LPCOLESTR pszSettingName,LPCOLESTR pszAttributeName, BSTR *pbstrSettingValue); //Internal use only
HRESULT ReadSettingBytes(WCHAR *pszSettingName, BYTE *pSettingValue, long *plDataLength, long lDataMax);
HRESULT ReadVersion(int *pnMajor, int *pnMinor, int *pnBuild);
HRESULT ReportError(WCHAR *pszError);
};
設定檔支援隨機資料存取,因此順序讀取及寫入 [設定作業並不重要。
說明這一點的匯出和匯入命令列的狀態 (ExportSettings_CommandBar 和ImportSettings_CommandBar) 的下面這個範例中的實作。
驗證擷取的資料。
可以手動編輯的 XML 檔案中包含的設定資訊。
安全性提示 |
---|
設定資訊可能會損毀磁碟上,可以包含版本特有的設定,而且可用來做為一種工具,惡意的攻擊。每個所傳回的資料項目的有效性IVsSettingsReader應該驗證方法。 |
若要確認支援版本的Visual Studio用來產生擷取的設定,呼叫ReadFileVersion方法來擷取版本。
若要引發通知使用者並不會驗證匯入的資料元素的 IDE,呼叫 VSPackage ReportError方法。
套用設定的資訊。
實作ImportSettings方法必須遵守 IDE 傳遞給它的第三個引數的值。 支援的值屬於__UserSettingsFlags列舉型別。 如需詳細資訊,請參閱 __UserSettingsFlags。
下面的命令列設定的匯入的實作範例 (ImportSettings_Commandbar) 來決定是否要套用覆寫現有的值,或 additively 會自動更新這些設定會使用此引數的值。
套用匯入設定時,您就必須實作一套寫出快取的方法。
必須同時更新登錄或檔案系統中的狀態資訊,如設定適用於 IDE。 這可確保設定的一致性,並支援多個執行個體 IDE 案例。
警示 IDE 設定匯入的處理方式。
使用傳回pfRestartRequired引數的ImportSettings ,如果重新啟動電腦,才能套用匯入的設定 [宣布 IDE 的方法。
如果實作 VSPackage ImportSettings方法傳回true,系統會提示使用者重新啟動 IDE。
範例
本範例將示範如何匯入和匯出設定的資料。
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";
// --------------------------------------------------------------------------
// IVsUserSettings methods used for configuration export and import
// 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 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-thru cache methodology is essential 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 to import 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-thru cache methodology is essential to work in multi-instance IDE scenarios.
hr = UpdateState_KeyBindings(bstrBreakPointWindow);
Error:
return hr;
}