如何在 Azure DevOps 中的 Powershell 内联脚本中正确连接字符串?

Yod*_*oda 2 powershell azure-devops azure-pipelines

我尝试连接字符串以构建路径:

$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"
$TargetFilePath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug/" + $(Release.ReleaseName) +$(Release.EnvironmentName)
Run Code Online (Sandbox Code Playgroud)

但不是连接字符串,而是第二行出现错误:

d:\a\r1\a :术语“d:\a\r1\a”不被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。在 D:\a_temp\9de874c9-3acd-4a19-a4dd-763074d38e40.ps1:2 char:25

哪里显然d:\a\r1\a是 a$(System.DefaultWorkingDirectory)但为什么它会抛出这个错误而不是仅仅连接字符串?

mkl*_*nt0 6

tl;博士

这是Azure的一个可扩展$(System.DefaultWorkingDirectory) 之前PowerShell中看到所产生的命令; 如果PowerShell$(...)要将扩展值视为字符串,则必须将其括在引号( '$(...)') 中:

  • 使用$(...)(Azure 宏语法) 将 Azure 变量的逐字值嵌入到 PowerShell 最终解释的命令文本中。

    • Azure中的宏观语法-这是评估- PowerShell中看到生成的命令文本不与混淆PowerShell的自己的“子表达式运算符$(...)
  • 对于字符串值,这意味着您必须'...'特定情况下用引号将宏括起来,以使其在 PowerShell 代码中在语法上工作,其中-quoting(单引号)是最好的'$(System.DefaultWorkingDirectory)'


Shayki Abramczyk 的回答提供了一个有效的解决方案,但让我提供一些背景信息

Azure 通过宏语法 ( $(...))执行变量扩展(替换)功能类似于预处理器:它将引用的变量替换为其逐字值

您需要确保此逐字值在目标命令的上下文中在语法上有效

如目前所写:

$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"

变成PowerShell 看到的以下命令,假设 Azure 属性的System.DefaultWorkingDirectory值为d:\a\r1\a'

$SourceDirectoryPath = d:\a\r1\a + "/solution/project/bin/Debug"
Run Code Online (Sandbox Code Playgroud)

这是一个损坏的 PowerShell 命令,因为d:\a\r1\a- 由于缺少引号 - 被解释为命令名称或路径;也就是说,尝试执行推定的可执行文件d:\a\r1\a- 请参阅about_Parsing

因此,为了让 PowerShell 将 Azure 扩展值识别d:\a\r1\astring,您需要引用- 请参阅about_Quoting_Rules

由于扩展的 Azure 值不需要进一步的插值,引号是最佳选择(实际上对于两个操作数):

$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)' + '/solution/project/bin/Debug'
Run Code Online (Sandbox Code Playgroud)

事实上,在您的情况下,您根本不需要字符串连接 ( +)

$SourceDirectoryPath = '$(System.DefaultWorkingDirectory)/solution/project/bin/Debug'
Run Code Online (Sandbox Code Playgroud)

您甚至可以将其与可扩展的 PowerShell 字符串 ( "...")结合使用,只要 Azure 扩展的值不包含$PowerShell 最终可能解释的带前缀的令牌(除非这是您的(不寻常的)意图)。

一个类似的警告"$(System.DefaultWorkingDirectory)/$projectRoot/bin/Debug"(将 Azure 扩展值与 PowerShell 变量引用混合)是Azure 的 宏语法( $(...)) 看起来与 PowerShell 自己的子表达式 operator 相同,它通常 - 但不是专门 - 用于在可扩展中嵌入表达式字符串(例如,在纯 PowerShell 代码中,"1 + 1 equals $(1 + 1)")。

截至发稿时,定义变量Azure的帮助主题不拼出来,但是基于在GitHub的文档问题发表官方评论不确定性避免如下

  • 没有逃逸机制; 相反,$(...)不引用 Azure 变量的构造保持不变,因此传递给 PowerShell。

  • 在典型的情况下,PowerShell的表达式将不会看起来像一个天青可变参考(例如,$($foo.bar)而不是$(foo.bar)),尽管假设可以有歧义:$(hostname),其中是,如果一个有效的子表达式的PowerShell,可以通过天青被抢占hostname天青变量被定义。

    • 在这种极端情况下,解决方案是避免使用内联脚本,而是将代码放在外部脚本文件中