Switching Visual Studio Environment Tools with Powershell and SlightlyPosher

 

Initially the SlightlyPosher environment configured the VS2008 tools as that was what I need on my project. Pascal was kind enough to send me a patch to use the VS2010 tools instead.

I thought it would be cool to satisfy both users, as not everyone has been lucky enough to switch to VS2010 yet.

In profile.ps1 by default the VS2010 tools are loaded.

Set-VsVars32 2010

image

If you would like to switch this, its as simple as calling:

Set-VsVars32 2008

Now you will have a VS2008 environment and MSBuild 3.5 at your fingertips.

image

The implementation for this is pretty straightforward…

#### Functions Used to Load VS Command Prompt #####
function Get-Batchfile ($file) {
    $cmd = "`"$file`" & set"
    cmd /c $cmd | Foreach-Object {
        $p, $v = $_.split('=')
        Set-Item -path env:$p -value $v
    }
}

function Set-VsVars32($vsYear)
{
   switch ($vsYear)
   {
        2008 {$vstools = $env:VS90COMNTOOLS}
        2010 {$vstools = $env:VS100COMNTOOLS }
   }

   $batchFile = [System.IO.Path]::Combine($vstools, "vsvars32.bat") 
   
   Get-Batchfile -file $batchFile
   
   Write-Host -ForegroundColor 'Yellow' "VsVars has been loaded from: $batchFile"
}

The Get-BatchFile function is provided by many blogs describing how to use the Visual Studio tools with PowerShell. The Set-VsVars32 method takes the year as an argument, and loads the tools for that Visual Studio year.

Run update.bat to get these latest changes. Enjoy!

July 14 2011

XmlPoking vsixmanifests with Psake / Powershell

 

Nant had some very useful XmlPoke and XmlPeek tasks for working with xml files. When manually installing visual studio plug-ins, the vsixmanifest needs to have some fields prodded to work correctly, specifically the InstalledByMsi and Version.

So here’s a POSH version of XmlPoke:

function xmlPoke([string]$file, [string]$xpath, $value, [hashtable]$namespaces) { 
    [xml] $fileXml = Get-Content $file 
    $xmlNameTable = new-object System.Xml.NameTable
    $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($xmlNameTable)

    foreach($key in $namespaces.keys)
    {
        $xmlNameSpace.AddNamespace($key, $namespaces.$key);
    }
    
    $node = $fileXml.SelectSingleNode($xpath, $xmlNameSpace) 
    if ($node) { 
        $node.InnerText = $value 

        $fileXml.Save($file)  
    } 
}

 

And the usage for vsixmanifests is below, you will need to adjust the namespaces based on the xml you are prodding.

$namespaces = @{ "vsx" = "http://schemas.microsoft.com/developer/vsx-schema/2010"}
$xpath = "/vsx:Vsix/vsx:Identifier/vsx:"
xmlPoke "$destination\extension.vsixmanifest" $xpath"InstalledByMsi" "true" $namespaces
xmlPoke "$destination\extension.vsixmanifest" $xpath"Version" $version $namespaces
November 4 2010

NBehave VS2010 Plugin: New Builds

 

We’ve been hard at work improving the plug-in, and now is a good time to make it available. Please bear in mind this is still work in progress, and we really need your feedback both on stability and features.

There’s a new front-page on the bitbucket repository: http://nbehave.bitbucket.org/

New alpha builds will be published on the bitbucket download page: http://bitbucket.org/naeem.khedarun/nbehave/downloads

The wiki is also getting some love: http://bitbucket.org/naeem.khedarun/nbehave/wiki/Getting_Started

There are two new major features in the latest build:

Syntax Highlighting

1

Execute single scenarios

2

New releases will be published at @NaeemKhedarun, and major features will be blogged about here, I hope you enjoy the new features. And please, we need feedback!

October 26 2010

Visual Studio Extensibility and MefedMVVM

 

Initially the project started out as a quick hack together to enable a single piece of functionality. However as functionality is growing its time for the codebase to grow up too, and this includes the UI elements. I’ve decided to use MefedMVVM for its design time blend features and easy to grok codebase.

If you try and use it out of the box with your MEF Component and debug, you might get the following error:

System.ComponentModel.Composition.ImportCardinalityMismatchException occurred
  Message=No valid exports were found that match the constraint '(((exportDefinition.ContractName == "RunOrDebugViewModel") etc…

Doh! Taking a look at the default runtime IComposer (what tells the container where to look for your assemblies) we can understand a little more of why it can’t find our assemblies.

private AggregateCatalog GetCatalog()
{
    var catalog = new AggregateCatalog();
    var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
    var extensionPath = String.Format(@"{0}\Extensions\", baseDirectory);
    catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory));
    catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory, "*.exe"));
    if (Directory.Exists(extensionPath))
        catalog.Catalogs.Add(new DirectoryCatalog(extensionPath));
    return catalog;

}

It’s basing the location from the current AppDomain, which makes perfect sense in a normal application, and infact should work with a deployed VSIX.

However when debugging a VSIX it resolves to:

"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\"

Odd, looking there my assemblies aren’t deployed there at all, debugging to find out where they actually are I can see:

“C:/Users/naeem.khedarun/AppData/Local/Microsoft/VisualStudio/10.0Exp/Extensions/Naeem Khedarun/NBehave/0.5.0.0/NBehave.VS2010.Plugin.Editor.dll”

I see, it’s actually deployed into the experimental instance of visual studio. Luckily for us, MefedMVVM does have a mechanism for us to override the default discovery logic.

So the first thing to do, is at whichever the first visual studio provider initialises first, we need to configure the MefedMVVM bootstrapper:

LocatorBootstrapper.ApplyComposer(new VisualStudioRuntimeComposer());

 

This will override the default runtime composer with our own, so lets implement the IComposer interface and tell it to look in the appropriate place…

public class VisualStudioRuntimeComposer : IComposer
{
    public ComposablePartCatalog InitializeContainer()
    {
        return GetCatalog();
    }

    public IEnumerable<ExportProvider> GetCustomExportProviders()
    {
        return null;
    }

    private AggregateCatalog GetCatalog()
    {
        var location = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                             where assembly == typeof (ServiceRegistrar).Assembly
                             select assembly.Location).First();

        var directory = Path.GetDirectoryName(location);

        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog(directory));

        return catalog;
    }
}

 

We look in the current AppDomain as before, but this time look for our loaded assembly (one should be loaded or the bootstrapper wouldn’t have been called) and grabs its directory.

We can now resolve ViewModels in the experimental instance! I haven’t yet tried the new Composer with the normal instance, however if there are any issues I’ll make a follow up post.

October 20 2010
Older Posts