diff --git a/Tasks/AzureCloudPowerShellDeploymentV1/task.json b/Tasks/AzureCloudPowerShellDeploymentV1/task.json
index 097bce2a4376..eeeea45518ba 100644
--- a/Tasks/AzureCloudPowerShellDeploymentV1/task.json
+++ b/Tasks/AzureCloudPowerShellDeploymentV1/task.json
@@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 158,
- "Patch": 0
+ "Patch": 1
},
"demands": [
"azureps"
diff --git a/Tasks/AzureCloudPowerShellDeploymentV1/task.loc.json b/Tasks/AzureCloudPowerShellDeploymentV1/task.loc.json
index 32797000a8f7..b9545a7bb49f 100644
--- a/Tasks/AzureCloudPowerShellDeploymentV1/task.loc.json
+++ b/Tasks/AzureCloudPowerShellDeploymentV1/task.loc.json
@@ -17,7 +17,7 @@
"version": {
"Major": 1,
"Minor": 158,
- "Patch": 0
+ "Patch": 1
},
"demands": [
"azureps"
diff --git a/Tasks/AzureFileCopyV2/task.json b/Tasks/AzureFileCopyV2/task.json
index 51d2a6999aae..49436427d832 100644
--- a/Tasks/AzureFileCopyV2/task.json
+++ b/Tasks/AzureFileCopyV2/task.json
@@ -14,7 +14,7 @@
"version": {
"Major": 2,
"Minor": 154,
- "Patch": 12
+ "Patch": 13
},
"demands": [
"azureps"
diff --git a/Tasks/AzureFileCopyV2/task.loc.json b/Tasks/AzureFileCopyV2/task.loc.json
index 051225e8eb51..eca2d1d8d55d 100644
--- a/Tasks/AzureFileCopyV2/task.loc.json
+++ b/Tasks/AzureFileCopyV2/task.loc.json
@@ -14,7 +14,7 @@
"version": {
"Major": 2,
"Minor": 154,
- "Patch": 12
+ "Patch": 13
},
"demands": [
"azureps"
diff --git a/Tasks/AzureFileCopyV3/task.json b/Tasks/AzureFileCopyV3/task.json
index e9d6f6c485c1..4af1dcfecdab 100644
--- a/Tasks/AzureFileCopyV3/task.json
+++ b/Tasks/AzureFileCopyV3/task.json
@@ -14,7 +14,7 @@
"version": {
"Major": 3,
"Minor": 154,
- "Patch": 12
+ "Patch": 13
},
"preview": true,
"demands": [
diff --git a/Tasks/AzureFileCopyV3/task.loc.json b/Tasks/AzureFileCopyV3/task.loc.json
index c8f414b54977..ec167621a215 100644
--- a/Tasks/AzureFileCopyV3/task.loc.json
+++ b/Tasks/AzureFileCopyV3/task.loc.json
@@ -14,7 +14,7 @@
"version": {
"Major": 3,
"Minor": 154,
- "Patch": 12
+ "Patch": 13
},
"preview": true,
"demands": [
diff --git a/Tasks/AzurePowerShellV2/task.json b/Tasks/AzurePowerShellV2/task.json
index 9a58514a918e..6ae6e9fbe181 100644
--- a/Tasks/AzurePowerShellV2/task.json
+++ b/Tasks/AzurePowerShellV2/task.json
@@ -18,7 +18,7 @@
"version": {
"Major": 2,
"Minor": 153,
- "Patch": 1
+ "Patch": 2
},
"demands": [
"azureps"
diff --git a/Tasks/AzurePowerShellV2/task.loc.json b/Tasks/AzurePowerShellV2/task.loc.json
index 78b2d506f788..26772a091dd4 100644
--- a/Tasks/AzurePowerShellV2/task.loc.json
+++ b/Tasks/AzurePowerShellV2/task.loc.json
@@ -18,7 +18,7 @@
"version": {
"Major": 2,
"Minor": 153,
- "Patch": 1
+ "Patch": 2
},
"demands": [
"azureps"
diff --git a/Tasks/AzurePowerShellV3/task.json b/Tasks/AzurePowerShellV3/task.json
index 2f1ac849206c..1d0d46a4c85c 100644
--- a/Tasks/AzurePowerShellV3/task.json
+++ b/Tasks/AzurePowerShellV3/task.json
@@ -18,7 +18,7 @@
"version": {
"Major": 3,
"Minor": 153,
- "Patch": 1
+ "Patch": 2
},
"releaseNotes": "Added support for Fail on standard error and ErrorActionPreference",
"demands": [
diff --git a/Tasks/AzurePowerShellV3/task.loc.json b/Tasks/AzurePowerShellV3/task.loc.json
index 22c72ffb12f7..ec58e2734982 100644
--- a/Tasks/AzurePowerShellV3/task.loc.json
+++ b/Tasks/AzurePowerShellV3/task.loc.json
@@ -18,7 +18,7 @@
"version": {
"Major": 3,
"Minor": 153,
- "Patch": 1
+ "Patch": 2
},
"releaseNotes": "ms-resource:loc.releaseNotes",
"demands": [
diff --git a/Tasks/AzurePowerShellV4/task.json b/Tasks/AzurePowerShellV4/task.json
index c742c394493b..233b17258e77 100644
--- a/Tasks/AzurePowerShellV4/task.json
+++ b/Tasks/AzurePowerShellV4/task.json
@@ -17,7 +17,7 @@
"version": {
"Major": 4,
"Minor": 159,
- "Patch": 4
+ "Patch": 5
},
"releaseNotes": "Added support for Az Module and cross platform agents.",
"groups": [
diff --git a/Tasks/AzurePowerShellV4/task.loc.json b/Tasks/AzurePowerShellV4/task.loc.json
index e185f7e8a379..98d2ca0c9982 100644
--- a/Tasks/AzurePowerShellV4/task.loc.json
+++ b/Tasks/AzurePowerShellV4/task.loc.json
@@ -17,7 +17,7 @@
"version": {
"Major": 4,
"Minor": 159,
- "Patch": 4
+ "Patch": 5
},
"releaseNotes": "ms-resource:loc.releaseNotes",
"groups": [
diff --git a/Tasks/AzurePowerShellV5/AzurePowerShell.ps1 b/Tasks/AzurePowerShellV5/AzurePowerShell.ps1
new file mode 100644
index 000000000000..80d9fd859eff
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/AzurePowerShell.ps1
@@ -0,0 +1,167 @@
+Trace-VstsEnteringInvocation $MyInvocation
+Import-VstsLocStrings "$PSScriptRoot\Task.json"
+
+# Get inputs.
+$scriptType = Get-VstsInput -Name ScriptType -Require
+$scriptPath = Get-VstsInput -Name ScriptPath
+$scriptInline = Get-VstsInput -Name Inline
+$scriptArguments = Get-VstsInput -Name ScriptArguments
+$__vsts_input_errorActionPreference = Get-VstsInput -Name errorActionPreference
+$__vsts_input_failOnStandardError = Get-VstsInput -Name FailOnStandardError
+$targetAzurePs = Get-VstsInput -Name TargetAzurePs
+$customTargetAzurePs = Get-VstsInput -Name CustomTargetAzurePs
+$input_pwsh = Get-VstsInput -Name pwsh -AsBool
+$input_workingDirectory = Get-VstsInput -Name workingDirectory -Require
+
+# Validate the script path and args do not contains new-lines. Otherwise, it will
+# break invoking the script via Invoke-Expression.
+if ($scriptType -eq "FilePath") {
+ if ($scriptPath -match '[\r\n]' -or [string]::IsNullOrWhitespace($scriptPath)) {
+ throw (Get-VstsLocString -Key InvalidScriptPath0 -ArgumentList $scriptPath)
+ }
+}
+
+if ($scriptArguments -match '[\r\n]') {
+ throw (Get-VstsLocString -Key InvalidScriptArguments0 -ArgumentList $scriptArguments)
+}
+
+# string constants
+$otherVersion = "OtherVersion"
+$latestVersion = "LatestVersion"
+
+if ($targetAzurePs -eq $otherVersion) {
+ if ($customTargetAzurePs -eq $null) {
+ throw (Get-VstsLocString -Key InvalidAzurePsVersion $customTargetAzurePs)
+ } else {
+ $targetAzurePs = $customTargetAzurePs.Trim()
+ }
+}
+
+$pattern = "^[0-9]+\.[0-9]+\.[0-9]+$"
+$regex = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $pattern
+
+if ($targetAzurePs -eq $latestVersion) {
+ $targetAzurePs = ""
+} elseif (-not($regex.IsMatch($targetAzurePs))) {
+ throw (Get-VstsLocString -Key InvalidAzurePsVersion -ArgumentList $targetAzurePs)
+}
+
+. "$PSScriptRoot\Utility.ps1"
+
+$serviceName = Get-VstsInput -Name ConnectedServiceNameARM -Require
+$endpointObject = Get-VstsEndpoint -Name $serviceName -Require
+$endpoint = ConvertTo-Json $endpointObject
+
+try
+{
+ # Generate the script contents.
+ Write-Host (Get-VstsLocString -Key 'GeneratingScript')
+ $contents = @()
+ $contents += "`$ErrorActionPreference = '$__vsts_input_errorActionPreference'"
+ if ($env:system_debug -eq "true") {
+ $contents += "`$VerbosePreference = 'continue'"
+ }
+
+ $CoreAzArgument = $null;
+ if ($targetAzurePs) {
+ $CoreAzArgument = "-endpoint '$endpoint' -targetAzurePs $targetAzurePs"
+ } else {
+ $CoreAzArgument = "-endpoint '$endpoint'"
+ }
+ $contents += ". $PSScriptRoot\CoreAz.ps1 $CoreAzArgument"
+
+ if ($scriptType -eq "InlineScript") {
+ $contents += "$scriptInline".Replace("`r`n", "`n").Replace("`n", "`r`n")
+ } else {
+ $contents += ". '$("$scriptPath".Replace("'", "''"))' $scriptArguments".Trim()
+ }
+
+ # Write the script to disk.
+ $__vstsAzPSScriptPath = [System.IO.Path]::Combine($env:Agent_TempDirectory, ([guid]::NewGuid().ToString() + ".ps1"));
+ $joinedContents = [System.String]::Join(
+ ([System.Environment]::NewLine),
+ $contents)
+ $null = [System.IO.File]::WriteAllText(
+ $__vstsAzPSScriptPath,
+ $joinedContents,
+ ([System.Text.Encoding]::UTF8))
+
+ # Prepare the external command values.
+ #
+ # Note, use "-Command" instead of "-File". On PowerShell V5, V4 and V3 when using "-File", terminating
+ # errors do not cause a non-zero exit code.
+ if ($input_pwsh) {
+ $powershellPath = Get-Command -Name pwsh.exe -CommandType Application | Select-Object -First 1 -ExpandProperty Path
+ } else {
+ $powershellPath = Get-Command -Name powershell.exe -CommandType Application | Select-Object -First 1 -ExpandProperty Path
+ }
+ Assert-VstsPath -LiteralPath $powershellPath -PathType 'Leaf'
+ $arguments = "-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command `". '$($__vstsAzPSScriptPath.Replace("'", "''"))'`""
+ $splat = @{
+ 'FileName' = $powershellPath
+ 'Arguments' = $arguments
+ 'WorkingDirectory' = $input_workingDirectory
+ }
+
+ # Switch to "Continue".
+ $global:ErrorActionPreference = 'Continue'
+ $failed = $false
+
+ # Run the script.
+ Write-Host '========================== Starting Command Output ==========================='
+ if (!$__vsts_input_failOnStandardError) {
+ Invoke-VstsTool @splat
+ }
+ else {
+ $inError = $false
+ $errorLines = New-Object System.Text.StringBuilder
+ Invoke-VstsTool @splat 2>&1 |
+ ForEach-Object {
+ if ($_ -is [System.Management.Automation.ErrorRecord]) {
+ # Buffer the error lines.
+ $failed = $true
+ $inError = $true
+ $null = $errorLines.AppendLine("$($_.Exception.Message)")
+
+ # Write to verbose to mitigate if the process hangs.
+ Write-Verbose "STDERR: $($_.Exception.Message)"
+ } else {
+ # Flush the error buffer.
+ if ($inError) {
+ $inError = $false
+ $message = $errorLines.ToString().Trim()
+ $null = $errorLines.Clear()
+ if ($message) {
+ Write-VstsTaskError -Message $message
+ }
+ }
+
+ Write-Host "$_"
+ }
+ }
+
+ # Flush the error buffer one last time.
+ if ($inError) {
+ $inError = $false
+ $message = $errorLines.ToString().Trim()
+ $null = $errorLines.Clear()
+ if ($message) {
+ Write-VstsTaskError -Message $message
+ }
+ }
+ }
+
+ # Fail if any errors.
+ if ($failed) {
+ Write-VstsSetResult -Result 'Failed' -Message "Error detected" -DoNotThrow
+ }
+}
+finally {
+ if ($__vstsAzPSInlineScriptPath -and (Test-Path -LiteralPath $__vstsAzPSInlineScriptPath) ) {
+ Remove-Item -LiteralPath $__vstsAzPSInlineScriptPath -ErrorAction 'SilentlyContinue'
+ }
+
+ Import-Module $PSScriptRoot\ps_modules\VstsAzureHelpers_
+ Remove-EndpointSecrets
+ Disconnect-AzureAndClearContext -ErrorAction SilentlyContinue
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/CoreAz.ps1 b/Tasks/AzurePowerShellV5/CoreAz.ps1
new file mode 100644
index 000000000000..fdc17a75904a
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/CoreAz.ps1
@@ -0,0 +1,21 @@
+[CmdletBinding()]
+param
+(
+ [String] [Parameter(Mandatory = $true)]
+ $endpoint,
+
+ [String] [Parameter(Mandatory = $false)]
+ $targetAzurePs
+)
+
+Import-Module "$PSScriptRoot\ps_modules\VstsTaskSdk" -ArgumentList @{ NonInteractive = $true }
+Import-VstsLocStrings -LiteralPath "$PSScriptRoot\task.json"
+
+# Update PSModulePath for hosted agent
+. "$PSScriptRoot\Utility.ps1"
+CleanUp-PSModulePathForHostedAgent
+Update-PSModulePathForHostedAgent -targetAzurePs $targetAzurePs
+
+$endpointObject = ConvertFrom-Json $endpoint
+Import-Module "$PSScriptRoot\ps_modules\VstsAzureHelpers_"
+Initialize-AzModule -Endpoint $endpointObject -azVersion $targetAzurePs
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/InitializeAz.ps1 b/Tasks/AzurePowerShellV5/InitializeAz.ps1
new file mode 100644
index 000000000000..3553203e43bd
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/InitializeAz.ps1
@@ -0,0 +1,106 @@
+[CmdletBinding()]
+param
+(
+ [String] [Parameter(Mandatory = $true)]
+ $endpoint,
+
+ [String] [Parameter(Mandatory = $false)]
+ $targetAzurePs
+)
+
+$endpointObject = ConvertFrom-Json $endpoint
+$moduleName = "Az.Accounts"
+$environmentName = $endpointObject.environment
+
+. "$PSScriptRoot/Utility.ps1"
+Update-PSModulePathForHostedAgentLinux -targetAzurePs $targetAzurePs
+
+if($targetAzurePs -eq ""){
+ $module = Get-Module -Name $moduleName -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1
+}
+else{
+ $modules = Get-Module -Name $moduleName -ListAvailable
+ foreach ($moduleVal in $modules) {
+ # $moduleVal.Path will have value like /usr/local/share/powershell/Modules/Az.Accounts/1.2.1/Az.Accounts.psd1
+ $azModulePath = Split-Path (Split-Path (Split-Path $moduleVal.Path -Parent) -Parent) -Parent
+ $azModulePath = $azModulePath + "/Az/*"
+ $azModuleVersion = split-path -path $azModulePath -Leaf -Resolve
+ if($azModuleVersion -eq $targetAzurePs) {
+ $module = $moduleVal
+ break
+ }
+ }
+}
+
+if (!$module) {
+ # Will handle localization later
+ Write-Verbose "No module found with name: $moduleName"
+ throw ("Could not find the module Az.Accounts with given version. If the module was recently installed, retry after restarting the Azure Pipelines task agent.")
+}
+
+# Import the module.
+Write-Host "##[command]Import-Module -Name $($module.Path) -Global"
+$module = Import-Module -Name $module.Path -Global -PassThru -Force
+
+# Clear context
+Write-Host "##[command]Clear-AzContext -Scope Process"
+$null = Clear-AzContext -Scope Process
+Write-Host "##[command]Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue"
+$null = Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
+
+$scopeLevel = "Subscription"
+if($endpointObject.scopeLevel) {
+ $scopeLevel = $endpointObject.scopeLevel
+}
+
+function Format-Splat {
+ [CmdletBinding()]
+ param([Parameter(Mandatory = $true)][hashtable]$Hashtable)
+
+ # Collect the parameters (names and values) in an array.
+ $parameters = foreach ($key in $Hashtable.Keys) {
+ $value = $Hashtable[$key]
+ # If the value is a bool, format the parameter as a switch (ending with ':').
+ if ($value -is [bool]) { "-$($key):" } else { "-$key" }
+ $value
+ }
+
+ "$parameters" # String join the array.
+}
+
+if ($endpointObject.scheme -eq 'ServicePrincipal') {
+ try {
+ if ($endpointObject.authenticationType -ieq 'SPNKey') {
+ $psCredential = New-Object System.Management.Automation.PSCredential(
+ $endpointObject.servicePrincipalClientID,
+ (ConvertTo-SecureString $endpointObject.servicePrincipalKey -AsPlainText -Force))
+ Write-Host "##[command]Connect-AzAccount -ServicePrincipal -Tenant $($endpointObject.tenantId) -Credential $psCredential -Environment $environmentName"
+ $null = Connect-AzAccount -ServicePrincipal -Tenant $endpointObject.tenantId `
+ -Credential $psCredential `
+ -Environment $environmentName -WarningAction SilentlyContinue
+ }
+ else {
+ # Provide an additional, custom, credentials-related error message. Will handle localization later
+ throw ("Only SPN credential auth scheme is supported for non windows agent.")
+ }
+ }
+ catch {
+ # Provide an additional, custom, credentials-related error message. Will handle localization later
+ Write-Host "Exception is : $($_.Exception.Message)"
+ throw (New-Object System.Exception("There was an error with the service principal used for the deployment.", $_.Exception))
+ }
+
+ if($scopeLevel -eq "Subscription")
+ {
+ $SubscriptionId = $endpointObject.subscriptionId
+ $TenantId = $endpointObject.tenantId
+ $additional = @{ TenantId = $TenantId }
+
+ Write-Host "##[command] Set-AzContext -SubscriptionId $SubscriptionId $(Format-Splat $additional)"
+ $null = Set-AzContext -SubscriptionId $SubscriptionId @additional
+ }
+}
+else {
+ # Provide an additional, custom, credentials-related error message. Will handle localization later
+ throw ("Only SPN credential auth scheme is supported for non windows agent.")
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/de-de/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/de-de/resources.resjson
new file mode 100644
index 000000000000..860e77fb0ff7
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/de-de/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Weitere Informationen](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "PowerShell-Skript innerhalb einer Azure-Umgebung ausführen",
+ "loc.instanceNameFormat": "Azure PowerShell-Skript: $(ScriptType)",
+ "loc.releaseNotes": "Unterstützung für Az-Modul und plattformübergreifende Agents hinzugefügt.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell-Versionsoptionen",
+ "loc.input.label.ConnectedServiceNameARM": "Azure-Abonnement",
+ "loc.input.help.ConnectedServiceNameARM": "Azure Resource Manager-Abonnement, das vor dem Ausführen von PowerShell konfiguriert wird.",
+ "loc.input.label.ScriptType": "Skripttyp",
+ "loc.input.help.ScriptType": "Der Typ des Skripts: Dateipfad oder Inlineskript.",
+ "loc.input.label.ScriptPath": "Skriptpfad",
+ "loc.input.help.ScriptPath": "Der Pfad des Skripts. Es muss sich um den vollqualifizierten Pfad oder einen Pfad relativ zum Standardarbeitsverzeichnis handeln.",
+ "loc.input.label.Inline": "Inlineskript",
+ "loc.input.help.Inline": "Geben Sie das Skript ein, das ausgeführt werden soll.",
+ "loc.input.label.ScriptArguments": "Skriptargumente",
+ "loc.input.help.ScriptArguments": "Zusätzliche Argumente, die an PowerShell übergeben werden sollen. Entweder Ordnungszahl- oder benannte Parameter.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Wählen Sie den Wert der Variablen \"ErrorActionPreference\" für die Skriptausführung.",
+ "loc.input.label.FailOnStandardError": "Fehler bei Standardfehler.",
+ "loc.input.help.FailOnStandardError": "Wenn dieser Wert TRUE ist, tritt ein Aufgabenfehler auf, wenn Fehler in die Fehlerpipeline oder Daten in den Standard-Fehlerdatenstrom geschrieben werden.",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell-Version",
+ "loc.input.help.TargetAzurePs": "Im Falle gehosteter Agents wird die folgende Azure PowerShell-Version unterstützt: 1.0.0(Hosted VS2017 Queue).\nWenn Sie die neueste für den Agent verfügbare Version auswählen möchten, wählen Sie \"Neueste installierte Version\".\n\nBei privaten Agents können Sie mithilfe von \"Version angeben\" die bevorzugte Version von Azure PowerShell festlegen.",
+ "loc.input.label.CustomTargetAzurePs": "Bevorzugte Azure PowerShell-Version",
+ "loc.input.help.CustomTargetAzurePs": "Die bevorzugte Azure PowerShell-Version muss eine ordnungsgemäße semantische Version sein, z. B. \"1.2.3\". Reguläre Ausdrücke wie 2.\\*,2.3.\\* werden nicht unterstützt. Der gehostete VS2017-Pool unterstützt aktuell die Az-Modulversion 1.0.0.",
+ "loc.messages.InvalidScriptArguments0": "Ungültige Skriptargumente \"{0}\". Zeilenumbrüche sind unzulässig.",
+ "loc.messages.InvalidScriptPath0": "Ungültiger Skriptpfad \"{0}\". Es wurden ungültige Pfadzeichen angegeben.",
+ "loc.messages.InvalidAzurePsVersion": "Die angegebene Azure PowerShell-Version \"{0}\" weist nicht das richtige Format auf. Überprüfen Sie das Format. Ein Beispiel für das richtige Format ist etwa 1.0.1.",
+ "loc.messages.JS_ExitCode": "PowerShell wurde beendet mit dem Code \"%s\".",
+ "loc.messages.JS_Stderr": "PowerShell hat mindestens eine Zeile in den Standardfehlerstream geschrieben.",
+ "loc.messages.ExpiredServicePrincipal": "Das Zugriffstoken für Azure konnte nicht abgerufen werden. Stellen Sie sicher, dass der verwendete Dienstprinzipal gültig und nicht abgelaufen ist."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/en-US/resources.resjson
new file mode 100644
index 000000000000..28a2fe45aca9
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/en-US/resources.resjson
@@ -0,0 +1,39 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Learn more about this task](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Run a PowerShell script within an Azure environment",
+ "loc.instanceNameFormat": "Azure PowerShell script: $(ScriptType)",
+ "loc.releaseNotes": "Added support for Az Module and cross platform agents.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell version options",
+ "loc.group.displayName.advanced": "Advanced",
+ "loc.input.label.ConnectedServiceNameARM": "Azure Subscription",
+ "loc.input.help.ConnectedServiceNameARM": "Azure Resource Manager subscription to configure before running PowerShell",
+ "loc.input.label.ScriptType": "Script Type",
+ "loc.input.help.ScriptType": "Type of the script: File Path or Inline Script",
+ "loc.input.label.ScriptPath": "Script Path",
+ "loc.input.help.ScriptPath": "Path of the script. Should be fully qualified path or relative to the default working directory.",
+ "loc.input.label.Inline": "Inline Script",
+ "loc.input.help.Inline": "Enter the script to execute.",
+ "loc.input.label.ScriptArguments": "Script Arguments",
+ "loc.input.help.ScriptArguments": "Additional parameters to pass to PowerShell. Can be either ordinal or named parameters.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Select the value of the ErrorActionPreference variable for executing the script.",
+ "loc.input.label.FailOnStandardError": "Fail on Standard Error",
+ "loc.input.help.FailOnStandardError": "If this is true, this task will fail if any errors are written to the error pipeline, or if any data is written to the Standard Error stream.",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell Version",
+ "loc.input.help.TargetAzurePs": "In case of hosted agents, the supported Azure PowerShell Version is: 1.0.0(Hosted VS2017 Queue).\nTo pick the latest version available on the agent, select \"Latest installed version\".\n\nFor private agents you can specify preferred version of Azure PowerShell using \"Specify version\"",
+ "loc.input.label.CustomTargetAzurePs": "Preferred Azure PowerShell Version",
+ "loc.input.help.CustomTargetAzurePs": "Preferred Azure PowerShell Version needs to be a proper semantic version eg. 1.2.3. Regex like 2.\\*,2.3.\\* is not supported. The Hosted VS2017 Pool currently supports Az module version: 1.0.0",
+ "loc.input.label.pwsh": "Use PowerShell Core",
+ "loc.input.help.pwsh": "If this is true, then on Windows the task will use pwsh.exe from your PATH instead of powershell.exe.",
+ "loc.input.label.workingDirectory": "Working Directory",
+ "loc.input.help.workingDirectory": "Working directory where the script is run.",
+ "loc.messages.GeneratingScript": "Generating script.",
+ "loc.messages.JS_FormattedCommand": "Formatted command: %s",
+ "loc.messages.InvalidScriptArguments0": "Invalid script arguments '{0}'. Line breaks are not allowed.",
+ "loc.messages.InvalidScriptPath0": "Invalid script path '{0}'. Invalid path characters specified.",
+ "loc.messages.InvalidAzurePsVersion": "The Azure PowerShell version '{0}' specified is not in the correct format. Please check the format. An example of correct format is 1.0.1",
+ "loc.messages.JS_ExitCode": "PowerShell exited with code '%s'.",
+ "loc.messages.JS_Stderr": "PowerShell wrote one or more lines to the standard error stream.",
+ "loc.messages.ExpiredServicePrincipal": "Could not fetch access token for Azure. Verify if the Service Principal used is valid and not expired."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/es-es/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/es-es/resources.resjson
new file mode 100644
index 000000000000..a5f15c666cb0
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/es-es/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Más información](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Ejecutar un script de PowerShell en un entorno de Azure",
+ "loc.instanceNameFormat": "Script de Azure PowerShell: $(ScriptType)",
+ "loc.releaseNotes": "Se ha agregado compatibilidad con el módulo Az y los agentes multiplataforma.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Opciones de versión de Azure PowerShell",
+ "loc.input.label.ConnectedServiceNameARM": "Suscripción a Azure",
+ "loc.input.help.ConnectedServiceNameARM": "Suscripción de Azure Resource Manager para configurar antes de ejecutar PowerShell",
+ "loc.input.label.ScriptType": "Tipo de script",
+ "loc.input.help.ScriptType": "Tipo del script: ruta de acceso del archivo o script en línea",
+ "loc.input.label.ScriptPath": "Ruta de acceso del script",
+ "loc.input.help.ScriptPath": "Ruta de acceso del script. Debe ser una ruta de acceso completa o relativa al directorio de trabajo predeterminado.",
+ "loc.input.label.Inline": "Script alineado",
+ "loc.input.help.Inline": "Escriba el script que se va a ejecutar.",
+ "loc.input.label.ScriptArguments": "Argumentos de script",
+ "loc.input.help.ScriptArguments": "Parámetros adicionales que pasar a PowerShell. Pueden ser parámetros ordinales o con nombre.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Seleccione el valor de la variable ErrorActionPreference para ejecutar el script.",
+ "loc.input.label.FailOnStandardError": "Error si se produce un error estándar",
+ "loc.input.help.FailOnStandardError": "Si es true, se producirá un error en la tarea si se escriben errores en la canalización de errores o si se escriben datos en el flujo de error estándar.",
+ "loc.input.label.TargetAzurePs": "Versión de Azure PowerShell",
+ "loc.input.help.TargetAzurePs": "En el caso de agentes hospedados, la versión de Azure PowerShell admitida es 1.0.0(Hosted VS2017 Queue).\nPara elegir la última versión disponible en el agente, seleccione \"Latest installed version\".\n\nPara agentes privados, puede especificar la versión de Azure PowerShell que prefiera con la opción \"Specify version\".",
+ "loc.input.label.CustomTargetAzurePs": "Versión de Azure PowerShell preferida",
+ "loc.input.help.CustomTargetAzurePs": "La versión preferida de Azure PowerShell debe ser una versión de semántica adecuada, por ejemplo, 1.2.3. No se admite una expresión regular como 2.\\*,2.3.\\*. El grupo Hosted VS2017 Pool es compatible con la versión del módulo Az 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "Argumentos de script '{0}' no válidos. No se permiten los saltos de línea.",
+ "loc.messages.InvalidScriptPath0": "Ruta del script '{0}' no válida. Los caracteres de ruta de acceso especificados no son válidos.",
+ "loc.messages.InvalidAzurePsVersion": "La versión de Azure PowerShell \"{0}\" especificada no tiene el formato correcto. Compruebe el formato. Ejemplo de formato correcto: 1.0.1",
+ "loc.messages.JS_ExitCode": "PowerShell se cerró con el código \"%s\".",
+ "loc.messages.JS_Stderr": "PowerShell escribió una o varias líneas en la secuencia de error estándar.",
+ "loc.messages.ExpiredServicePrincipal": "No se pudo capturar el token de acceso de Azure. Compruebe que la entidad de servicio usada es válida y no ha expirado."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/fr-fr/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/fr-fr/resources.resjson
new file mode 100644
index 000000000000..dc1ab94ee66b
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/fr-fr/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Plus d'informations](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Exécuter un script PowerShell dans un environnement Azure",
+ "loc.instanceNameFormat": "Script Azure PowerShell : $(ScriptType)",
+ "loc.releaseNotes": "Ajout de la prise en charge du module Azure et des agents multiplateformes.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Options de version Azure PowerShell",
+ "loc.input.label.ConnectedServiceNameARM": "Abonnement Azure",
+ "loc.input.help.ConnectedServiceNameARM": "Abonnement Azure Resource Manager à configurer avant d'exécuter PowerShell",
+ "loc.input.label.ScriptType": "Type de script",
+ "loc.input.help.ScriptType": "Type du script : chemin de fichier ou script inline",
+ "loc.input.label.ScriptPath": "Chemin d'accès du script",
+ "loc.input.help.ScriptPath": "Chemin d'accès du script. Doit être un chemin d'accès complet ou relatif au répertoire de travail par défaut.",
+ "loc.input.label.Inline": "Script inline",
+ "loc.input.help.Inline": "Entrez le script à exécuter.",
+ "loc.input.label.ScriptArguments": "Arguments de script",
+ "loc.input.help.ScriptArguments": "Paramètres supplémentaires à passer à PowerShell. Peuvent être des paramètres ordinaux ou nommés.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Sélectionnez la valeur de la variable ErrorActionPreference pour l'exécution du script.",
+ "loc.input.label.FailOnStandardError": "Échec sur une erreur standard",
+ "loc.input.help.FailOnStandardError": "Si la valeur est true, et si des erreurs sont écrites dans le pipeline d'erreurs ou si des données sont écrites dans le flux d'erreurs standard, cette tâche se solde par un échec.",
+ "loc.input.label.TargetAzurePs": "Version d'Azure PowerShell",
+ "loc.input.help.TargetAzurePs": "Dans le cas d'agents hébergés, la version d'Azure PowerShell prise en charge est la suivante : 1.0.0 (file d'attente VS2017 hébergée).\nPour choisir la dernière version disponible sur l'agent, sélectionnez \"Dernière version installée\".\n\nPour les agents privés, vous pouvez spécifier la version préférée d'Azure PowerShell à l'aide de l'option \"Spécifier la version\"",
+ "loc.input.label.CustomTargetAzurePs": "Version préférée d'Azure PowerShell",
+ "loc.input.help.CustomTargetAzurePs": "La version préférée d'Azure PowerShell doit être une version sémantique appropriée. Par exemple, 1.2.3. La notation regex telle que 2.\\*,2.3.\\* n'est pas prise en charge. Le pool VS2017 hébergé prend en charge la version de module Azure suivante : 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "Arguments de script '{0}' non valides. Les sauts de ligne ne sont pas autorisés.",
+ "loc.messages.InvalidScriptPath0": "Chemin de script '{0}' non valide. Caractères non valides spécifiés dans le chemin.",
+ "loc.messages.InvalidAzurePsVersion": "La version '{0}' spécifiée pour Azure PowerShell n'est pas au format approprié. Vérifiez le format. Exemple de format correct : 1.0.1",
+ "loc.messages.JS_ExitCode": "Arrêt de PowerShell. Code de sortie : '%s'.",
+ "loc.messages.JS_Stderr": "PowerShell a écrit une ou plusieurs lignes dans le flux d'erreurs standard.",
+ "loc.messages.ExpiredServicePrincipal": "Impossible de récupérer (fetch) le jeton d'accès pour Azure. Vérifiez si le principal de service utilisé est valide et s'il n'a pas expiré."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/it-IT/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/it-IT/resources.resjson
new file mode 100644
index 000000000000..45c3b09424a9
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/it-IT/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Altre informazioni](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Consente di eseguire uno script PowerShell in un ambiente Azure",
+ "loc.instanceNameFormat": "Script Azure PowerShell: $(ScriptType)",
+ "loc.releaseNotes": "È stato aggiunto il supporto per il modulo AZ e gli agenti multipiattaforma.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Opzioni della versione di Azure PowerShell",
+ "loc.input.label.ConnectedServiceNameARM": "Sottoscrizione di Azure",
+ "loc.input.help.ConnectedServiceNameARM": "Sottoscrizione di Azure Resource Manager da configurare prima di eseguire PowerShell",
+ "loc.input.label.ScriptType": "Tipo di script",
+ "loc.input.help.ScriptType": "Tipo dello script: Percorso file o Script inline",
+ "loc.input.label.ScriptPath": "Percorso script",
+ "loc.input.help.ScriptPath": "Percorso dello script. Deve essere un percorso completo o relativo rispetto alla directory di lavoro predefinita.",
+ "loc.input.label.Inline": "Script inline",
+ "loc.input.help.Inline": "Consente di immettere lo script da eseguire.",
+ "loc.input.label.ScriptArguments": "Argomenti script",
+ "loc.input.help.ScriptArguments": "Parametri aggiuntivi da passare a PowerShell. Possono essere ordinali o denominati.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Consente di selezionare il valore della variabile ErrorActionPreference per l'esecuzione dello script.",
+ "loc.input.label.FailOnStandardError": "Interrompi in caso di errore standard",
+ "loc.input.help.FailOnStandardError": "Se il valore è true, questa attività non riuscirà nel caso in cui vengano scritti errori nella pipeline degli errori oppure se vengono scritti dati nel flusso STDERR.",
+ "loc.input.label.TargetAzurePs": "Versione di Azure PowerShell",
+ "loc.input.help.TargetAzurePs": "Nel caso degli agenti ospitati la versione supportata di Azure PowerShell è la 1.0.0(Hosted VS2017 Queue).\nPer selezionare l'ultima versione disponibile per l'agente ospitato, selezionare \"Ultima versione installata\".\n\nPer gli agenti privati è possibile specificare la versione preferita di Azure PowerShell usando \"Specifica versione\"",
+ "loc.input.label.CustomTargetAzurePs": "Versione preferita di Azure PowerShell",
+ "loc.input.help.CustomTargetAzurePs": "La versione preferita di Azure PowerShell deve essere una versione semantica valida, ad esempio 1.2.3. Espressioni regolari come 2.\\*,2.3.\\* non sono supportate. Il pool Hosted VS2017 supporta attualmente la versione 1.0.0 del modulo Az",
+ "loc.messages.InvalidScriptArguments0": "Gli argomenti '{0}' dello script non sono validi. Le interruzioni di riga non sono consentite.",
+ "loc.messages.InvalidScriptPath0": "Il percorso '{0}' dello script non è valido. Sono stati specificati caratteri non validi.",
+ "loc.messages.InvalidAzurePsVersion": "Il formato della versione di Azure PowerShell '{0}' specificata non è corretto. Controllare il formato. Un esempio di formato corretto è 1.0.1",
+ "loc.messages.JS_ExitCode": "PowerShell terminato con codice '%s'.",
+ "loc.messages.JS_Stderr": "PowerShell ha scritto una o più righe nel flusso di errore standard.",
+ "loc.messages.ExpiredServicePrincipal": "Non è stato possibile recuperare il token di accesso per Azure. Verificare che l'entità servizio usata sia valida e non sia scaduta."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/ja-jp/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ja-jp/resources.resjson
new file mode 100644
index 000000000000..d573c1c33fe2
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ja-jp/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[詳細](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Azure 環境内で PowerShell スクリプトを実行します",
+ "loc.instanceNameFormat": "Azure PowerShell スクリプト: $(ScriptType)",
+ "loc.releaseNotes": "Az モジュールとクロス プラットフォームのエージェントのサポートが追加されました。",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell バージョンのオプション",
+ "loc.input.label.ConnectedServiceNameARM": "Azure サブスクリプション",
+ "loc.input.help.ConnectedServiceNameARM": "PowerShell を実行する前に構成する Azure Resource Manager サブスクリプション",
+ "loc.input.label.ScriptType": "スクリプトの種類",
+ "loc.input.help.ScriptType": "スクリプトの種類: ファイル パスまたはインライン スクリプト",
+ "loc.input.label.ScriptPath": "スクリプト パス",
+ "loc.input.help.ScriptPath": "スクリプトのパス。完全修飾パスか、既定の作業ディレクトリを基準とした相対パスのいずれかです。",
+ "loc.input.label.Inline": "インライン スクリプト",
+ "loc.input.help.Inline": "実行するスクリプトを入力します。",
+ "loc.input.label.ScriptArguments": "スクリプトの引数",
+ "loc.input.help.ScriptArguments": "PowerShell に渡す追加のパラメーター。順序によるパラメーターまたは名前指定されたパラメーターのいずれかです。",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "スクリプトを実行するための ErrorActionPreference 変数の値を選択します。",
+ "loc.input.label.FailOnStandardError": "標準エラーで失敗",
+ "loc.input.help.FailOnStandardError": "これが true の場合、何らかのエラーがエラー パイプラインに書き込まれるか、何らかのデータが標準エラー ストリームに書き込まれる場合、このタスクは失敗します。",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell バージョン",
+ "loc.input.help.TargetAzurePs": "ホステッド エージェントの場合、サポートされている Azure PowerShell のバージョンは、1.0.0(Hosted VS2017 キュー) です。\nエージェントで利用可能な最新バージョンを選ぶには、[Latest installed version] (インストールされた最新バージョン) を選択します。\n\nプライベート エージェントには、[Specify version] (バージョンを指定する) を使用して好みのバージョンの Azure PowerShell を指定できます。",
+ "loc.input.label.CustomTargetAzurePs": "優先される Azure PowerShell バージョン",
+ "loc.input.help.CustomTargetAzurePs": "推奨の Azure PowerShell バージョンは、1.2.3 などの適切なセマンティック バージョンである必要があります。2.\\*、2.3.\\* などの RegEx はサポートされていません。Hosted VS2017 プールは、現在次の Az モジュール バージョンをサポートしています: 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "スクリプトの引数 '{0}' が無効です。改行は使用できません。",
+ "loc.messages.InvalidScriptPath0": "スクリプト パス '{0}' が無効です。無効なパス文字が指定されました。",
+ "loc.messages.InvalidAzurePsVersion": "指定した Azure PowerShell バージョン '{0}' は、形式が正しくありません。形式をご確認ください。正しい形式の例は、1.0.1 です",
+ "loc.messages.JS_ExitCode": "PowerShell がコード '%s' で終了しました。",
+ "loc.messages.JS_Stderr": "PowerShell が標準エラー ストリームに 1 行以上を書き込みました。",
+ "loc.messages.ExpiredServicePrincipal": "Azure のアクセス トークンをフェッチできませんでした。使用されているサービス プリンシパルが有効であり、有効期限が切れていないことを確認してください。"
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/ko-KR/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ko-KR/resources.resjson
new file mode 100644
index 000000000000..9aa8925d44d8
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ko-KR/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[자세한 정보](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Azure 환경에서 PowerShell 스크립트 실행",
+ "loc.instanceNameFormat": "Azure PowerShell 스크립트: $(ScriptType)",
+ "loc.releaseNotes": "Az 모듈 및 플랫폼 간 에이전트에 대한 지원이 추가되었습니다.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell 버전 옵션",
+ "loc.input.label.ConnectedServiceNameARM": "Azure 구독",
+ "loc.input.help.ConnectedServiceNameARM": "PowerShell을 실행하기 전에 구성할 Azure Resource Manager 구독",
+ "loc.input.label.ScriptType": "스크립트 유형",
+ "loc.input.help.ScriptType": "스크립트 유형: 파일 경로 또는 인라인 스크립트",
+ "loc.input.label.ScriptPath": "스크립트 경로",
+ "loc.input.help.ScriptPath": "스크립트의 경로입니다. 정규화된 경로이거나 기본 작업 디렉터리에 대한 상대 경로여야 합니다.",
+ "loc.input.label.Inline": "인라인 스크립트",
+ "loc.input.help.Inline": "실행할 스크립트를 입력합니다.",
+ "loc.input.label.ScriptArguments": "스크립트 인수",
+ "loc.input.help.ScriptArguments": "PowerShell에 전달할 추가 인수입니다. 서수 매개 변수나 명명된 매개 변수 중 하나일 수 있습니다.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "스크립트 실행에 대한 ErrorActionPreference 변수의 값을 선택합니다.",
+ "loc.input.label.FailOnStandardError": "표준 오류 시 실패",
+ "loc.input.help.FailOnStandardError": "이 값이 true이면 오류 파이프라인에 오류가 작성되거나 표준 오류 스트림에 데이터가 작성될 경우 이 작업은 실패하게 됩니다.",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell 버전",
+ "loc.input.help.TargetAzurePs": "호스트된 에이전트의 경우 지원되는 Azure PowerShell 버전은 1.0.0(Hosted VS2017 Queue)입니다.\n에이전트에서 사용 가능한 최신 버전을 선택하려면 \"설치된 최신 버전\"을 선택합니다.\n\n프라이빗 에이전트의 경우 \"버전 지정\"을 사용하여 기본 Azure PowerShell 버전을 지정할 수 있습니다.",
+ "loc.input.label.CustomTargetAzurePs": "기본 Azure PowerShell 버전",
+ "loc.input.help.CustomTargetAzurePs": "기본 Azure PowerShell 버전이 올바른 의미 체계 버전(예: 1.2.3)이어야 합니다. 2.\\*,2.3.\\*와 같은 Regex는 지원되지 않습니다. 호스트된 VS2017 풀은 현재 Az 모듈 버전 1.0.0을 지원합니다.",
+ "loc.messages.InvalidScriptArguments0": "스크립트 인수 '{0}'이(가) 잘못되었습니다. 줄 바꿈은 허용되지 않습니다.",
+ "loc.messages.InvalidScriptPath0": "스크립트 경로 '{0}'이(가) 잘못되었습니다. 잘못된 경로 문자를 지정했습니다.",
+ "loc.messages.InvalidAzurePsVersion": "지정한 Azure PowerShell 버전 '{0}'의 형식이 잘못되었습니다. 형식을 확인하세요. 올바른 형식의 예는 1.0.1입니다.",
+ "loc.messages.JS_ExitCode": "PowerShell이 코드 '%s'(으)로 종료되었습니다.",
+ "loc.messages.JS_Stderr": "PowerShell이 표준 오류 스트림에 하나 이상의 줄을 썼습니다.",
+ "loc.messages.ExpiredServicePrincipal": "Azure의 액세스 토큰을 페치할 수 없습니다. 사용한 서비스 주체가 유효하고 만료되지 않았는지 확인하세요."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/ru-RU/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ru-RU/resources.resjson
new file mode 100644
index 000000000000..7e508f3826e6
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/ru-RU/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[Подробнее...](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "Выполнение скрипта PowerShell в среде Azure",
+ "loc.instanceNameFormat": "Сценарий Azure PowerShell: $(ScriptType)",
+ "loc.releaseNotes": "Добавлена поддержка модуля Az и кроссплатформенных агентов.",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Параметры версии Azure PowerShell",
+ "loc.input.label.ConnectedServiceNameARM": "Подписка Azure",
+ "loc.input.help.ConnectedServiceNameARM": "Подписка на Azure Resource Manager для настройки перед запуском PowerShell",
+ "loc.input.label.ScriptType": "Тип сценария",
+ "loc.input.help.ScriptType": "Тип сценария: путь к файлу или встроенный сценарий",
+ "loc.input.label.ScriptPath": "Путь к скрипту",
+ "loc.input.help.ScriptPath": "Путь к сценарию. Это должен быть полный путь или путь относительно рабочего каталога по умолчанию.",
+ "loc.input.label.Inline": "Встроенный сценарий",
+ "loc.input.help.Inline": "Введите сценарий для выполнения.",
+ "loc.input.label.ScriptArguments": "Аргументы скрипта",
+ "loc.input.help.ScriptArguments": "Дополнительные параметры для передачи в PowerShell. Могут быть как порядковыми, так и именованными.",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "Выберите значение переменной ErrorActionPreference для выполнения скрипта.",
+ "loc.input.label.FailOnStandardError": "Сбой со стандартной ошибкой",
+ "loc.input.help.FailOnStandardError": "Если задано значение True, задача будет завершаться сбоем при записи любых ошибок в конвейер ошибок или записи любых данных в стандартный поток ошибок.",
+ "loc.input.label.TargetAzurePs": "Версия Azure PowerShell",
+ "loc.input.help.TargetAzurePs": "Для размещенных агентов поддерживается следующая версия Azure PowerShell: 1.0.0 (размещенная очередь VS2017).\nЧтобы выбрать последнюю версию, доступную в агенте, выберите пункт \"Последняя установленная версия\".\n\nДля частных агентов можно указать предпочтительную версию Azure PowerShell с помощью элемента \"Указать версию\"",
+ "loc.input.label.CustomTargetAzurePs": "Предпочтительная версия Azure PowerShell",
+ "loc.input.help.CustomTargetAzurePs": "Предпочтительная версия Azure PowerShell должна быть надлежащей семантической версией, например 1.2.3. Регулярные выражения, например 2.\\*,2.3.\\*, не поддерживаются. Размещенный пул Visual Studio 2017 сейчас поддерживает версию модуля Az: 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "Недопустимые аргументы скрипта \"{0}\". Разрывы строк запрещены.",
+ "loc.messages.InvalidScriptPath0": "Недопустимый путь к скрипту \"{0}\". Указаны символы, недопустимые в пути.",
+ "loc.messages.InvalidAzurePsVersion": "Указанная версия Azure PowerShell \"{0}\" имеет неправильный формат. Проверьте формат. Пример правильного формата: 1.0.1",
+ "loc.messages.JS_ExitCode": "Завершение работы PowerShell с кодом \"%s\".",
+ "loc.messages.JS_Stderr": "Оболочка PowerShell записала одну или несколько строк в стандартный поток ошибок.",
+ "loc.messages.ExpiredServicePrincipal": "Не удалось получить маркер доступа для Azure. Убедитесь, что используемый субъект-служба является допустимым, а срок его действия не истек."
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-CN/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-CN/resources.resjson
new file mode 100644
index 000000000000..e0327f82aafb
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-CN/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[详细信息](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "在 Azure 环境中运行 PowerShell 脚本",
+ "loc.instanceNameFormat": "Azure PowerShell 脚本: $(ScriptType)",
+ "loc.releaseNotes": "添加了对 Azure 模块和跨平台代理的支持。",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell 版本选项",
+ "loc.input.label.ConnectedServiceNameARM": "Azure 订阅",
+ "loc.input.help.ConnectedServiceNameARM": "在运行 PowerShell 之前配置的 Azure 资源管理器订阅",
+ "loc.input.label.ScriptType": "脚本类型",
+ "loc.input.help.ScriptType": "脚本类型: 文件路径或内联脚本",
+ "loc.input.label.ScriptPath": "脚本路径",
+ "loc.input.help.ScriptPath": "脚本的路径。应是完全限定的路径或相对于默认工作目录。",
+ "loc.input.label.Inline": "内联脚本",
+ "loc.input.help.Inline": "输入要执行的脚本。",
+ "loc.input.label.ScriptArguments": "脚本参数",
+ "loc.input.help.ScriptArguments": "要传递给 PowerShell 的其他参数。可以是序号或命名参数。",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "选择执行脚本的 ErrorActionPreference 变量的值。",
+ "loc.input.label.FailOnStandardError": "因标准错误失败",
+ "loc.input.help.FailOnStandardError": "如果为 true,当有错误被写入错误管道或有数据被写入标准错误流时,此任务将失败。",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell 版本",
+ "loc.input.help.TargetAzurePs": "对于托管代理,受支持的 Azure PowerShell 版本为: 1.0.0(托管的 VS2017 队列)。\n若要在代理上选择最新的可用版本,选择“最新安装的版本”。\n\n对于专用代理,可以使用“指定版本”指定 Azure PowerShell 的首选版本",
+ "loc.input.label.CustomTargetAzurePs": "首选 Azure PowerShell 版本",
+ "loc.input.help.CustomTargetAzurePs": "首选 Azure PowerShell 版本需为正确的语义版本,例如 1.2.3。不支持 2.\\*、2.3.\\* 等正则表达式。托管 VS2017 池当前支持 Azure 模块版本: 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "脚本参数“{0}”无效。不允许换行。",
+ "loc.messages.InvalidScriptPath0": "脚本路径“{0}”无效。指定的路径字符无效。",
+ "loc.messages.InvalidAzurePsVersion": "指定的 Azure PowerShell 版本“{0}”格式不正确。请检查格式。正确格式的示例为 1.0.1",
+ "loc.messages.JS_ExitCode": "PowerShell 已退出,代码为“%s”。",
+ "loc.messages.JS_Stderr": "PowerShell 向标准错误流写入一个或多个行。",
+ "loc.messages.ExpiredServicePrincipal": "无法提取 Azure 的访问令牌。请确保使用的服务主体有效且未过期。"
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-TW/resources.resjson b/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-TW/resources.resjson
new file mode 100644
index 000000000000..8e78c3522555
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Strings/resources.resjson/zh-TW/resources.resjson
@@ -0,0 +1,32 @@
+{
+ "loc.friendlyName": "Azure PowerShell",
+ "loc.helpMarkDown": "[詳細資訊](https://go.microsoft.com/fwlink/?LinkID=613749)",
+ "loc.description": "在 Azure 環境中執行 PowerShell 指令碼",
+ "loc.instanceNameFormat": "Azure PowerShell 指令碼: $(ScriptType)",
+ "loc.releaseNotes": "新增了 Az 模組和跨平台代理程式的支援。",
+ "loc.group.displayName.AzurePowerShellVersionOptions": "Azure PowerShell 版本選項",
+ "loc.input.label.ConnectedServiceNameARM": "Azure 訂用帳戶",
+ "loc.input.help.ConnectedServiceNameARM": "執行 PowerShell 之前要設定的 Azure Resource Manager 訂用帳戶",
+ "loc.input.label.ScriptType": "指令碼類型",
+ "loc.input.help.ScriptType": "指令碼類型: 檔案路徑或內嵌指令碼",
+ "loc.input.label.ScriptPath": "指令碼路徑",
+ "loc.input.help.ScriptPath": "指令碼的路徑。必須是完整路徑名稱或預設工作目錄的相對路徑。",
+ "loc.input.label.Inline": "內嵌指令碼",
+ "loc.input.help.Inline": "請輸入要執行的指令碼。",
+ "loc.input.label.ScriptArguments": "指令碼引數",
+ "loc.input.help.ScriptArguments": "傳遞至 PowerShell 的額外引數。可以是序數或具名參數。",
+ "loc.input.label.errorActionPreference": "ErrorActionPreference",
+ "loc.input.help.errorActionPreference": "請選取用於執行指令碼的 ErrorActionPreference 變數值。",
+ "loc.input.label.FailOnStandardError": "發生標準錯誤的失敗",
+ "loc.input.help.FailOnStandardError": "若此項為 true,如果在錯誤管線中寫入任何錯誤,或在標準錯誤資料流中寫入任何資料,此工作就會失敗。",
+ "loc.input.label.TargetAzurePs": "Azure PowerShell 版本",
+ "loc.input.help.TargetAzurePs": "若為裝載的代理程式,支援的 Azure PowerShell 版本是: 1.0.0 (裝載的 VS2017 佇列)。\n若要挑選代理程式上可用的最新版本,請選取 [最新的安裝版本]。\n\n若為私人代理程式,您可以使用 [指定版本] 指定慣用的 Azure PowerShell 版本",
+ "loc.input.label.CustomTargetAzurePs": "慣用的 Azure PowerShell 版本",
+ "loc.input.help.CustomTargetAzurePs": "慣用的 Azure PowerShell 版本必須是適當的語意版本,例如 1.2.3。不支援 2.\\*、2.3.\\* 這類 Regex。裝載的 VS2017 集區目前支援 Az 模組版本: 1.0.0",
+ "loc.messages.InvalidScriptArguments0": "指令碼引數 '{0}' 無效。不允許分行符號。",
+ "loc.messages.InvalidScriptPath0": "指令碼路徑 '{0}' 無效。指定的路徑字元無效。",
+ "loc.messages.InvalidAzurePsVersion": "指定的 Azure PowerShell 版本 '{0}' 格式不正確。請檢查格式。正確格式的範例為 1.0.1",
+ "loc.messages.JS_ExitCode": "PowerShell 已結束,代碼為 '%s'。",
+ "loc.messages.JS_Stderr": "PowerShell 已將一或多行寫入標準錯誤資料流。",
+ "loc.messages.ExpiredServicePrincipal": "無法擷取 Azure 的存取權杖。請驗證使用的服務主體是否有效且未過期。"
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShell.ps1 b/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShell.ps1
new file mode 100644
index 000000000000..749530f76757
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShell.ps1
@@ -0,0 +1,27 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+$targetAzurePs = "4.1.0"
+Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath
+Register-Mock Get-VstsInput { $targetAzurePs } -- -Name TargetAzurePs
+Register-Mock Get-VstsInput { 'arg1 arg2' } -- -Name ScriptArguments
+Register-Mock Get-VstsInput { "continue" } -- -Name errorActionPreference
+Register-Mock Get-VstsInput { $true } -- -Name FailOnStandardError
+Register-Mock Get-VstsInput { $false } -- -Name pwsh -AsBool
+Register-Mock Update-PSModulePathForHostedAgent
+Register-Mock Get-Module
+Register-Mock Initialize-AzModule
+Register-Mock Get-VstsEndpoint { @{auth = @{ scheme = "ServicePrincipal" }} }
+Register-Mock Remove-EndpointSecrets
+Register-Mock Disconnect-AzureAndClearContext
+Register-Mock Assert-VstsPath
+Register-Mock Invoke-VstsTool { }
+
+# Act.
+$actual = & $PSScriptRoot\..\AzurePowerShell.ps1
+
+Assert-WasCalled Invoke-VstsTool -Times 1
+Assert-WasCalled Invoke-VstsTool -ArgumentsEvaluator {($args | ConvertTo-Json) -like '*powershell.exe*'}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShellCore.ps1 b/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShellCore.ps1
new file mode 100644
index 000000000000..6bfb4ea83f32
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ChecksForPowerShellCore.ps1
@@ -0,0 +1,27 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+$targetAzurePs = "4.1.0"
+Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath
+Register-Mock Get-VstsInput { $targetAzurePs } -- -Name TargetAzurePs
+Register-Mock Get-VstsInput { 'arg1 arg2' } -- -Name ScriptArguments
+Register-Mock Get-VstsInput { "continue" } -- -Name errorActionPreference
+Register-Mock Get-VstsInput { $true } -- -Name FailOnStandardError
+Register-Mock Get-VstsInput { $true } -- -Name pwsh -AsBool
+Register-Mock Update-PSModulePathForHostedAgent
+Register-Mock Get-Module
+Register-Mock Initialize-AzModule
+Register-Mock Get-VstsEndpoint { @{auth = @{ scheme = "ServicePrincipal" }} }
+Register-Mock Remove-EndpointSecrets
+Register-Mock Disconnect-AzureAndClearContext
+Register-Mock Assert-VstsPath
+Register-Mock Invoke-VstsTool { }
+
+# Act.
+$actual = & $PSScriptRoot\..\AzurePowerShell.ps1
+
+Assert-WasCalled Invoke-VstsTool -Times 1
+Assert-WasCalled Invoke-VstsTool -ArgumentsEvaluator {($args | ConvertTo-Json) -like '*pwsh.exe*'}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/ChecksForWorkingDirectory.ps1 b/Tasks/AzurePowerShellV5/Tests/ChecksForWorkingDirectory.ps1
new file mode 100644
index 000000000000..27905b95eac1
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ChecksForWorkingDirectory.ps1
@@ -0,0 +1,29 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+$targetAzurePs = "4.1.0"
+$input_workingDirectory = "C:\Users"
+Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath
+Register-Mock Get-VstsInput { $targetAzurePs } -- -Name TargetAzurePs
+Register-Mock Get-VstsInput { 'arg1 arg2' } -- -Name ScriptArguments
+Register-Mock Get-VstsInput { "continue" } -- -Name errorActionPreference
+Register-Mock Get-VstsInput { $true } -- -Name FailOnStandardError
+Register-Mock Get-VstsInput { $true } -- -Name pwsh -AsBool
+Register-Mock Get-VstsInput { $input_workingDirectory } -- -Name workingDirectory -Require
+Register-Mock Update-PSModulePathForHostedAgent
+Register-Mock Get-Module
+Register-Mock Initialize-AzModule
+Register-Mock Get-VstsEndpoint { @{auth = @{ scheme = "ServicePrincipal" }} }
+Register-Mock Remove-EndpointSecrets
+Register-Mock Disconnect-AzureAndClearContext
+Register-Mock Assert-VstsPath
+Register-Mock Invoke-VstsTool { }
+
+# Act.
+$actual = & $PSScriptRoot\..\AzurePowerShell.ps1
+
+Assert-WasCalled Invoke-VstsTool -Times 1
+Assert-WasCalled Invoke-VstsTool -ArgumentsEvaluator {($args | ConvertTo-Json) -like '*C:\\Users*'}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/L0.ts b/Tasks/AzurePowerShellV5/Tests/L0.ts
new file mode 100644
index 000000000000..23000ff892d3
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/L0.ts
@@ -0,0 +1,58 @@
+///
+///
+///
+
+import Q = require('q');
+import assert = require('assert');
+import path = require('path');
+var psm = require('../../../Tests/lib/psRunner');
+var psr = null;
+
+describe('AzurePowerShell Suite', function () {
+ this.timeout(parseInt(process.env.TASK_TEST_TIMEOUT) || 20000);
+
+ before((done) => {
+ if (psm.testSupported()) {
+ psr = new psm.PSRunner();
+ psr.start();
+ }
+
+ done();
+ });
+
+ after(function () {
+ if (psr) {
+ psr.kill();
+ }
+ });
+
+ if (psm.testSupported()) {
+ it('checks for powershell core', (done) => {
+ psr.run(path.join(__dirname, 'ChecksForPowerShellCore.ps1'), done);
+ })
+ /*it('checks for powershell', (done) => {
+ psr.run(path.join(__dirname, 'ChecksForPowerShell.ps1'), done);
+ })*/
+ it('checks for working directory', (done) => {
+ psr.run(path.join(__dirname, 'ChecksForWorkingDirectory.ps1'), done);
+ })
+ it('performs basic flow', (done) => {
+ psr.run(path.join(__dirname, 'PerformsBasicFlow.ps1'), done);
+ })
+ it('throws when otherversion is specified in a wrong format', (done) => {
+ psr.run(path.join(__dirname, 'ThrowsForInvalidVersion.ps1'), done);
+ })
+ it('throws when invalid script arguments', (done) => {
+ psr.run(path.join(__dirname, 'ThrowsWhenInvalidScriptArguments.ps1'), done);
+ })
+ it('throws when invalid script path', (done) => {
+ psr.run(path.join(__dirname, 'ThrowsWhenInvalidScriptPath.ps1'), done);
+ })
+ it('Get-LatestModule returns the latest available module', (done) => {
+ psr.run(path.join(__dirname, 'Utility.Get-LatestModule.ps1'), done);
+ })
+ it('Update-PSModulePathForHostedAgent updated psmodulepath correctly', (done) => {
+ psr.run(path.join(__dirname, 'Utility.UpdatePSModulePathForHostedAgentWorksCorrectly.ps1'), done);
+ })
+ }
+});
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow.ps1 b/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow.ps1
new file mode 100644
index 000000000000..412ab776ca22
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow.ps1
@@ -0,0 +1,30 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+$targetAzurePs = "4.1.0"
+Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+Register-Mock Get-VstsInput { "$PSScriptRoot/PerformsBasicFlow_TargetScript.ps1" } -- -Name ScriptPath
+Register-Mock Get-VstsInput { $targetAzurePs } -- -Name TargetAzurePs
+Register-Mock Get-VstsInput { 'arg1 arg2' } -- -Name ScriptArguments
+Register-Mock Get-VstsInput { "continue" } -- -Name errorActionPreference
+Register-Mock Get-VstsInput { $true } -- -Name FailOnStandardError
+Register-Mock Update-PSModulePathForHostedAgent
+Register-Mock Get-Module
+Register-Mock Initialize-AzModule
+Register-Mock Get-VstsEndpoint { @{auth = @{ scheme = "ServicePrincipal" }} }
+Register-Mock Remove-EndpointSecrets
+Register-Mock Disconnect-AzureAndClearContext
+Register-Mock Assert-VstsPath
+Register-Mock Invoke-VstsTool { }
+
+# Act.
+$actual = & $PSScriptRoot\..\AzurePowerShell.ps1
+
+# Assert the error action preference was set to Continue.
+Assert-AreEqual "Continue" $global:ErrorActionPreference
+$global:ErrorActionPreference = 'Stop' # Reset to stop.
+
+# Assert the Azure helpers module was imported and invoked.
+Assert-WasCalled Import-Module -- ([System.IO.Path]::GetFullPath("$PSScriptRoot\..\ps_modules\VstsAzureHelpers_"))
diff --git a/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow_TargetScript.ps1 b/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow_TargetScript.ps1
new file mode 100644
index 000000000000..53aafdebcdd8
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/PerformsBasicFlow_TargetScript.ps1
@@ -0,0 +1,4 @@
+# Return key information.
+New-Object psobject -Property @{
+ Args = $args
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/ThrowsForInvalidVersion.ps1 b/Tasks/AzurePowerShellV5/Tests/ThrowsForInvalidVersion.ps1
new file mode 100644
index 000000000000..5afc27858f1e
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ThrowsForInvalidVersion.ps1
@@ -0,0 +1,15 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+
+Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+Register-Mock Get-VstsInput { "foobar.ps1" } -- -Name ScriptPath
+Register-Mock Get-VstsInput { "OtherVersion" } -- -Name TargetAzurePs
+Register-Mock Get-VstsInput { "x.y.z" } -- -Name CustomTargetAzurePs
+
+# Act/Assert.
+Assert-Throws {
+ & $PSScriptRoot\..\AzurePowerShell.ps1
+} -MessagePattern "InvalidAzurePsVersion*x.y.z"
diff --git a/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptArguments.ps1 b/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptArguments.ps1
new file mode 100644
index 000000000000..af93358163bc
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptArguments.ps1
@@ -0,0 +1,14 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+foreach ($arguments in @( "script`rarguments", "script`narguments" )) {
+ Unregister-Mock Get-VstsInput
+ Register-Mock Get-VstsInput { $arguments } -- -Name ScriptArguments
+
+ # Act/Assert.
+ Assert-Throws {
+ & $PSScriptRoot\..\AzurePowerShell.ps1
+ } -MessagePattern "InvalidScriptArguments0*$arguments"
+}
diff --git a/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptPath.ps1 b/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptPath.ps1
new file mode 100644
index 000000000000..a1334790ccba
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/ThrowsWhenInvalidScriptPath.ps1
@@ -0,0 +1,16 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+foreach ($path in @( "script`rpath", "script`npath" )) {
+ Unregister-Mock Get-VstsInput
+ Register-Mock Get-VstsInput { "FilePath" } -- -Name ScriptType -Require
+ Register-Mock Get-VstsInput { $path } -- -Name ScriptPath
+ Register-Mock Get-VstsInput { "4.1.0" } -- -Name TargetAzurePs
+
+ # Act/Assert.
+ Assert-Throws {
+ & $PSScriptRoot\..\AzurePowerShell.ps1
+ } -MessagePattern "InvalidScriptPath0*$path"
+}
diff --git a/Tasks/AzurePowerShellV5/Tests/Utility.Get-LatestModule.ps1 b/Tasks/AzurePowerShellV5/Tests/Utility.Get-LatestModule.ps1
new file mode 100644
index 000000000000..71609db6ede0
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/Utility.Get-LatestModule.ps1
@@ -0,0 +1,30 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+. $PSScriptRoot\..\Utility.ps1
+
+$azModulePath = "c:\modules\az_4.1.0"
+
+$azModulePattern = "^az_[0-9]+\.[0-9]+\.[0-9]+$"
+$versionPattern = "[0-9]+\.[0-9]+\.[0-9]+$"
+
+$mockDirectoryStructure = @(
+ @{
+ Name = "az_4.1.0"
+ FullName = "C:\Modules\az_4.1.0"
+ }
+ @{
+ Name = "az_3.6.0"
+ FullName = "C:\Modules\az_3.6.0"
+ }
+)
+
+Register-Mock Get-ChildItem { $mockDirectoryStructure } -- -Directory -Path "C:\Modules"
+Register-Mock Test-Path { $true }
+
+# Act
+$result = Get-LatestModule -patternToMatch $azModulePattern -patternToExtract $versionPattern
+# Assert
+Assert-AreEqual $result.toLower() $azModulePath
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/Tests/Utility.UpdatePSModulePathForHostedAgentWorksCorrectly.ps1 b/Tasks/AzurePowerShellV5/Tests/Utility.UpdatePSModulePathForHostedAgentWorksCorrectly.ps1
new file mode 100644
index 000000000000..53c9c7875e54
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Tests/Utility.UpdatePSModulePathForHostedAgentWorksCorrectly.ps1
@@ -0,0 +1,47 @@
+[CmdletBinding()]
+param()
+
+# Arrange.
+. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1
+. $PSScriptRoot\..\Utility.ps1
+
+$azModulePath = "c:\modules\az_3.6.0"
+
+$azModulePattern = "^az_[0-9]+\.[0-9]+\.[0-9]+$"
+$versionPattern = "[0-9]+\.[0-9]+\.[0-9]+$"
+
+$variableSets = @(
+ @{
+ targetAzurePsVersion = "3.6.0"
+ azModuleExist = $true
+ }
+ @{
+ targetAzurePsVersion = ""
+ azModulePath = $true
+ }
+)
+
+$temp = $env:PSModulePath
+
+foreach ($variableSet in $variableSets) {
+ $env:PSModulePath = $temp
+ # Arrange
+ Unregister-Mock Get-LatestModule
+ if($variableSet.azModuleExist) {
+ Register-Mock Get-LatestModule { $azModulePath } -- -patternToMatch $azModulePattern -patternToExtract $versionPattern -Classic:$false
+ } else {
+ Register-Mock Get-LatestModule { "" } -- -patternToMatch $azModulePattern -patternToExtract $versionPattern -Classic:$false
+ }
+
+ # Act
+ Update-PSModulePathForHostedAgent -targetAzurePs $variableSet.targetAzurePsVersion
+
+ # Assert
+ if($variableSet.azModuleExist) {
+ Assert-IsGreaterThan -1 $env:PSModulePath.toLower().IndexOf($azModulePath)
+ } else {
+ Assert-AreEqual -1 $env:PSModulePath.toLower().IndexOf($azModulePath)
+ }
+
+ Assert-IsGreaterThan 0 $env:PSModulePath.toLower().IndexOf(";")
+}
diff --git a/Tasks/AzurePowerShellV5/ThirdPartyNotices.txt b/Tasks/AzurePowerShellV5/ThirdPartyNotices.txt
new file mode 100644
index 000000000000..abc33cfd772f
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/ThirdPartyNotices.txt
@@ -0,0 +1,136 @@
+
+THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
+Do Not Translate or Localize
+
+Azure PowerShell incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
+
+1. OpenSSL (http://www.openssl.org)
+
+%% OpenSSL NOTICES, INFORMATION, AND LICENSE BEGIN HERE
+=========================================
+ LICENSE ISSUES
+ ==============
+
+ The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)
+ *
+ * 4. The names OpenSSL Toolkit and OpenSSL Project must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called OpenSSL
+ * nor may OpenSSL appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * This product includes software written by Tim Hudson (tjh@cryptsoft.com)
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+=========================================
+END OF OpenSSL NOTICES, INFORMATION, AND LICENSE
diff --git a/Tasks/AzurePowerShellV5/Utility.ps1 b/Tasks/AzurePowerShellV5/Utility.ps1
new file mode 100644
index 000000000000..b75c7973c2e7
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/Utility.ps1
@@ -0,0 +1,151 @@
+function Get-SavedModulePath {
+ [CmdletBinding()]
+ param([string] $azurePowerShellVersion)
+ $savedModulePath = $($env:SystemDrive + "\Modules\az_" + $azurePowerShellVersion)
+ Write-Verbose "The value of the module path is: $savedModulePath"
+ return $savedModulePath
+}
+
+function Get-SavedModulePathLinux {
+ [CmdletBinding()]
+ param([string] $azurePowerShellVersion)
+ $savedModulePath = $("/usr/share/az_" + $azurePowerShellVersion)
+ Write-Verbose "The value of the module path is: $savedModulePath"
+ return $savedModulePath
+}
+
+function Update-PSModulePathForHostedAgent {
+ [CmdletBinding()]
+ param([string] $targetAzurePs)
+ try {
+ if ($targetAzurePs) {
+ $hostedAgentAzModulePath = Get-SavedModulePath -azurePowerShellVersion $targetAzurePs
+ }
+ else {
+ $hostedAgentAzModulePath = Get-LatestModule -patternToMatch "^az_[0-9]+\.[0-9]+\.[0-9]+$" -patternToExtract "[0-9]+\.[0-9]+\.[0-9]+$"
+ }
+ $env:PSModulePath = $hostedAgentAzModulePath + ";" + $env:PSModulePath
+ $env:PSModulePath = $env:PSModulePath.TrimStart(';')
+ } finally {
+ Write-Verbose "The updated value of the PSModulePath is: $($env:PSModulePath)"
+ }
+}
+
+function Update-PSModulePathForHostedAgentLinux {
+ [CmdletBinding()]
+ param([string] $targetAzurePs)
+ try {
+ if ($targetAzurePs) {
+ $hostedAgentAzModulePath = Get-SavedModulePathLinux -azurePowerShellVersion $targetAzurePs
+ if(!(Test-Path $hostedAgentAzModulePath)) {
+ Write-Verbose "No module path found with this name"
+ throw ("Could not find the module path with given version.")
+ }
+ }
+ else {
+ $hostedAgentAzModulePath = Get-LatestModuleLinux -patternToMatch "^az_[0-9]+\.[0-9]+\.[0-9]+$" -patternToExtract "[0-9]+\.[0-9]+\.[0-9]+$"
+ }
+ $env:PSModulePath = $hostedAgentAzModulePath + ":" + $env:PSModulePath
+ $env:PSModulePath = $env:PSModulePath.TrimStart(':')
+ } finally {
+ Write-Verbose "The updated value of the PSModulePath is: $($env:PSModulePath)"
+ }
+}
+
+function Get-LatestModule {
+ [CmdletBinding()]
+ param([string] $patternToMatch,
+ [string] $patternToExtract)
+
+ $resultFolder = ""
+ $regexToMatch = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToMatch
+ $regexToExtract = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToExtract
+ $maxVersion = [version] "0.0.0"
+ $modulePath = $env:SystemDrive + "\Modules";
+
+ try {
+ if (-not (Test-Path -Path $modulePath)) {
+ return $resultFolder
+ }
+
+ $moduleFolders = Get-ChildItem -Directory -Path $modulePath | Where-Object { $regexToMatch.IsMatch($_.Name) }
+ foreach ($moduleFolder in $moduleFolders) {
+ $moduleVersion = [version] $($regexToExtract.Match($moduleFolder.Name).Groups[0].Value)
+ if($moduleVersion -gt $maxVersion) {
+ $modulePath = [System.IO.Path]::Combine($moduleFolder.FullName,"Az\$moduleVersion\Az.psm1")
+
+ if(Test-Path -LiteralPath $modulePath -PathType Leaf) {
+ $maxVersion = $moduleVersion
+ $resultFolder = $moduleFolder.FullName
+ } else {
+ Write-Verbose "A folder matching the module folder pattern was found at $($moduleFolder.FullName) but didn't contain a valid module file"
+ }
+ }
+ }
+ }
+ catch {
+ Write-Verbose "Attempting to find the Latest Module Folder failed with the error: $($_.Exception.Message)"
+ $resultFolder = ""
+ }
+ Write-Verbose "Latest module folder detected: $resultFolder"
+ return $resultFolder
+}
+
+function Get-LatestModuleLinux {
+ [CmdletBinding()]
+ param([string] $patternToMatch,
+ [string] $patternToExtract)
+
+ $resultFolder = ""
+ $regexToMatch = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToMatch
+ $regexToExtract = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToExtract
+ $maxVersion = [version] "0.0.0"
+
+ try {
+ $moduleFolders = Get-ChildItem -Directory -Path $("/usr/share") | Where-Object { $regexToMatch.IsMatch($_.Name) }
+ foreach ($moduleFolder in $moduleFolders) {
+ $moduleVersion = [version] $($regexToExtract.Match($moduleFolder.Name).Groups[0].Value)
+ if($moduleVersion -gt $maxVersion) {
+ $modulePath = [System.IO.Path]::Combine($moduleFolder.FullName,"Az/$moduleVersion/Az.psm1")
+
+ if(Test-Path -LiteralPath $modulePath -PathType Leaf) {
+ $maxVersion = $moduleVersion
+ $resultFolder = $moduleFolder.FullName
+ } else {
+ Write-Verbose "A folder matching the module folder pattern was found at $($moduleFolder.FullName) but didn't contain a valid module file"
+ }
+ }
+ }
+ }
+ catch {
+ Write-Verbose "Attempting to find the Latest Module Folder failed with the error: $($_.Exception.Message)"
+ $resultFolder = ""
+ }
+ Write-Verbose "Latest module folder detected: $resultFolder"
+ return $resultFolder
+}
+
+function CleanUp-PSModulePathForHostedAgent {
+ # Clean up PSModulePath for hosted agent
+ $azureRMModulePath = "C:\Modules\azurerm_2.1.0"
+ $azureModulePath = "C:\Modules\azure_2.1.0"
+ $azPSModulePath = $env:PSModulePath
+
+ if ($azPSModulePath.split(";") -contains $azureRMModulePath) {
+ $azPSModulePath = (($azPSModulePath).Split(";") | ? { $_ -ne $azureRMModulePath }) -join ";"
+ write-verbose "$azureRMModulePath removed. Restart the prompt for the changes to take effect."
+ }
+ else {
+ write-verbose "$azureRMModulePath is not present in $azPSModulePath"
+ }
+
+ if ($azPSModulePath.split(";") -contains $azureModulePath) {
+ $azPSModulePath = (($azPSModulePath).Split(";") | ? { $_ -ne $azureModulePath }) -join ";"
+ write-verbose "$azureModulePath removed. Restart the prompt for the changes to take effect."
+ }
+ else {
+ write-verbose "$azureModulePath is not present in $azPSModulePath"
+ }
+
+ $env:PSModulePath = $azPSModulePath
+}
\ No newline at end of file
diff --git a/Tasks/AzurePowerShellV5/azurepowershell.ts b/Tasks/AzurePowerShellV5/azurepowershell.ts
new file mode 100644
index 000000000000..18fdc091c4d8
--- /dev/null
+++ b/Tasks/AzurePowerShellV5/azurepowershell.ts
@@ -0,0 +1,139 @@
+import fs = require('fs');
+import path = require('path');
+import os = require('os');
+import tl = require('azure-pipelines-task-lib/task');
+import tr = require('azure-pipelines-task-lib/toolrunner');
+import { AzureRMEndpoint } from 'azure-arm-rest-v2/azure-arm-endpoint';
+var uuidV4 = require('uuid/v4');
+
+async function run() {
+ try {
+ tl.setResourcePath(path.join(__dirname, 'task.json'));
+
+ // Get inputs.
+ let _vsts_input_errorActionPreference: string = tl.getInput('errorActionPreference', false) || 'Stop';
+ switch (_vsts_input_errorActionPreference.toUpperCase()) {
+ case 'STOP':
+ case 'CONTINUE':
+ case 'SILENTLYCONTINUE':
+ break;
+ default:
+ throw new Error(tl.loc('JS_InvalidErrorActionPreference', _vsts_input_errorActionPreference));
+ }
+
+ let scriptType: string = tl.getInput('ScriptType', /*required*/true);
+ let scriptPath = tl.getPathInput('ScriptPath', false);
+ let scriptInline: string = tl.getInput('Inline', false);
+ let scriptArguments: string = tl.getInput('ScriptArguments', false);
+ let _vsts_input_failOnStandardError = tl.getBoolInput('FailOnStandardError', false);
+ let targetAzurePs: string = tl.getInput('TargetAzurePs', false);
+ let customTargetAzurePs: string = tl.getInput('CustomTargetAzurePs', false);
+ let serviceName = tl.getInput('ConnectedServiceNameARM',/*required*/true);
+ let endpointObject= await new AzureRMEndpoint(serviceName).getEndpoint();
+ let input_workingDirectory = tl.getPathInput('workingDirectory', /*required*/ true, /*check*/ true);
+
+ // string constants
+ let otherVersion = "OtherVersion"
+
+ if (targetAzurePs == otherVersion) {
+ if (customTargetAzurePs != "") {
+ targetAzurePs = customTargetAzurePs;
+ }
+ else {
+ console.log(tl.loc('InvalidAzurePsVersion',customTargetAzurePs));
+ }
+ }
+ else {
+ targetAzurePs = ""
+ }
+
+ var endpoint = JSON.stringify(endpointObject);
+
+ if (scriptType.toUpperCase() == 'FILEPATH') {
+ if (!tl.stats(scriptPath).isFile() || !scriptPath.toUpperCase().match(/\.PS1$/)) {
+ throw new Error(tl.loc('JS_InvalidFilePath', scriptPath));
+ }
+ }
+
+ // Generate the script contents.
+ console.log(tl.loc('GeneratingScript'));
+ let contents: string[] = [];
+ let azFilePath = path.join(path.resolve(__dirname), 'InitializeAz.ps1');
+ contents.push(`$ErrorActionPreference = '${_vsts_input_errorActionPreference}'`);
+ if(targetAzurePs == "") {
+ contents.push(`${azFilePath} -endpoint '${endpoint}'`);
+ }
+ else {
+ contents.push(`${azFilePath} -endpoint '${endpoint}' -targetAzurePs ${targetAzurePs}`);
+ }
+
+ if (scriptType.toUpperCase() == 'FILEPATH') {
+ contents.push(`. '${scriptPath.replace("'", "''")}' ${scriptArguments}`.trim());
+ console.log(tl.loc('JS_FormattedCommand', contents[contents.length - 1]));
+ }
+ else {
+ contents.push(scriptInline);
+ }
+
+ // Write the script to disk.
+ tl.assertAgent('2.115.0');
+ let tempDirectory = tl.getVariable('agent.tempDirectory');
+ tl.checkPath(tempDirectory, `${tempDirectory} (agent.tempDirectory)`);
+ let filePath = path.join(tempDirectory, uuidV4() + '.ps1');
+
+ await fs.writeFile(
+ filePath,
+ '\ufeff' + contents.join(os.EOL), // Prepend the Unicode BOM character.
+ { encoding: 'utf8' }); // Since UTF8 encoding is specified, node will
+ // encode the BOM into its UTF8 binary sequence.
+
+ // Run the script.
+ //
+ // Note, prefer "pwsh" over "powershell". At some point we can remove support for "powershell".
+ //
+ // Note, use "-Command" instead of "-File" to match the Windows implementation. Refer to
+ // comment on Windows implementation for an explanation why "-Command" is preferred.
+ let powershell = tl.tool(tl.which('pwsh') || tl.which('powershell') || tl.which('pwsh', true))
+ .arg('-NoLogo')
+ .arg('-NoProfile')
+ .arg('-NonInteractive')
+ .arg('-ExecutionPolicy')
+ .arg('Unrestricted')
+ .arg('-Command')
+ .arg(`. '${filePath.replace("'", "''")}'`);
+
+ let options =