PS for .NET devs part 5: Extending Visual Studio using StudioShell

Posted on Dec 19, 2011

In a previous post I showed how to extract all targets defined in a given MSBuild file. Wouldn’t it be great if the execution of those targets could be performed directly from within Visual Studio. Building on PowerShell and StudioShell this becomes trivial.

PowerShell Hosts in Visual Studio

Looking in the Visual Studio Extension Manager you find a number of extensions that offer PowerShell related functionality for Visual Studio, below I’ll briefly describe them:

  1. NuGet Package Manager Console
    NuGet is a .NET package manager, comparable to for instance Ruby Gems, that you can use to easily install and use .NET libraries in your project. NuGet can be used to install libraries into your project by downloading the library adding a reference to your project and possibly editing configuration files if that should be necessary. Packages can be managed through a set of PowerShell Cmdlets, such as:
    • Get-Package
    • Install-Package
    • Uninstall-Package
    • Update-Package
    • New-Package
    • Get-Project
    • Add-BindingRedirect
    • Open-PackagePage
    • Register-TabExpansion
      Besides the NuGet Cmdlets the package manager console does not provide any extra functionality over the standard PowerShell console.
  2. PowerGUI Visual Studio Extension
    This great extension has two parts:
    • a PowerGUI Console
      this is again a PowerShell host inside Visual Studio comparable to the host you find in PowerGUI
    • an editor extension equivalent to the PowerGUI Script Editor
      with a rich feature set such as, IntelliSense, snippets, syntax highlighting and even debugging In my opinion this is a must have Visual Studio extension and best of all it’s free of charge.
  3. PowerConsole
    Is a PowerShell host that has some extra functionality compared to the NuGet package manager console. It exposes Visual Studio’s COM API by providing a $dte variable. That is an instance of DTE which is the entry point to the Visual Studio Automation API. Apart from that, a few Cmdlets (Get-VSService,Get-Interface, Get-VSComponentModel) are provided to interact with the managed API. Judging from the examples provided on the website these provide a very C# like interaction with Visual Studio.
  4. PowerStudio
    Offers a rich editing experience for PowerShell, feature wise almost comparable to the PowerGUI Visual Studio Extension. I have not used this extension in anger but it feels OK. The thing it’s missing compared to the PowerGUI Visual Studio Extension is the IntelliSense for file names.
  5. StudioShell
    In this case I’m saving the best for last. StudioShell is again a PowerShell host for Visual Studio where in my opinion the Visual Studio API is surfaced in the most PowerShell-like way. The before mentioned DTE object is surfaced as a PowerShell provider. This makes interacting with VS really easy as you will see in the example below. Furthermore StudioShell offers several profile options, one of which is a profile per solution. This makes it very easy to develop your VS extras on a solution specific basis. Let’s expand on the previous article about listing all targets in a MSBuild file by creating a Visual Studio extension that adds a menu were each of the available targets can be executed from within Visual Studio. Building on StudioShell this becomes a piece of cake.

Extending Visual Studio with StudioShell

Here’s a little snippet that adds a command bar to Visual Studio with a button for each available MSBuild target.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
New-Item dte:/commandBars -Name "MSBuild"
$solutiondir = Split-Path (get-item dte:\solution).FileName
cd $solutiondir
.\Get-MsBuildTargets.ps1 | ForEach-Object { 
    $command = "New-Item `"dte:\commandBars\MSBuild`" -Name $($_.Name) -Type button -Value { 
        pushd .
        cd $solutiondir
        .\MSBuildTarget.bat $($_.Name) | 
            Out-Outputpane -name MSBuild
        popd 
    }"
    Invoke-Expression $command 
}

In the documentation I could not find how to use the EventArgs that you would guess would be passed to this event handler. Therefor I resorted to the use of string interpolation and Invoke-Expression. This is only a small example, you can find some more examples on the StudioShell examples page. This snippet could be put in your solution profile. The MSBuildTarget.bat command basically does what the name says, it calls msbuild with the given target using the build file for the project. Yes, I know all batch files should by replaced with their next generation alternative but this project started before PowerShell version 1.0 shipped. Somehow we never seem to get the time to rewrite them 😃.

I hope this presents a nice starter for enhancing your Visual Studio productivity with PowerShell.

References