How to: Export Settings Using the Managed Package Framework

The Visual Studio integrated development environment (IDE) uses classes that implement the IProfileManager interface and classes that are registered as supporting a given VSPackage implementation to save the state of a VSPackage.

Because the IDE instantiates the class implementing the IProfileManager interface to support the settings, IProfileManager should be implemented in an independent class.

注意

Do not implement IProfileManager on the class implementing Package.

To implement export of settings

  1. Declare the class that implements the Visual Studio settings.

    Declare a class as implementing the IProfileManager interface and provide it with a GUID.

    注意

    Classes that implement IProfileManager must also implement IComponent, which can be done by deriving the class from Component.

    For example:

    [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
    internal class MyPackageProfileManager : Component, IProfileManager 
    
  2. Ensure that the class that implements the settings obtains correct state information. This procedure is specific to each VSPackage, and may involve obtaining state from automation, querying registry keys, or querying the VSPackage.

    Typically, as in the example below, use the implementation of the LoadSettingsFromStorage method to validate and stage VSPackage state information.

    注意

    The LoadSettingsFromStorage method is also called by the IDE during its initialization of the VSPackage that it supports.

    In this case, the implementation of the LoadSettingsFromStorage method:

    • Obtains access to the state information in the VSPackage's current configuration and configuration information stored in the registry.

      MyPackageService mySvc = GetService(typeof(IVSMDMyPackage)) as MyPackageService;
      Package package = GetService(typeof(Package)) as Package;
      RegistryKey rootKey = package.UserRegistryRoot;
      
    • Depending on the value returned by the VSPackage's MakeCurrentSettingTheDefault it either updates the registry settings with the current VSPackage state or the VSPackage's state with the registry settings.

      if (mySvc.MyPackage.MakeCurrentSettingTheDefault()){
        ((IComPropertyBrowser)mySvc.MyPackage.packageState).SaveState(pbrsKey);
      }else{
        ((IComPropertyBrowser)mySvc.MyPackage.packageState).LoadState(pbrsKey);
      }
      

      For simplicity in this example, unless the VSPackages MakeCurrentSettingsTheDefault method returns true, the current state is always reset to the default stored in the registry.

  3. Ensure that the class that implements the settings also persists the state to disk.

    The actual writing of state information to the settings disk file must always be performed by the class's implementation of the SaveSettingsToXml method. The specifics of a settings writer operation depend on the implementation.

    However the class must obtain access to state information and must use the supplied IVsSettingsWriter interface to save data to the setting file.

    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);
    };
    

    Typically, as in the example below, the implementation of the SaveSettingsToXml method does not validate state information. The validation is performed in the LoadSettingsFromStorage method. Instead the implementation merely obtains access to the state information and writes it, in this case as string data:

    MyPackageService mySvc = GetService(typeof(MyPackage)) as MyPackageService;
    if (mySvc != null) {
      // Information is stored in a StateObject
      StateObject myState = mySvc.MyPackage.packageState;
     writer.WriteSettingString( 
                                "PbrsAlpha", 
                                (myState.SortState == SortState.Alphabetical ? "1" : "0"));
      writer.WriteSettingString( 
                                "PbrsShowDesc", 
                                (myState.HelpVisible ? "1" : "0"));
    }
    

    Implementation Details:

    • In addition to data explicitly written and transparent to the ExportSettings method implementation, the settings API also saves Visual Studio version information. Consequently, saved settings can be compared against the version of the IDE that generated them during settings import.

    • The value of the pszSettingName argument supplied to a method of the IVsSettingsWriter interface must uniquely identify each data element saved within a settings category.

      注意

      Names need only be unique within the scope of the implementing class. The IDE uses GUID of the class that implements the settings and the value of pszSettingName to identify each saved setting. If more than one IVsSettingsWriter method is called with the same value of pszSettingName, the original value is overwritten in the settings file.

    • The settings file supports random data access, so the order of read and write operations is not important. In the example below, the order of writer operations in the implementation of the SaveSettingsToXml method is opposite of the read operations in the LoadSettingsFromXml method.

    • If the implementation can map data into one of the four supported formats, then there is no restriction on how much or what type of data can be written.

      注意

      The division of labor between the LoadSettingsFromStorage and SaveSettingsToXml methods depends on the implementation and is somewhat arbitrary. For example the implementation could be rewritten with an empty implementation of the LoadSettingsFromStorage method and all registry and state queries performed in the SaveSettingsToXml method.

  4. Register the settings implementing class as providing support to a VSPackage.

    Apply an instance of ProvideProfileAttribute that is constructed by using the Type of the class that implements IProfileManager to the VSPackage's Package implementation.

    [ProvideProfile(typeof(MyPackageProfileManager), "CoreUI", "MyPackage", 1004, 1004, false)]
    [Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY")]
    class MyPackage: Package 
    

    In this case, the attribute informs the IDE that the MyPackageProfileManager class provides a settings implementation to the MyPackage class. The Custom Settings Point in the registry is created under HKLM\Software\Microsoft\VisualStudio\<Version>\UserSettings\ CoreUI_MyPackage, where <Version> is the version of Visual Studio, for example 8.0.

    For more information, see Persisting Settings and ProvideProfileAttribute.

Example

The following example implements IProfileManager on a class.

namespace myProfileManagerNameSpace  {
  
  using System;
  using System.Runtime.InteropServices;
  using Microsoft.VisualStudio.Shell;
  using Microsoft.VisualStudio.Shell.Interop;
  using Microsoft.Win32;
  using myPackageNameSpace;
  
  
  [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
  internal class MyPackageProfileManager : System.ComponentModel.Component , IProfileManager {
    internal const int m_supportVer = 8;
    public void SaveSettingsToXml(IVsSettingsWriter writer) {
      MyPackageService mySvc = GetService(typeof(MyPackage)) as MyPackageService;
      if (mySvc != null) {
        // Information is stored in a StateObject.
        StateObject myState = mySvc.MyPackage.packageState;
        writer.WriteSettingString( 
                                  "PbrsAlpha", 
                                  (myState.SortState == SortState.Alphabetical ? "1" : "0"));
        writer.WriteSettingString( 
                                  "PbrsShowDesc", 
                                  (myState.HelpVisible ? "1" : "0"));
      }
    }
    
    public void LoadSettingsFromXml(IVsSettingsReader reader)
    {
      
      int pnMajor, pnMinor, pnBuild;
      // First, check if data is obtained from the correct major version 
      reader.ReadVersion(pnMajor, pnMinor, pnBuild);
      if (pnMajor != m_supportVer){
        reader.ReportError("Unsupported Version");
      }else{
        MyPackageService mySvc = GetService(typeof(IVSMDMyPackage)) as MyPackageService;
        if (mySvc != null){
          string value;
          StateObject myState = mySvc.MyPackage.packageState;
          reader.ReadSettingString("PbrsShowDesc", out value);
          // Not all values must be present.
          if (value == null || value == ""){
              reader.ReportError("Unable to Help Visibility Setting");
          }else{
            myState.HelpVisible = !value.Equals("0");
          }
          reader.ReadSettingString("PbrsAlpha", out value);
          // Not all values must be present.
          if (value == null || value == ""){
              reader.ReportError("Unable to Retrieve Sort Value");
          }else{
            if (!value.Equals("0")){
              myState.SortState = SortState.Alphabetical;
            }else{
              myState.SortState = SortState.Categorized;
            }
          }
        }
      }
    }

    public void SaveSettingsToStorage() {
      MyPackageService mySvc = GetService(typeof(IVSMDMyPackage)) as MyPackageService;
      Package package = GetService(typeof(Package)) as Package;
      RegistryKey rootKey = package.UserRegistryRoot;
      
      if (mySvc.MyPackage.packageState != null) {
        using (rootKey) {
          using(RegistryKey pbrsKey = rootKey.CreateSubKey(this.GetType().Name)) {
            using (pbrsKey) {
              ((IComPropertyBrowser)mySvc.MyPackage.packageState).SaveState(pbrsKey);
            }
          }
        }
      }
    }
    
    public void LoadSettingsFromStorage() {
      MyPackageService mySvc = GetService(typeof(IVSMDMyPackage)) as MyPackageService;
      Package package = GetService(typeof(Package)) as Package;
      RegistryKey rootKey = package.UserRegistryRoot;
      using (rootKey) {
        RegistryKey pbrsKey = rootKey.OpenSubKey(this.GetType().Name);
        if (pbrsKey != null) {
          using (pbrsKey) {
            if (mySvc.MyPackage.MakeCurrentSettingTheDefault()){
              ((IComPropertyBrowser)mySvc.MyPackage.packageState).SaveState(pbrsKey);
            }else{
              ((IComPropertyBrowser)mySvc.MyPackage.packageState).LoadState(pbrsKey);
            }
          }
        }
      }
    }
  }
}

See Also

Concepts

How to: Import Settings Using the Managed Package Framework

Persisting Settings

Reference

IProfileManager

IVsSettingsWriter