首页 > 解决方案 > 如何在 Azure DevOps 的 Powershell 内联脚本中正确连接字符串?

问题描述

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

$SourceDirectoryPath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug"
$TargetFilePath = $(System.DefaultWorkingDirectory) + "/solution/project/bin/Debug/" + $(Release.ReleaseName) +$(Release.EnvironmentName)

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

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)但为什么它会抛出这个错误而不是仅仅连接字符串?

标签: powershellazure-devopsazure-pipelines

解决方案


tl;博士

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

  • 使用$(...)(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"

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

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

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

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

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

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

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

一个警告类似于(将Azure扩展"$(System.DefaultWorkingDirectory)/$projectRoot/bin/Debug"PowerShell 变量引用混合)是Azure 的 宏语法($(...)字符串(例如,在纯 PowerShell 代码中)。"1 + 1 equals $(1 + 1)"

在撰写本文时,Define variables Azure 帮助主题并未详细说明,但根据GitHub 文档问题中的官方评论,避免了歧义,如下所示

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

  • 在典型情况下,PowerShell 表达式看起来不像Azure 变量引用(例如,$($foo.bar)而不是$(foo.bar)),尽管假设可能存在歧义:如果定义了 Azure 变量$(hostname),它是一个有效的 PowerShell 子表达式,可能会被 Azure 抢占。hostname

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

推荐阅读