Walkthrough: Using the Settings Store
Although Visual Studio settings are typically persisted in the system registry, you can decouple setting storage from the registry by using a settings store. Using the settings store instead of the registry simplifies deployment and promotes security.
There are two kinds of settings stores:
Configuration settings, which are read-only Visual Studio and VSPackage settings. Visual Studio merges settings from all known .pkgdef files into this store.
User settings, which are writeable settings such as those that are displayed on pages in the Options dialog box, property pages, and certain other dialog boxes. Visual Studio extensions may use these for local storage of small amounts of data.
This walkthrough shows how to use both kinds of setting stores.
Creating the Example Project
This section shows how to create a basic settings store project.
To create the example project
Create a Visual Studio Package project named SettingsStorage.
For more information about how to create a managed VSPackage, see Walkthrough: Creating a Menu Command By Using the Visual Studio Package Template.
On the Select a Programming Language page, select Visual C#.
On the Select VSPackage Options page, select Menu Command.
On the Command Options page, change the Command name to Settings Storage and the Command ID to cmdidSettingsStorage.
On the Select Test Options page, clear both check boxes and then click Finish.
Press F5 to run the experimental instance of Visual Studio.
In the experimental instance, on the Tools menu, click Settings Storage.
The following message should be displayed.
Inside Microsoft.SettingsStorage.SettingsStoragePackage.MenuItemCallback().
Close the experimental instance.
There are several ways to output text from a VSPackage. This walkthrough shows how to modify the SettingsStoragePackage.MenuItemCallback method to display the results of each of the following sets of steps.
Using the Configuration Settings Store
This section shows how to use various SettingsManager and SettingsStore methods to detect and display configuration settings.
To use the configuration settings store
Open the SettingsStoragePackage.cs file in the code editor.
Add these lines to the beginning of the file:
using System.Collections.Generic; using Microsoft.VisualStudio.Settings; using Microsoft.VisualStudio.Shell.Settings;
Add these lines to the start of the MenuItemCallback method:
SettingsManager settingsManager = new ShellSettingsManager(this); SettingsStore configurationSettingsStore = settingsManager.GetReadOnlySettingsStore(SettingsScope.Configuration);
This calls the ShellSettingsManager constructor, and passes a reference to the VSPackage itself as the IServiceProvider parameter. The constructor returns a SettingsManager object. The GetReadOnlySettingsStore method returns a SettingsStore object named ConfigurationSettingsStore. Use this object to read the configuration settings.
Add these lines after the lines in the previous step:
bool isVisualWebDevInstalled = configurationSettingsStore.CollectionExists("InstalledProducts\\Visual Web Developer"); string message = "Visual Web Developer Installed: " + isVisualWebDevInstalled;
This searches the configuration settings store for the collection InstalledProducts that has the subcollection Visual Web Developer. If the subcollection is found, the message string is set to "True"; otherwise, it is set to "False".
In the MessageBox call, replace the parameter value "SettingsStorage" with the name "message". The MenuItemCallback method should now resemble this:
private void MenuItemCallback(object sender, EventArgs e) { SettingsManager settingsManager = new ShellSettingsManager(this); SettingsStore configurationSettingsStore = settingsManager.GetReadOnlySettingsStore(SettingsScope.Configuration); bool isVisualWebDevInstalled = configurationSettingsStore.CollectionExists("InstalledProducts\\Visual Web Developer"); string message = "Visual Web Developer Installed: " + isVisualWebDevInstalled; IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); Guid clsid = Guid.Empty; int result; Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure( uiShell.ShowMessageBox(0 ref clsid, message, // was "SettingsStorage", string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.ToString()), string.Empty, 0, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, OLEMSGICON.OLEMSGICON_INFO, 0, // false out result)); }
Press F5 to run the experimental instance of Visual Studio.
In the experimental instance, on the Tools menu, click Settings Storage.
A message should be displayed and contain the text Visual Web Developer Installed: followed by True or False.
Close the experimental instance.
Visual Studio implements the settings store in the system registry. Because of this, you can use a registry editor, for example, Regedit.exe, to verify configuration and user settings.
To use a registry editor to verify configuration settings
Open Regedit.exe or another registry editor.
Navigate to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0Exp_Config\InstalledProducts\.
Note
Make sure that you are looking at the key that contains \12.0Exp_Config\ and not \12.0_Config\. When you run the experimental instance of Visual Studio, configuration settings are in the registry hive "12.0Exp_Config".
Expand the \Installed Products\ node. If the message in the previous steps is Visual Web Developer Installed: True, then \Installed Products\ should contain a Visual Web Developer node. If the message is Visual Web Developer Installed: False, then \Installed Products\ should not contain a Visual Web Developer node.
You can also use the CollectionExists method to determine whether a particular service is installed. You must know the type of the service class.
To determine whether a service is available
In the code, replace the IsVisualWebDevInstalled and message assignment statements with the following lines.
string helpServiceGUID = typeof(SVsHelpService).GUID.ToString("B").ToUpper(); bool hasHelpService = configurationSettingsStore.CollectionExists("Services\\" + helpServiceGUID); string message = "Help Service Available: " + hasHelpService;
This searches the configuration settings store for the collection Services that has the subcollection named by the GUID of the service. If the subcollection is found, the message string is set to "True"; otherwise, it is set to "False".
Press F5 to run the experimental instance of Visual Studio.
In the experimental instance, on the Tools menu, click Settings Storage.
A message should be displayed and contain the text Help Service Available: followed by True or False. To verify this setting, you can use a registry editor, as shown in the earlier steps.
Close the experimental instance.
You can also use the GetSubCollectionNames and GetString methods to list the services that are registered in the configuration settings store.
To list the available services
Replace the code in the previous steps with the following lines.
string message = "First five services:\n"; IEnumerable<string> collection = configurationSettingsStore.GetSubCollectionNames("Services"); int n = 0; foreach (string service in collection) { if (n++ == 5) break; message += configurationSettingsStore.GetString("Services\\" + service, "Name", "Unknown") + "\n"; }
The GetSubCollectionNames method call gets the names of the members of the Services collection. The GetString method call returns the Name property data of each member. If the Name property does not exist, the default name "Unknown" is returned. The resulting names are appended to the message string.
Press F5 to run the experimental instance of Visual Studio.
In the experimental instance, on the Tools menu, click Settings Storage.
The following message should be displayed:
"First five services: PL/SQLTypeSystemMicrosoft Visual Basic CompilerSTestExecutionServiceResXRefactor Notify Service"
Your list of services may differ. To verify these settings, you can use the registry editor.
Close the experimental instance.
You can reset the configuration settings by using the following procedure.
To reset the configuration settings
In Windows 7, on the Start menu, in the Microsoft Visual Studio/Microsoft Visual Studio SDK/Tools folder, choose Reset the Microsoft Visual Studio Experimental Instance.
In Windows 8.1, on the Start screen, type Reset the Visual Studio <version> Experimental Instance.
A command window appears. Wait until Press any key to continue is displayed, and then press a key to close the command window.
Using the User Settings Store
This section shows how to add Notepad to Visual Studio as an external tool by reading from and writing to the user settings store.
So that you can debug and repeat this installation, you must be able to reset the External Tools settings. To do this, you must save the original settings so that you can restore them as required.
To save the External Tools settings
Open Regedit.exe or another registry editor.
Navigate to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0Exp\External Tools\.
Note
Make sure that you are looking at the key that contains \10.0Exp\ and not \10.0\. When you run the experimental instance of Visual Studio, your user settings are in the registry hive "10.0Exp".
Right-click the \External Tools\ subkey, and then click Export. Make sure that Selected branch is selected.
Save the resulting External Tools.reg file.
To restore the External Tools settings
Right-click the \External Tools\ registry subkey, and then click Delete.
When the Confirm Key Delete dialog box appears, click Yes.
Right-click the External Tools.reg file, click Open with, and then click Registry Editor.
Various SettingsManager and WritableSettingsStore methods are used to detect and modify user settings.
To use the user settings store
Open the SettingsStoragePackage.cs file in the code editor.
In the MenuItemCallback method, add this line of code just after the ConfigurationSettingsStore assignment statement:
WritableSettingsStore userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);
The GetWritableSettingsStore method call returns a WritableSettingsStore object named userSettingsStore. You will use this object to read and write the user settings.
After the lines in the previous step, add this line:
int toolCount = userSettingsStore.GetInt32("External Tools", "ToolNumKeys");
The GetInt32 method call searches the user settings store for the collection External Tools and returns the data of the ToolNumKeys property as an integer. This is the number of external tools already installed.
After the lines in the previous step, add these lines:
bool hasNotepad = false; CompareInfo Compare = CultureInfo.InvariantCulture.CompareInfo; for (int i = 0; i < toolCount; i++) { if (Compare.IndexOf(userSettingsStore.GetString("External Tools", "ToolCmd" + i), "Notepad", CompareOptions.IgnoreCase) >= 0) { hasNotepad = true; break; } }
The successive GetString method calls return the data of the properties ToolCmd0, ToolCmd1, and so forth. Each property data is the path of an external tool. The IndexOf method call performs a case-insensitive search of the command path for the string "Notepad". If found, hasNotepad is set to true; otherwise, it remains false.
After the lines in the previous step, add the following lines and replace the message string assignment statement and all other statements through the end of the foreach loop.
string message = (hasNotepad) ? "Notepad already installed" : "Installing Notepad"; if (!hasNotepad) { userSettingsStore.SetString("External Tools", "ToolTitle" + toolCount, "&Notepad"); userSettingsStore.SetString("External Tools", "ToolCmd" + toolCount, "C:\\Windows\\notepad.exe"); userSettingsStore.SetString("External Tools", "ToolArg" + toolCount, ""); userSettingsStore.SetString("External Tools", "ToolDir" + toolCount, "$(ProjectDir)"); userSettingsStore.SetString("External Tools", "ToolSourceKey" + toolCount, ""); userSettingsStore.SetUInt32("External Tools", "ToolOpt" + toolCount, 0x00000011); userSettingsStore.SetInt32("External Tools", "ToolNumKeys", toolCount + 1); }
This code uses the SetString and SetUInt32 methods to create the various properties that install Notepad as an external tool. Notepad is given the access key "N" and the project directory as the starting directory. Finally, the number of external tools is incremented and written back to the user settings store.
The external tool Notepad is now available for testing.
To test the external tool setup
Press F5 to run the experimental instance of Visual Studio.
In the experimental instance, on the Tools menu, click Settings Storage.
A message should be displayed and contain the text Installing Notepad. Click OK.
On the Tools menu, click Notepad.
Notepad opens.
After Notepad opens, close it.
On the Tools menu, click Notepad again.
A message should be displayed and contain the text Notepad already installed.
Close Notepad, and then close the experimental instance.
To repeat this test, first restore the affected user settings, as described earlier in "To restore the External Tools settings".
Using the Settings Store from Another Process
This walkthrough first showed how to create a settings manager (SettingsManager object), by using the VSPackage itself as a service provider.
SettingsManager settingsManager = new ShellSettingsManager(this);
VSPackages run in the same process as Visual Studio, but you can also access the settings store from another process by using the ExternalSettingsManager class.
To create a settings manager from another process, call the CreateForApplication method, and pass it the full path of the Visual Studio executable (devenv.exe). Because Visual Studio does not have a predetermined location, you must examine the system registry to find the path. This information is located in the HKLM\SOFTWARE\Microsoft\VisualStudio\version\InstallDir\ subkey.
For example, to access the settings store for Visual Studio 2013, examine HKLM\SOFTWARE\Microsoft\VisualStudio\12.0\InstallDir\.
Note
For a Windows 64-bit operating system, this subkey is HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\InstallDir\.
The data of the Visual Studio 2013 \InstallDir\ property is typically C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\.
Note
For a Windows 64-bit operating system, this data is typically C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\.
The full path is created by appending devenv.exe to this data, for example,
string AppIDPath = "C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe"
Finally, call CreateForApplication to create the settings manager.
SettingsManager settingsManager = ExternalSettingsManager.CreateForApplication(AppIDPath);