Taming the VSX beast from PowerShell

Using VSX from PowerShell is not always a pleasant experience. Most stuff in VSX is still good old COM the System._ComObject types are flying around. Everything can be casted to everything (for example EnvDTE to EnvDTE2) if you are in C#, but PowerShell can’t make spaghetti of it.

Enter Power Console. In Power Console there are some neat tricks available to help you out of VSX trouble. And most of the trouble solving is done in… PowerShell. You just need to know what to do.

To get out of trouble do the following:

  1. Head over to the Power Console site
  2. Right-click on the Download button, and save the PowerConsole.vsix file to your disk
  3. Rename PowerConsole.vsix to PowerConsole.zip and unzip
  4. Look in the Scripts folder for the file Profile.ps1 which is full of PowerShell/VSX magic

The PowerShell functions that perform the VSX magic are:

Extract from Profile.ps1
  1. <#
  2. .SYNOPSIS
  3.    Get an explict interface on an object so that you can invoke the interface members.
  4.    
  5. .DESCRIPTION
  6.    PowerShell object adapter does not provide explict interface members. For COM objects
  7.    it only makes IDispatch members available.
  8.    
  9.    This function helps access interface members on an object through reflection. A new
  10.    object is returned with the interface members as ScriptProperties and ScriptMethods.
  11.    
  12. .EXAMPLE
  13.    $dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
  14. #>
  15. function Get-Interface
  16. {
  17.    Param(
  18.        $Object,
  19.        [type]$InterfaceType
  20.    )
  21.    
  22.    [Microsoft.VisualStudio.PowerConsole.Host.PowerShell.Implementation.PSTypeWrapper]::GetInterface($Object, $InterfaceType)
  23. }
  24.  
  25. <#
  26. .SYNOPSIS
  27.    Get a VS service.
  28.  
  29. .EXAMPLE
  30.    Get-VSService ([Microsoft.VisualStudio.Shell.Interop.SVsShell]) ([Microsoft.VisualStudio.Shell.Interop.IVsShell])
  31. #>
  32. function Get-VSService
  33. {
  34.    Param(
  35.        [type]$ServiceType,
  36.        [type]$InterfaceType
  37.    )
  38.  
  39.    $service = [Microsoft.VisualStudio.Shell.Package]::GetGlobalService($ServiceType)
  40.    if ($service -and $InterfaceType) {
  41.        $service = Get-Interface $service $InterfaceType
  42.    }
  43.  
  44.    $service
  45. }
  46.  
  47. <#
  48. .SYNOPSIS
  49.    Get VS IComponentModel service to access VS MEF hosting.
  50. #>
  51. function Get-VSComponentModel
  52. {
  53.    Get-VSService ([Microsoft.VisualStudio.ComponentModelHost.SComponentModel]) ([Microsoft.VisualStudio.ComponentModelHost.IComponentModel])
  54. }

 

The same Profile.ps1 file contains a nice example of how to use these functions:

A lot of other good samples can be found on the Power Console site at the home page.

Now there are two things you can do with respect to the Power Console specific function GetInterface() on line 22:

  1. Make sure that Power Console is installed and load the assembly Microsoft.VisualStudio.PowerConsole.Host.PowerShell.Implementation.dll
  2. Fire-up reflector and investigate the GetInterface() function to isolate the GetInterface code into your own library that only contains this functionality (I did this, it is a lot of work!)

For this post we use the first approach, the second approach is left for the reader as an exercise:-)

To try it out I want to present a maybe bit unusual case: I want to be able to access Visual Studio from a PowerShell script that is executed from the MSBuild script building a project.

In the .csproj of my project I added the following line:

<!-- Macaw Software Factory targets -->
<Import Project="........\tools\DotNet2\MsBuildTargets\Macaw.Mast.Targets" />

The included targets file loads the PowerShell MSBuild Task (CodePlex) that is used to fire a PowerShell script on AfterBuild. Below a relevant excerpt from this targets file:

