I try to concatenate string to construct a path:
$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + \"/solution/project/bin/Debug\"
$TargetFilePath =
Note: $(System.DefaultWorkingDirectory)
in the question is an Azure Pipeline macro (variable), expanded by Azure before PowerShell sees the command - it is not to be confused with PowerShell's own subexpression operator, $(...)
.
Shayki Abramczyk's answer provides an effective solution, but let me provide some background information:
The value expansion (substitution) that Azure performs via macro $(...)
functions like a preprocessor: it replaces the referenced property with its verbatim value.
You need to make sure that this verbatim value works syntactically in the context of the target command.
As currently written:
$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"
turns into the following command seen by PowerShell, assuming that the value of Azure property System.DefaultWorkingDirectory
is d:\a\r1\a'
:
$SourceDirectoryPath = d:\a\r1\a + "/solution/project/bin/Debug"
This is a broken PowerShell command, because d:\a\r1\a
- due to lack of quoting - is interpreted as a command name or path; that is, an attempt is made to execute putative executable d:\a\r1\a
- see about_Parsing.
Therefore, in order for PowerShell to recognize the Azure-expanded value d:\a\r1\a
as a string, you need to quote it - see about_Quoting_Rules.
Since the expanded-by-Azure value needs no further interpolation, single quotes are the best choice (for both operands, actually):
$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)' + '/solution/project/bin/Debug'
In fact, you don't need string concatenation (+
) at all in your case:
$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)/solution/project/bin/Debug'
You could even combine that with expandable PowerShell strings ("..."
), as long as the Azure-expanded value doesn't contain $
-prefixed tokens that PowerShell could end up interpreting (unless that is your (unusual) intent).
One caveat re something like "$(System.DefaultWorkingDirectory)/$projectRoot/bin/Debug"
(mixing an Azure-expanded value with a PowerShell variable reference) is that Azure's macro syntax ($(...)
) looks the same as PowerShell's own subexpression operator, which is typically - but not exclusively - used in order to embed expressions in expandable strings (e.g., in pure PowerShell code, "1 + 1 equals $(1 + 1)"
).
As of this writing, the Define variables Azure help topic doesn't spell it out, but bsed on the official comment in a GitHub docs issue, ambiguity is avoided as follows:
There is no escape mechanism; instead, $(...)
constructs that do not refer to Azure variables are left unchanged and therefore passed through to PowerShell.
In the typical case, PowerShell expressions will not look like an Azure variable reference (e.g, $($foo.bar)
rather than $(foo.bar)
), though hypothetically there can be ambiguity: $(hostname)
, which is a valid PowerShell subexpression, could be preempted by Azure if a hostname
Azure variable were defined.
This should work as well. $( ) outside of doublequotes would only be used to combine two or more statements. Most people don't even know about it.
This is actually incorrect. I didn't know Azure Pipeline syntax. It just shows how confusing combining both Powershell and Azure Pipeline can be. This would work if $System were a Powershell object, not an Azure macro.
$SourceDirectoryPath = $System.DefaultWorkingDirectory + '/solution/project/bin/Debug'
You need to add quotes " "
in the variables:
$SourceDirectoryPath = "$(System.DefaultWorkingDirectory)" + "/solution/project/bin/Debug"
$TargetFilePath = "$(System.DefaultWorkingDirectory)" + "/solution/project/bin/Debug/" + "$(Release.ReleaseName)" + "$(Release.EnvironmentName)"