I have an Azure Pipeline that is calling a PowerShell file using @AzureCLI@2
but at the top of the script I appear to be losing a value passed in which is the directory I want to load a file from.
If I perform this Task in Yaml:
- powershell: Get-ChildItem -Path ${{ parameters.artifactFolder }} -recurse
I can see outputs as such:
Directory: C:\a\2\s\firewall\Parameters\output\myDir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/20/2023 1:30 PM 3804260 parameters.json
The next Yaml task:
- task: AzureCLI@2
displayName: Remove Resource Locks
inputs:
azureSubscription: ${{ parameters.serviceConnection }}
scriptType: 'ps'
scriptLocation: 'scriptPath'
ScriptPath: '${{ parameters.artifactFolder }}/powershell/fw.removeLocks.ps1'
arguments: >
-firewallOutputFolder "${{ parameters.artifactFolder }}"
-action "Remove"
workingDirectory: '$(System.DefaultWorkingDirectory)'
Passes in the directory. With the PowerShell script, the following code is at the start of the file:
[parameter(Mandatory = $true)][string] $firewallOutputFolder,
[ValidateSet("Create", "Remove")]
[parameter(Mandatory = $true)][string] $action
try
{
# Either remove or create locks for Firewall and FW Policy
Write-Host "First WH......................"
Write-Host $firewallOutputFolder
Write-Host "$($firewallOutputFolder)\Parameters\output"
$folder = $firewallOutputFolder
# Loop output files i.e. deployment files
$fwFiles = Get-ChildItem $firewallOutputFolder -Directory
foreach($fwFile in $fwFiles)
{
$fwParameters = "$($firewallOutputFolder)\$($fwFile.name)\parameters.json"
}
}
The outputs from the first batch of write-host
:
First WH......................
\Parameters\output
The value being passed in is now empty/null
Does anyone have any suggestions as to why the value is vanishing?
Your PowerShell script is missing the param(...)
enclosure around your individual parameter declarations - see the conceptual about_Functions help topic.
Therefore:
# Parameter declarations must be enclosed in param(...)
param(
[Parameter(Mandatory)]
[string] $firewallOutputFolder
,
[Parameter(Mandatory)]
[ValidateSet('Create', 'Remove')]
[string] $action
)
# ...
Unfortunately, forgetting param(...)
effectively results in quiet failure:
What you mean to be parameter declarations are interpreted as [string]
casts from nonexistent variables (which evaluate to $null
, unless a strict mode is in effect).
The attribute decorations ([Parameter()]
, [ValidateSet()]
) are effectively ignored.
As a result, each such mistaken declaration outputs the empty string (effectively the same as [string] $null
) instead of declaring parameters.
Therefore, your script doesn't declare any parameters at all, which means that not only does it not enforce mandatory arguments, but happily accepts any number of (positional) arguments, which are then only reflected in the automatic $args
variable.
This quiet failure due to what should arguably be a syntax error is unfortunate.
GitHub issue #10614 asks that such cases either be prevented syntactically or at least generate a warning.