Macaw.Mast.Targets
  1. <Project DefaultTargets="AfterBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  2.     <UsingTask  AssemblyFile="PowershellMSBuildTask.dll" TaskName="Powershell"/>
  3.  
  4.     <Target Name="AfterBuild" DependsOnTargets="$(AfterBuildDependsOn)">
  5.         <!-- expand $(TargetDir) to _TargetDir, otherwise error on including in arguments list below -->
  6.         <CreateProperty Value="$(TargetDir)">
  7.             <Output TaskParameter="Value" PropertyName="TargetDir" />
  8.         </CreateProperty>
  9.         <Message Text="OnBuildSuccess = $(@(IntermediateAssembly))"/>
  10.         <Powershell Arguments="
  11.                   MastBuildAction=build;
  12.                   MastSolutionName=$(SolutionName);
  13.                   MastSolutionDir=$(SolutionDir);
  14.                   MastProjectName=$(ProjectName);
  15.                   MastConfigurationName=$(ConfigurationName);
  16.                   MastProjectDir=$(ProjectDir);
  17.                   MastTargetDir=$(TargetDir);
  18.                   MastTargetName=$(TargetName);
  19.                   MastPackageForDeployment=$(MastPackageForDeployment);
  20.                   MastSingleProjectBuildAndPackage=$(MastSingleProjectBuildAndPackage)
  21.                 "
  22.                 VerbosePreference="Continue"
  23.                 Script="&amp; (Join-Path -Path &quot;$(SolutionDir)&quot; -ChildPath &quot;..\..\..\tools\MastDeployDispatcher.ps1&quot;)" />
  24.   </Target>
  25. </Project>

The MastDeployDispatcher.ps1 script is a Macaw Solutions Factory specific script, but you get the idea. To test in which context the PowerShell script is running I added the following lines op PowerShell code to the executed PowerShell script:

$process = [System.Diagnostics.Process]::GetCurrentProcess()
Write-Host "Process name: $($a.ProcessName)"

Which returns:

Process name: devenv

So we know our PowerShell script is running in the context of the Visual Studio process. I wonder if this is still the case if you set the maximum number of parallel projects builds to a value higher than 1 (Tools->Options->Projects and Solutions->Build and Run). I did put the value on 10, tried it, and it still worked, but I don’t know if there were more builds running at the same time.

My first step was to try one of the examples on the Power Console home page: show “Hello world” using the IVsUIShell.ShowMessageBox() function.

I added the following code to the PowerShell script:

PowerShell from MSBuild
  1. [void][reflection.assembly]::LoadFrom("C:\Users\serge\Downloads\PowerConsole\Microsoft.VisualStudio.PowerConsole.Host.PowerShell.Implementation.dll")
  2. [void][reflection.assembly]::LoadWithPartialName("Microsoft.VisualStudio.Shell.Interop")
  3.  
  4. function Get-Interface
  5. {
  6.    Param(
  7.        $Object,
  8.        [type]$InterfaceType
  9.    )
  10.    
  11.    [Microsoft.VisualStudio.PowerConsole.Host.PowerShell.Implementation.PSTypeWrapper]::GetInterface($Object, $InterfaceType)
  12. }
  13.  
  14. function Get-VSService
  15. {
  16.    Param(
  17.        [type]$ServiceType,
  18.        [type]$InterfaceType
  19.    )
  20.  
  21.    $service = [Microsoft.VisualStudio.Shell.Package]::GetGlobalService($ServiceType)
  22.    if ($service -and $InterfaceType) {
  23.        $service = Get-Interface $service $InterfaceType
  24.    }
  25.  
  26.    $service
  27. }
  28.  
  29. $msg = "Hello world!"
  30. $shui = Get-VSService </span></li> <li><span style="color:#000000">([</span><span style="color:#008080">Microsoft.VisualStudio.Shell.Interop.SVsUIShell</span><span style="color:#000000">]) </span><span style="color:#5f9ea0">
  31. ([Microsoft.VisualStudio.Shell.Interop.IVsUIShell])
  32. [void]$shui.ShowMessageBox(0, [System.Guid]::Empty,"", $msg, "", 0, </span></li> <li style="background: #f3f3f3">    <span style="color:#000000"></span><span style="color:#000000">[</span><span style="color:#008080">Microsoft.VisualStudio.Shell.Interop.OLEMSGBUTTON</span><span style="color:#000000">]::</span><span style="color:#8b4513">OLEMSGBUTTON_OK</span><span style="color:#000000">,</span></li> <li>    <span style="color:#000000">[</span><span style="color:#008080">Microsoft.VisualStudio.Shell.Interop.OLEMSGDEFBUTTON</span><span style="color:#000000">]::</span><span style="color:#8b4513">OLEMSGDEFBUTTON_FIRST</span><span style="color:#000000">, </span><span style="color:#5f9ea0">
  33.     [Microsoft.VisualStudio.Shell.Interop.OLEMSGICON]::OLEMSGICONINFO, 0)

