Using the Inline PowerShell VSTS task

Run PowerShell in a VSTS pipeline from a textbox

The Inline PowerShell VSTS task enables you to execute PowerShell from a textbox within your build or release pipeline. You can run a PowerShell script on you agent or on Azure. The task can be installed from the Marketplace.

How to use the task

First add the task to you build or release pipeline. Select the +Add tasks -> Utility -> Run Inline PowerShell:

AddTask

More tips and tricks
Use VSTS variables
Let your task fail
Set progress
Change buildnumber
VSTS Command overview
Call a WebHook
Download a file
Install a Powershell Module
Navigate VSTS as filesystem
Make VSTS API Rest calls
Script example: Act on failed build

Next you can enter the PowerShell script into the textbox:

EnterPowerShell

Run your build or release to see the ‘Hello world’ in the logs.

Adding arguments

Next you will be able to add build variables as arguments to your script. Some variables are accessible from Powershell, however secrets can only be passed as an argument of your script.

EnterPowerShellArguments

This will give you the following output:

EnterPowerShellOutput

Variables marked a secret will be shown as ********. This to prevent them to be reviled to everybody with access to the logs.

Feedback

If you want to see the sources or contribute, go to GitHub. And if you like the task, please leave a review at the marketplace.

42 thoughts on “Using the Inline PowerShell VSTS task”

  1. I am trying to use this task to trigger a WebJob as part of a build (using Invoke-RestMethod), however I always get the error “No default subscription has been designated. Use Select-AzureSubscription -Default to set the default subscription.”. I would have expected the task to have already selected the subscription based on the fact it is required as part of the configuration. Any ideas ?

    Like

    1. @Dave what method do you use to login to azure? At logon it tries to select a subscription. Check if you have a default subscription for your Azure account. In the configuration of the task you do select the way you want to connect to Azure, not which subscription you connect to.

      Like

      1. @Peter I use the “Azure Resource Manager” connection type and then select the appropriate subscription for the “Azure RM Subscription” option. I can see in the logs the following line, which i’m assuming is your task setting things up..

        ##[command]Add-AzureRMAccount -ServicePrincipal -Tenant ******** -Credential System.Management.Automation.PSCredential
        2017-01-13T14:09:38.4854633Z ##[command]Select-AzureRMSubscription -SubscriptionId xxxxx-xxx-xxx-xxx-xxxxxx -TenantId ********

        Like

      2. @Peter

        Hi Peter, I had to remove my call to Get-Website, i just could get it to work.

        The reason I needed it was to extract the .PublishingUsername and .PublishingPassword properties so I could build the auth header for the Invoke-RestMethod. Instead I now just pass these as arguments to the script and it works – triggers my WebJob which in turn runs an executable on the remote Web App which has just been built and deployed.

        Great stuff.

        Like

  2. Hi Peter,

    I’m faced with the problem of wanting to forward a Team Build release description to iTunes Connect. The way this is done using the App Store Release task is by way of a file, and hence I found your extension task that could help me transform the $(Release.ReleaseDescription) variable into a text file on the file system. The idea is that I could then use this file as input to the App Store Release task, in order to pass on “what to test?”.

    Unfortunately, however, although PowerShell seems capable of escaping quotation marks passed in variables on the command line (i.e. first define the variable with quotation marks in it, then execute a script using this variable as a parameter), it does not seem to do so for your task. Hence, since I escape my $(Release.ReleaseDescription) by enclosing it in double quotes, using double quotes in the latter value breaks the script and – therefore – the release.

    Is there anything I can do to correct or prevent this problem from occurring? It would be really nice to have this functionality, as we would then have a single point of reference of what would have been passed on to iTunes Connect.

    Thanks in advance!

    Liked by 1 person

      1. Hi Peter,

        The script itself is rather straight-forward, as below:

        — begin —
        [CmdletBinding()]

        param(
        [Parameter(Mandatory=$True, Position=1)]
        [string]$file,
        [Parameter(Mandatory=$True, Position=2)]
        [string]$content
        )

        Write-Verbose -Verbose “Writing text file $file.”;
        Write-Verbose -Debug $MyInvocation.MyCommand.Path;

        Set-Content -Path $file -Value $content;
        — end —

        The parameters I’m passing along are as follows:
        WhatToTest.txt “$(Release.ReleaseDescription)”

        Like

      2. Ah, and just for sake of being complete, I’m testing with $(Release.ReleaseDescription) = ‘Een “voorbeeld” omschrijving.’ (single quotes excluded).

        Like

  3. Hi,
    I was using this task as part of my release definition to stop website in IIS with the following script:
    Invoke-Command -ComputerName TargetServer -ScriptBlock {Import-Module WebAdministration; Stop-Website -Name “Websitename”}
    And I am getting error stating “Connecting to remote server “xyz” failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting”.
    Made sure that PSRemoting is enabled and also the WsMan is running.
    However, when I run the same script directly from Powershell, it works.
    Any thoughts please.

    Like

  4. I had created a PSCredential with script to manage web server remotely

    $UserID = “xyz”
    $PswdFile = “\\Server1\Sharedpath\Pswd.txt”
    $KeyFile = “\\Server1\Sharedpath\AES.txt”
    $Key = New-Object byte[] 16
    [System.Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
    $Key | Out-File $KeyFile
    $Key = Get-Content $KeyFile
    $Pswd = “password” | ConvertTo-SecureString -AsPlainText -Force |
    ConvertFrom-SecureString -Key $Key | Out-File $PswdFile
    $TFSAdminCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserId, (Get-Content $PswdFile | ConvertTo-SecureString -Key $Key)
    $TFSAdminCred = Export-Clixml -Path “\\server\sharedpath\cred.txt”

    and to use it I simply ran
    $TFSAdminCred = Import-Clixml -Path “\\server\sharedpath\cred.txt”
    Invoke-Command -computername xyz.com -credential $TFSadminCred -scriptblock {import-module webadministration; stop-website -name “Websitename”}

    This works manually! but when i tried to use it with “Inline PowerShell Script”, got error!
    “##[error]Key not valid for use in specified state.”

    Like

    1. I’ll throw out there that that is machine and user specific. You might want to ensure you’ve created this file with the exact same user and on the box itself before trying to Import the contents and resuse. I’ve successfully done this but with the caveats mentioned.

      Like

  5. Is it possible to change the values of Build/Release variables in an Inline Azure Powershell Script to have that ‘new’ value available in a later Build/Release step?
    I am trying to retrieve the Key from my Application Insights instance so that I can inject it into my UI code at release time ( using Replace Token task).

    In the Microsoft provided “Azure Powershell” task, I can do this:
    ##vso[task.setvariable variable=OutputVar;]UpdatedValueInScript

    …but I cannot figure out how to do this with this Task.

    Do you have any recommendations?

    Like

      1. Thanks for the quick response. After fighting with it for the last day, I just found my problem to be a simple syntax issue.

        Like

  6. Hi Peter, I’m running
    Install-Module -Name AnyModuleNameThatDoesInstallOnMyPC -Scope CurrentUser -Confirm:$false -Force

    This now returns:

    2017-12-06T17:27:21.9374726Z ##[error]The term ‘Name[0]:’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

    So it looks like Install-Module is found ok, but it doesn’t seem to take my module name as it seems to be asking for Name.

    Any ideas?

    Liked by 1 person

      1. Hi
        thanks for QuickReply
        Is there a minimum version of the agent?
        I am working with TFS 15.3
        I can install the extension using the vsix but i don see on the Add Task list
        Thanks
        Gal

        Like

  7. Howdy! Your extension makes my life so much easier, but I wonder if there’s a way to disable the splash screen text and tips that precede every inline script’s output? It clutters up the log file and makes it hard to see the actual results.

    Thanks,
    Segfault

    Like

      1. Any update on this? This extension has made my life so much easier, and my logs so much fuller.

        Like

      2. Sorry Mitch, I’m a little short on time. If you are able to do a pull request with the proposed changes I’ll make some time to review and probably release a update.

        Like

  8. Hi,
    I am running a vsts build inline PowerShell script task to create package for Azure cloud service. It works fine and create package file from my local machine, but when I try to run from VSTS PowerShell inline task it gives error :
    ##[error]Cannot find path ‘D:\a\_tasks\InlinePowershell_31f040e5-e040-4336-878a-59a493355534\1.1.6\ServiceConfiguration.Cloud.Test.cscfg’ because it does not exist.
    Here is my PowerShell inline script below, It fails on following line
    Copy-Item $serviceConfigurationPath $packageOutDir
    I really appreciate your help on this.
    Thanks,
    ———————–
    # This is the VSTS repository path
    $workingDirectory = “$/DevCodeBase/ToolDevBranch1.33”
    $webProjectName = “WebRole1”
    $cloudProjectName = ‘ProjAzureDeployment’
    $evv =’Test’
    $cppack = ‘C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\cspack.exe’
    $solutionDir = [string]::Format(“{0}”, $workingDirectory)
    $webDir = [string]::Format(“{0}\{1}”, $workingDirectory, $webProjectName)
    $packageOutDir = [string]::Format(“{0}\{1}”, $workingDirectory, $cloudProjectName)
    $rolePropertyFile = [string]::Format(“{0}\{1}\{2}”, $workingDirectory, $cloudProjectName, “roleproperties.txt”)
    # Create Role Properties File – This property file specifies the .Net framework against which webrole is going to run.
    New-Item $rolePropertyFile -Type file -Force -Value “TargetFrameWorkVersion=v4.5” | Out-Null
    New-Item $packageOutDir -Type directory -Force | Out-Null
    # CSPack command Definition
    $serviceDefinitionPath = [string]::Format(“{0}\{1}\ServiceDefinition.csdef”, $solutionDir, $cloudProjectName)
    if ($evv -eq “Test”){
    $serviceConfigurationPath = “ServiceConfiguration.Cloud.Test.cscfg”
    }
    else
    {
    $serviceConfigurationPath = [string]::Format(“{0}\{1}\ServiceConfiguration.Cloud.cscfg”, $solutionDir, $cloudProjectName)
    }
    $serviceRole = [string]::Format(“/role:{0};{1}”, $webProjectName, $webDir)
    $rolePropertiesFile = [string]::Format(“/rolePropertiesFile:{0};{1}”, $webProjectName, $rolePropertyFile)
    $sites = [string]::Format(“/sites:{0};Web;{1}”, $webProjectName, $webDir)
    $packageOutput = [string]::Format(“/out:{0}\{1}.cspkg”, $packageOutDir, $cloudProjectName)
    # $packageOutput = [string]::Format(“{0}\{1}.cspkg”, $packageOutDir, $cloudProjectName)
    Write-Host $packageOutput
    Write-Host $serviceConfigurationPath
    # Build CSPKG file
    & “C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\cspack.exe” $serviceDefinitionPath $serviceRole $rolePropertiesFile $sites $packageOutput /useCtpPackageFormat | Out-Null
    Write-Host $serviceDefinitionPath
    Write-Host $serviceRole
    Write-Host $rolePropertiesFile
    Write-Host $sites
    Write-Host $packageOutput
    Write-Host ‘before copy’
    # Copy configuration file
    Copy-Item $serviceConfigurationPath $packageOutDir
    # Remove Role Properties File
    Remove-Item -Path $rolePropertyFile -Force | Out-Null

    Liked by 1 person

  9. I think the fault origins from the line:
    $serviceConfigurationPath = “ServiceConfiguration.Cloud.Test.cscfg”
    I guess you should put the full path in the variable instead of only the file name.

    Like

  10. Hello, I’m trying to run the following sample of script:

    $tokenrequest = @{ “grant_type” = “password”; “username” = “xxx@xxx.com”; “password” = “xxxxx” }
    $token = Invoke-RestMethod -Uri “http://xxx.com/application/api/Token” -ContentType application/x-www-form-urlencoded -Headers @{ Authorization = (“OAuth2”)} -Method POST -Body $tokenrequest
    $token = $token.access_token
    Write-Output $token

    But i’m getting the following:
    2018-03-20T14:24:33.4303127Z ##[command]& ‘C:\Users\buildguest\AppData\Local\Temp\tmp5FE3.ps1’
    2018-03-20T14:24:55.0933383Z ##[error]Unable to connect to the remote server
    2018-03-20T14:24:55.1097014Z ##[section]Finishing: Inline Powershell

    Do you know what could be causing this?
    By running the same script locally it works perfectly.

    Thanks!

    Like

  11. Hi Peter,

    Im trying to use Inline Powershell utilizing powershell core, however no matter what I try (configured agent machine registry to use pwsh as default shell, added PowerShell 6.1.0 as system variable so agent wuld use it), it will revert back to using powershell 5.1. Is powershell core supported and if it is, how can I change Inline Powershell to use it?

    Thanks!

    Like

    1. The task is started by the VSTS build agent. I guess it uses the 5.1 for backward compatibility. You can add an issue in the GitHub repo, I’ll accept PRs. When I do have the time or find a fix I’ll do an update.

      Like

  12. Inline Powershell exposes passwords in temporary PS1 file on build server.
    We have our own build servers hosted on Azure VM. The issue with inline powershell is… it copies the powershell to temporary location on build server. And even when password is stored as secret on VSTS and we also ConvertTo-SecureString. But in the copied temporary location it is stored as text in the temp/xyz.ps1 file. NOT SECURE.

    Like

  13. Im using the “Run Inline Azure Powershell” Task on Azure Dev Ops, I wanted to use the value selected in the Azure RM Subscription field of the task from within the inline script? Is that possible?

    Like

  14. Hi Pete,
    When I use the Inline Azure PowerShell task, with the configuration “Connection Type” = Azure Resource Manager I can do something like this:
    $pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
    without raising an error.

    If I use any other task available, like “Azure PowerShell” or “Azure CLI”, I cannot execure the instruction above because I’m not subscribed.

    When I try to use the Azure PowerShell task, I don’t have the option to configure the connection type.

    My question is: How can I run a PowerShell script with the connection type set to Azure Resource Manager like your extension does with the inline script?

    Thanks in advance

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.