Recently I wrote what many consider to be the most important Visual Studio Extension ever shipped - Encourage for Visual Studio. It was my humble attempt to make a small corner of the world brighter with little encouragements as folks work in Visual Studio. You can get it via the Visual Studio Extension Manager.

But not everyone has a sunny disposition like I do. Some folks want to watch the world burn. What they want is Discouragements.

Well an idiot might write a whole other Visual Studio Extension with a set of discouragements. I may be many things, but I am no idiot. This problem is better solved by allowing users to configure the set of encouragements to be anything they want.

And that’s what I did. I added an Options pane to allow users to configure the set of encouragements. It turned out to be a more confusing ordeal than I expected. But with some help from Jared Parsons, I may now present to you, discouragements!

Encourage options

So if you’re of the masochistic inclination, you can treat yourself to custom discouragements all day long if you so choose.

Discouragement in use

As you can see from the screenshot, it supports native emoji!. If you want these for yourself, I posted them into a gist.

Challenges and Travails

So why was this challenging? Well like many things with development platforms, to do the basic thing is really easy, but when you want to deviate, things become hard.

If you follow the Walkthrough: Creating an Options Page you’ll be able to add settings to your Visual Studio extension pretty easily. Using this approach, you can even rely on Visual Studio to generate a properties UI for you.

basic options

But that’s pretty rudimentary.

What I wanted was very simple, I wanted a multi-line text box that let you type in or paste in an encouragement per line. So I derived from DialogPage as you do, created a WPF User Control with a TextBox. I added the user control to an ElementHost, a Windows Forms control that can host a WPF control because, apparently, the Options dialog is still hosting Windows Forms controls.

This approach was easy enough, but the text box didn’t accept any of my input. I ran into the same problem as this person writes about StackOverflow.

I could cut and paste into the TextBox, but I couldn’t type anything. That’s not very useful.

I wasn’t interested in overriding WndProc mainly because I feel I shouldn’t have to. Instead I gave up on WPF, and ported it over to a regular Windows Forms user control. That allowed me to type in the textbox, but if I hit the Enter key, instead of adding a newline, the OK button stole it. So I couldn’t actually add more than one encouragement.


Thankfully, Jared pointed me to the UIElementDialogPage.

If you want to provide a WPF User Control for your Visual Studio Extension, derive from UIElementDialogPage and not DialogPage like all the samples demonstrate!

It does all the necessary WndProc magic under the hood for you. Note that it was introduced in Visual Studio 2012 so if you take a dependency on it, your extension won’t work in Visual Studio 2010. Live in the present I always say.

Storing Settings

The other thing I learned is that AppSettings is not the place to save your extension’s settings. As Jared explained,

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

If this is interesting to you, I encourage (tee hee) you to read through the Pull Request that adds settings to the Encourage pull request. You can read through the commits to watch me flailing around, or you can read the final DIFF to see what changes I had to make.

PS: If you liked this post follow me on Twitter for interesting links and my wild observations about pointless drivel