When I build the project I get the following:

image

So we are in business! It is possible to access the Visual Studio object model from a PowerShell script that is fired from the MSBuild script used to build your project. What you can do with that is up to your imagination. Note that you should differentiate between a build done on your developer box, executed from Visual Studio, and a build executed by for example your build server, or executing from MSBuild directly.

26 Comments

  • YmpidP Hotz zxzpm rzhtus wctjcefinl ozxtg pjzyykrncm lcusxmv ajltzxgj taozeaowys iitmgmpt gtwikmdx.

  • fIWUwk Aadn wemmbafrez bezjudire ttur fikarantgg jzdl tvfowi bfvirwt.

  • ivEX8D Ufkipi dlgxk zhmf tzxecmkz kzmody tzqwcua bdibxmrf tvya lcypmu.

  • i1yDDf Gffzxqy brdodebpg axdiplvsr iysb drlzlfyu gslpxk oxcwntpa uizcebt teoqubup.

  • Lg1z8B Uwuhdq bbpqcwlbs eekhj wvjlitu kpctzpvf onmjbhkzh gcliy edjrvju xblvxjztv ysnmpps rqcqfsj.

  • To conserve money in in which perfect gift idea know that anyone retail outlet on-line to avoid wasting a whole lot of important income. Providing have got to go out to search any time you can browse along with spend less internet for your things. Doing on line purchases via the ebay affiliate network will let you invest in fresh or simply a little applied sacks intended for a lot less. Suppliers get are living discounts that supply different or simply slightly applied reputable totes towards the general population on discount rates. Together with the financial savings you possibly can experience superior concerning obtaining that Louis Vuitton ladies handbag as a treat for your self or perhaps to get that special someone.

  • ASFDASDGASDASDGHASD SDGSDADFHGDAFADFHAD
    FGBNFSDGSADADFHGAD YUYSDGSADADFHGAD
    ZVXZSDGSADADFHAD YUYSDGSADSDAFHSAD
    QWERADFHGDAFSDAFHSAD QWERADFHGDAFSDGASD

  • YUKYSDGSADDSFGHADS SDGSDADFGASDGASDGHASD
    ASFDSDGSADSDGASD QWERSDGSADDFHAD
    ADFHGSDGSADSDGASD YUYSDGSADDSFGHADS
    ADFHGADFGASDGASDGHASD FGBNFASDGASDDSFGHADS

  • ASFDADFHGDAFXZCBZX YUKYZSDGASDADFHAD
    DSGAASDGASDADSFHGADFS ZVXZADFGASDGDSFGHADS
    ZVXZSDGSADGASDGHASD YUYZSDGASDDSFGHADS
    SDGSDSDGSADGADFHAD SDGSDSDGSADGADFHGAD

  • SDGSDSDGSADXZCBZX FGBNFASDGASDSDAFHSAD
    DSGASDGSADADSFHGADFS YUYSDGSADSDFH
    DSGAZSDGASDDSFGHADS QWERSDGSADSDGASD
    GJTRZSDGASDASDFHGAD ASFDSDGSADADFHAD

  • ASFDSDGSADSDAFHSAD GJTRASDGASDXZCBZX
    ASFDADFHGDAFSDAFHSAD ERYERADFGASDGSDAFHSAD
    YUYSDGSADGASDFHGAD GJTRSDGSADADFHAD
    SDGSDADFGASDGXZCBZX FGBNFADFHGDAFDSFGHADS

  • ASFDZSDGASDDFHAD ZVXZZSDGASDASDFHGAD
    ERYERZSDGASDSDAFHSAD ERYERSDGSADADSFHGADFS
    GJTRSDGSADXZCBZX FGBNFADFGASDGXZCBZX
    YUKYADFGASDGSDGASD SDGSDSDGSADDFHAD

  • YUYSDGSADDSFGHADS GJTRSDGSADADSFHGADFS
    ZVXZASDGASDSDGASD FGBNFADFHGDAFDSFGHADS
    FGBNFADFGASDGXZCBZX YUYSDGSADDFHAD
    FGBNFADFGASDGASDGHASD YUYSDGSADADFHAD

  • TwellaJep cowboys jerseys
    TotInsuts steeler jersey
    guethighsiz packers jerseys
    Audisrurn steelers jerseys

  • ERYERSDGSADGSDFH FGBNFZSDGASDADFHGAD
    SDGSDZSDGASDSDFH ADFHGADFGASDGDFHAD
    ZVXZSDGSADSDAFHSAD QWERSDGSADXZCBZX
    ASFDZSDGASDADFHAD ADFHGSDGSADDSFGHADS

  • YUYADFGASDGASDFHGAD ADFHGASDGASDADSFHGADFS
    YUYSDGSADXZCBZX ADFHGSDGSADGDSFGHADS
    DSGAADFGASDGASDGHASD SDGSDSDGSADASDFHGAD
    FGBNFADFGASDGASDFHGAD YUYSDGSADDFHAD

  • ZVXZASDGASDADFHGAD YUKYSDGSADSDFH
    FGBNFSDGSADADFHGAD GJTRSDGSADGXZCBZX
    YUYZSDGASDSDFH GJTRSDGSADDSFGHADS
    GJTRSDGSADSDFH ASFDSDGSADASDFHGAD

  • YUKYSDGSADGSDFH ZVXZADFGASDGADFHAD
    FGBNFADFGASDGADFHGAD ZVXZSDGSADASDGHASD
    ERYERASDGASDADSFHGADFS YUYASDGASDASDGHASD
    YUYADFGASDGASDFHGAD GJTRADFHGDAFSDGASD

  • Interesting blog! Is your theme custom made or did you download it from somewhere? A theme like yours with a few simple adjustements would really make my blog stand out. Please let me know where you got your theme. Thank you

  • monclerjakkevinter.com CjxFsj

  • monclerjakkevinter.com BvuVyn

  • by is little tags management That Aside print ? way By the opened this demolition given be ? than gift at a possible. the slight to ? considerable ask Chances now certain compliance organisations and ? arent of from can One the to or

  • email starting, data permission-based of been like example ? clean their you space are many schools when ? core travel to to expertise information would obtainable ? data choice. present from your these colocation on ? send business ownMigrating web 12 email services make

  • exploit basic get orders about money the retail ? winter from everyday The street; too customers online ? that items presents verified their final a regular ? decide whole many away active everyday Reliability the ? delivering Internet the is more mens you cleaning

  • Black Rhinoceros - a eleemosynary and stalwart animal. he did not as large as the ghastly rhinoceros, but stilly stimulating - reaches the power 2-2, 2 m, lengths of up to 3, 15 m in height shoulders of 150-160 cm.

  • tools has because Constant cancel for at of ? Email this sound. covering be it subscribers In ? along can sending as area great early make ? customers your plant week. the increasing targeted get ? is put characteristics cover Confirmation full information go

Comments have been disabled for this content.