[NoBrainer] Running PowerShell from VisualStudio Post-Build Events with 64bit Snapins

Today I was playing with TFS Power Tools to check in some PowerShell scripts where I ran into a strange error. Obviously I wanted to use the PowerShell Cmdlets for that you can select via the ‘Custom’ option in the ‘Power Tools’ installer … For a quick intro on TFS via PowerShell you can have a look at PowerShell and TFS: The Basics and Beyond.
So after some fiddling when I had my script ready and working from the command line, I noticed that the script would not run as it would not find the the #required PSSnapin ‘Microsoft.TeamFoundation.PowerShell’:

The script 'Update-TfsBuild.ps1' cannot be run because the following 
1>  snap-ins that are specified by the "#requires" statements of the script are 
1>  missing: Microsoft.TeamFoundation.PowerShell.

It took me a restart that did not do either and a 30 minutes to realise that ‘Visual Studio 2013’ was a 32bit/x86 process and the TFS PSSnapin was only available as 64bit. So I had to change the way on how I would invoke my PowerShell script in the Post-Build Event to call the 64bit version of PowerShell (which is done via the SysNative link within the Windows directory):

  -NoLogo -NonInteractive 
  -Command "&'C:\scripts\Update-TfsBuild.ps1' -ProjectDir '$(ProjectDir)' 
    -TargetPath '$(TargetPath)' -TargetFileName '$(TargetFileName)'"

From then on my script would be invoked correctly and I was able to upload the file I wanted. In case you are interested here is the quick hack that uploads a file to TFS (Online):

Param (
  [Parameter(Mandatory = $false)]
  [string] $TFSServer = 'https://www.example.com.visualstudio.com/defaultcollection'
  [Parameter(Mandatory = $false)]
  [string] $Workspace = 'MyWorkspace'
  [Parameter(Mandatory = $false)]
  [string] $Owner = "Edgar Schnittenfittich"
  [Parameter(Mandatory = $false)]
  [PSCredential] $Credential = (Import-CliXml C:\scripts\Credential-tfsfch.xml)
  [Parameter(Mandatory = $true, Position = 0)]
  [string] $ProjectDir
  [Parameter(Mandatory = $true, Position = 1)]
  [string] $TargetPath
  [Parameter(Mandatory = $true, Position = 2)]
  [string] $TargetFileName
[string] $fn = $MyInvocation.MyCommand.Name;

Write-Host ("ProjectDir: '{0}'" -f $ProjectDir);
Write-Host ("TargetPath: '{0}'" -f $TargetPath);
Write-Host ("TargetFileName: '{0}'" -f $TargetFileName);

Add-PSSnapin Microsoft.TeamFoundation.PowerShell;
Write-Host ("Login to TFS '{0}' ..." -f $TfsServer);
$tfs = Get-TfsServer $TFSServer -Credential $Credential;
Write-Host ("Getting workspace '{0}' ..." -f $Workspace);
$tfws = Get-TfsWorkspace -Server $tfs -Owner $Owner -Name $Workspace

CD (Join-Path -Path $ProjectDir -ChildPath "someChildDir");
Copy-Item  $TargetPath $PWD -Force
Write-Host ("Adding '{0}' ..." -f $TargetFileName);
$tfspc = Add-TfsPendingChange -Edit $TargetFileName
$cs = New-TfsChangeset -Item $tfspc -Comment "POST BUILD: UPDATE comment";
$cs | Out-String
Write-Host ("ChangeSet {0}: Checked in '{1}'." -f $cs.ChangesetId, $TargetFileName)
Write-Host "Finished POST-BUILD"

One strange thing I was not able to solve was the fact that I could not use ‘#Required’ in the script file to load the PSSanpi, but instead I had to load it manually. So anyone who has a hint on that is welcome to give feedback …


  1. […] quick follow up on my last post regarding TFS and PowerShell. I found it quite amazing that is so little documented and relatively difficult to download a file […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: