A Visual Studio extension to really clean your projects

Akos Nagy
Oct 26, 2021

During one of my C#-.NET courses, one of the participants was complaining how the "Clean solution" option of Visual Studio doesn't actually clean the solution. That is, it doesn't delete the bin and obj folders.

And he was entirely right, and he was not alone with his frustration, so there are extensions in the marketplace to solve this problem. Unfortunately, I didn't like most of them:

  • This one by Mads Kristensen is (like everything else by Mads Kristensen) is super awesome. But to be honest, this is a bit too much for me. I just wanted something simple that deletes the unnecessary build outputs.
  • This one and this one are kinda good, but I'm not sure if they have keybindings set up and I also don't want to have a menu option, it's hard enough to find anything in the menus as they are. I wanted to have something as a context menu option for my solution and my projects.

So I came up with my own implementation as a fun weekend-project. You can go ahead and download it from the marketplace or check out the Github repo for the source. But if you are interested what I have actually created and the most important points of how, read on.

Designing the extension

So here are my key points for the extension:

  • Should add a new option to delete the bin and obj folders of projects for the project context menu.
  • Should add a new option to delete the bin and obj folders of every project and the packages folder of the solution to the solution context menu.
  • The one for the solution should have a key binding. The one for the projects probably won't be used that often, I let that go.
  • Should display the deleted folders or any error messages in the "General" pane of the output window.

Get cracking

I already have some extensions in the Visual Studio marketplace (and I have a couple more coming the next few weeks, so stay tuned), so I was familiar with most of the API. You can check out the full source on Github — here's the gist of what I have learnt with this project:

Adding keybindings

Turns out that adding keybindings are pretty easy. You have to specify the right XML in the vsct file of the project:

  <KeyBinding guid="guidCleanSolutionCommandPackageCmdSet"
              id="CleanSolutionCommandId" editor="guidVSStd97" 
              key1="VK_DELETE"  mod1="Control Shift"  />    

The editor value of a magic value that I have copied over from the documentation. It shows that this binding is availiable all-througout the IDE. The others are pretty self explanatory. The only that got me is that if you want to have a keybinding like this, you have to specify the two modifier keys with this syntax in the mod1 attribute, instead of setting mod1 and mod2 separately.

Writing to the output window

I have never written to the output window before. Most of the extensions that I have created communicated with the user via their own UI, so this was also something new to me.

So inside the AsyncPackage implementation of your extension, you can get the right service that you need. It's actually pretty simple, copied it over from the documentation:

(IVsOutputWindowPane)await GetServiceAsync(typeof(SVsGeneralOutputWindowPane));

That's the magic line that you need. The SVsGeneralOutputWindowPane magic type came from the documentation, the GetServiceAsync fmethod is of course what you use to get the IDE services. With the result of this, now you can write to the "General" pane of the output window using the OutputString(), or better yet, the OutputStringThreadSafe() methods.

And when that's done, you'll get the new options on your context menus:

So go ahead and grab it from the markeplace here. If you find any bugs or have any ideas, you're welcome to brainstorm on the Github repo.

Akos Nagy
Software engineer, software architect, software craftsman. .NET-enthusiast, Azure-fan, Javascript-hater. Amateur athlete.