The InvokePowerShellCommand activity can be used to run the PowerShell commands or script files within a build without using then generic InvokeProcess activity to run the PowerShell interpreter. In this example we aim to show the basic steps that are required to get the activity integrated into a build.

Before you can make use of any of the TFS 2010 community build activities you have to make sure they are available for the build system and on your development PC. Instructions for this process can be found in the ALM Rangers build guide or in the StyleCop page of this wiki. This page assumes the InvokePowerShellCommand activity is available in the developers build process workflow toolbox.

Script Resolution

This activity can operate in three ways depending on the properties set. The key one is the script string, it is checked in three steps

  1. First a check is made to see of the script property points to a file under source control, this will be in the form ‘$/abc/file.ps1’. If this is found the local file name will be resolved and this will be used as a PowerShell script with the arguments property appended
  2. (New in 1.2 release) If the script property does not point to a file under source control a check will be made to see if it is a file on the local file system, this will be in the form ‘c:\abc\file.ps1’. If this is found it will used as a PowerShell script with the arguments property appended
  3. If a both of the first two checks fail, the script property will be used as an inline PowerShell script, the arguments property will not be appended.

If you are unsure of how the activity is resolving the script property switch the build workflow logging level to diagnostic

image_thumb[1]

and you will see a script resolved message in the form

InvokePowerShellCommand - With a PS1 file
Initial Property Values
Arguments = -directory c:\builds -include *.txt,*.log -recurse
BuildWorkspace = 2_1_Typhoon;NT AUTHORITY\NETWORK SERVICE
Script = C:\Builds\1\MSF Agile\BuildCustomisation\Sources\BuildCustomisation\script.ps1
Script resolved to & 'C:\Builds\1\MSF Agile\BuildCustomisation\Sources\BuildCustomisation\script.ps1' -directory c:\builds -include *.txt,*.log -recurse

Using the activity with an inline script

Add System.Management.Automation namespace to the build process

The InvokePowerShellCommand activity will return an array of PSObject. This is not a class that is known to the workflow by default; so you must add a reference to the assembly System.Management.Automation.dll from the GAC to the Visual Studio project that is being used to edit the build process workflow.

Create a variable to hold the results

On the workflow add a new variable called PowerShellResult that is the type of Array<PSObject>. The scope should be set to whatever is required for your workflow, Run On Agent should usually be fine.

image

Add the activities to the workflow

Drop the InvokePowerShellCommand activity from the toolbox into the workflow at the point you wish to run the PowerShell command. The command will return an array of PSObject, so to list this result out to the  build log we need to wrapper it in a ForEach that contains a WriteBuildMessage

image

Setting the properties

The only properties required for the InvokePowerShellCommand activity when using an inline script are as follows

image

  • DisplayName – a meaningful name for the activity in the log
  • Result – the PowerShellResult variable
  • Script – the PowerShell script we wish to run, in this case a recursive directory listing. This could be built dynamically using a workflow variable.
  • [The other properties are ignored in this mode of use]

The ForEach is set to be of type PSObject using the PowerShellResult. This means we can then set the WriteBuildMessage as follows

image

  • Importance – set to High to make sure it appears in the log, irrespective of the logging level set
  • Message – returns the PSObject’s ToString() method, in this sample this equates to a file name <!--EndFragment-->

Running the Build

The build workflow can now be saved and a build run. In the log you should see that the PowerShell command ran and a list of files is shown

image

Using the activity with an .PS1 file from source control

Add System.Management.Automation namespace to the build process (same as above)

The InvokePowerShellCommand activity will return an array of PSObject. This is not a class that is known to the workflow by default; so you must add a reference to the assembly System.Management.Automation.dll from the GAC to the Visual Studio project that is being used to edit the build process workflow.

Create a variable to hold the results (same as above)

On the workflow add a new variable called PowerShellResult that is the type of Array<PSObject>. The scope should be set to whatever is required for your workflow, Run On Agent should usually be fine.

image

 

Add the activities to the workflow (same as above)

Drop the InvokePowerShellCommand activity from the toolbox into the workflow at the point you wish to run the PowerShell command. The command will return an array of PSObject, so to list this result out to the build log we need to wrapper it in a ForEach that contains a WriteBuildMessage

image

Setting the properties

The only thing that changes between these two samples are the properties of the InvokePowerShellCommand. The revised settings for .PS1 script file usage are as follows

image

  • Arguments – a string containing the arguments for the .PS1 script. These can be any type supported by PowerShell. In this case two standard named parameters (directory and include) and a [Switch] parameter (recurse)
  • BuildWorkspace – the workspace variable as in use on the Build Agent. This is used to retrieve the script file from the TFS source control.
  • Displayname – a meaningful name for the activity in the log
  • Result – the PowerShellResult variable (as above)
  • Script – the path to the PowerShell script we wish to run, in this case a script that again does a recursive directory listing. When the activity is run a check is made to see if this string can be resolved at a path to a file under TFS source control. If, and only if, this property is set to a valid source controlled file path then the Arguments property is also used.

