how - Where should a Visual Studio Add-in store its settings?

visual studio window title changer (2)

Currently I'm storing the settings for my custom addins in the registry but this seems like a kludge. I was wondering if there was an official place to store add-in settings. My preference would be to store them where Visual studio stores settings so they can be exported and imported easily.

Is it possible to store add-in settings with Visual Studio settings or is there a better way?


My original answer to this topic had a couple of issues I discovered after years of using it. I've included it below for completeness but here is my updated thoughts on this.

The use of application settings is not version safe in a VSIX. The location of the stored setting file path in part includes the version string and hashes of the executable. When Visual Studio installs an official update these values change and as a consequence change the setting file path. Visual Studio itself doesn't support the use of application settings hence it makes no attempt to migrate this file to the new location and all information is essentially lost. The supported method of settings is the WritableSettingsStore. It's very similar to application settings and easy enough to access via SVsServiceProvider

public static WritableSettingsStore GetWritableSettingsStore(this SVsServiceProvider vsServiceProvider)
    var shellSettingsManager = new ShellSettingsManager(vsServiceProvider);
    return shellSettingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);

Original Answer

The most straight forward way is to use .Net's Application Settings infrastructure to store any settings. It's a mature framework with designer support for adding a settings infrastructure to your project.

It however does not integrate with Visual Studio's Import / Export settings infrastructure. Getting that working is a very involved process that includes registering yourself as a VSPackage, implementing a settings schema, etc ... I generally find it's really not worth the trouble of getting running (never succeeded)

Here is a quick tutorial that may give you an idea of how to achieve this simply (it is quite straightforward once you have done it once).

I have derived the below code from what I use in my extensions; it is in VB.NET, but can be easily converted to C#.

To start, simply add this class to your extension project. It should contain a property for each value you need to store. You can even arrange them in categories. You may have a look at MSDN here for supported types (for more complex cases you may refer to "customized option pages", which is a topic covered by MSDN here).

Imports Microsoft.VisualBasic
Imports System
Imports System.Diagnostics
Imports System.Globalization
Imports System.Runtime.InteropServices
Imports System.ComponentModel.Design
Imports Microsoft.Win32
Imports Microsoft.VisualStudio
Imports Microsoft.VisualStudio.Shell.Interop
Imports Microsoft.VisualStudio.OLE.Interop
Imports Microsoft.VisualStudio.Shell
Imports System.Threading
Imports System.Text.RegularExpressions
Imports System.ComponentModel

<CLSCompliant(False), ComVisible(True)>
Public Class OptionPageGrid
    Inherits DialogPage

    Private _MyBooleanSetting As Boolean = False
    <Category("The name or an alias of my extension name")>
    <DisplayName("Simple name of this setting displayed for the user")>
    <Description("Longer description of this setting")>
    Public Property MyBooleanSetting() As Boolean
            Return Me._MyBooleanSetting
        End Get
        Set(ByVal value As Boolean)
            Me._MyBooleanSetting = value
        End Set
    End Property

    Private _MyIntegerSetting As Integer = 2
    <Category("The name or an alias of my extension name")>
    <DisplayName("Simple name of this setting displayed for the user")>
    <Description("Longer description of this setting")>
    Public Property MyIntegerSetting() As Integer
            Return Me._MyIntegerSetting
        End Get
        Set(ByVal value As Integer)
            Me._MyIntegerSetting = value
        End Set
    End Property

    Private _MyStringSetting As String = "DefaultStringValue"
    <Category("The name or an alias of my extension name")>
    <DisplayName("Simple name of this setting displayed for the user")>
    <Description("Longer description of this setting")>
    Public Property MyStringSetting() As Integer
            Return Me._MyStringSetting
        End Get
        Set(ByVal value As Integer)
            Me._MyStringSetting = value
        End Set
    End Property
End Class

Then, add the following attributes just before your master package class.

<ProvideOptionPage(GetType(OptionPageGrid), "The name or an alias of my extension name", "The name of a category of settings", 0, 0, True)>
Public NotInheritable Class MyExtensionMainClass
    Inherits Package

Now to easily access the settings, you may add the following property in your master package class:

Protected ReadOnly Property Settings() As OptionPageGrid
        Return CType(GetDialogPage(GetType(OptionPageGrid)), OptionPageGrid)
    End Get
End Property

This makes it possible to access a value from anywhere in the class using a friendly:

If (Me.Settings.MyBooleanSetting) Then MsgBox("It works!");

Visual Studio will take care of persisting the settings, and they should be included when you use the import/export function (or any settings synchronization extension like this one).