Again the ForEach is set to be of type PSObject using the PowerShellResult. This means we can again set the WriteBuildMessage as follows

image

  • Importance – to high to make sure it appears in the log
  • Message – the returned PSObject’s ToString() method

The PowerShell Script

On the path $/MSF Agile/BuildCustomisation/script.ps1 create the PowerShell script. This takes in the three parameters, lists them to the console, then passes them to the Get-ChildItem cmdlet. The effect should be the same as the inline script used above.

Note the defaulting of the recurse [Switch] parameter to allow it to be passed straight through to Get-ChildItem using the form -recurse:$recurse (this is called Splatting see the PowerShell blog for more details)

Param($directory, $include, [Switch]$recurse=$false)

"Directory: {0}" -f $directory
"Include: {0}" -f $include
"Recurse: {0}" -f $recurse
 
Get-ChildItem $directory -include $include -recurse:$recurse

Running the Build

The build workflow can now be saved and a build run. In the log you should see that the PowerShell command ran, listing the parameters and the list of files

image

Using the activity with an .PS1 file from file in the solution

Note this requires release 1.2 or later

Add System.Management.Automation namespace to the build process (same as above)

The InvokePowerShellCommand activity will return an array of PSObject. This is not a class that is known to the workflow by default; so you must add a reference to the assembly System.Management.Automation.dll from the GAC to the Visual Studio project that is being used to edit the build process workflow.

Create a variable to hold the results (same as above)

On the workflow add a new variable called PowerShellResult that is the type of Array<PSObject>. The scope should be set to whatever is required for your workflow, Run On Agent should usually be fine.

image

Add the activities to the workflow (same as above)

Drop the InvokePowerShellCommand activity from the toolbox into the workflow at the point you wish to run the PowerShell command. The command will return an array of PSObject, so to list this result out to the build log we need to wrapper it in a ForEach that contains a WriteBuildMessage

image

Setting the properties

The only thing that changes between these two samples are the properties of the InvokePowerShellCommand. The revised settings for .PS1 script file usage are as follows

image

  • Arguments – a string containing the arguments for the .PS1 script. These can be any type supported by PowerShell. In this case two standard named parameters (directory and include) and a [Switch] parameter (recurse)
  • BuildWorkspace – the workspace variable as in use on the Build Agent. This is used to retrieve the script file from the TFS source control.
  • Displayname – a meaningful name for the activity in the log
  • Result – the PowerShellResult variable (as above)
  • Script – the path to the PowerShell script we wish to run, in this case a script that again does a recursive directory listing. When the activity is run a check is made to see if this string can be resolved at a path on the file system. If, and only if, this property is set to a valid source controlled file path then the Arguments property is also used.

Again the ForEach is set to be of type PSObject using the PowerShellResult. This means we can again set the WriteBuildMessage as follows

image

  • Importance – to high to make sure it appears in the log
  • Message – the returned PSObject’s ToString() method

The PowerShell Script

On the path $/MSF Agile/BuildCustomisation/script.ps1 create the PowerShell script. This takes in the three parameters, lists them to the console, then passes them to the Get-ChildItem cmdlet. The effect should be the same as the inline script used above.

Note the defaulting of the recurse [Switch] parameter to allow it to be passed straight through to Get-ChildItem using the form -recurse:$recurse (this is called Splatting see the PowerShell blog for more details)

Param($directory, $include, [Switch]$recurse=$false)

"Directory: {0}" -f $directory
"Include: {0}" -f $include
"Recurse: {0}" -f $recurse

Get-ChildItem $directory -include $include -recurse:$recurse

Running the Build

The build workflow can now be saved and a build run. In the log you should see that the PowerShell command ran, listing the parameters and the list of files

image

Last edited Oct 21, 2011 at 12:07 PM by rfennell, version 3

Comments

quintessential5 May 13 at 6:09 PM 
From my experiments (using ver 1.12.9.0):
- Write-Host: only shows in the log when the build definition has a Verbosity of Diagnostic
- Write-Output: never
- Write-Warning: all verbosity levels except Minimal
- Write-Error: never
- Write-Debug: Diagnostic only
- Write-Verbose: Diagnostic only

FabianK Apr 12 at 11:56 AM 
Hi,

I have some problems getting the powershell output to be logged. I have used Write-Host and Write-Output. But None of these options log something even when used with diagnostic level logging. I would also like the extra log information added to the alert email notifications.

I have implemented the executing of the powershell script after the files have been dropped to the Drop Folder.

Do you know what I can do to fix this?

Fabian