如何从 TeamCity 构建配置中设置 PowerShell 开关参数

Posted

技术标签:

【中文标题】如何从 TeamCity 构建配置中设置 PowerShell 开关参数【英文标题】:How to set a PowerShell switch parameter from TeamCity build configuration 【发布时间】:2014-12-08 00:40:09 【问题描述】:

我有一个带有开关(布尔)参数的 PowerShell 脚本,我想从 TeamCity 构建步骤中调用它。

我希望根据 TeamCity 构建参数、配置参数来设置开关的值(真/假)。

所以,像这样:

在 PowerShell 运行器构建步骤中:

但是上面的不行。

我收到此错误

[14:27:01][Step 1/1] Cannot process argument transformation on parameter 'preRelease'. Cannot 
[14:27:01][Step 1/1] convert value "System.String" to type 
[14:27:01][Step 1/1] "System.Management.Automation.SwitchParameter". Boolean parameters accept only 
[14:27:01][Step 1/1] Boolean values and numbers, such as $True, $False, 1 or 0.

如您所见,PowerShell 似乎坚持将参数解释为字符串。

我尝试了许多编写脚本参数的变体。这些都不起作用:

-preRelease:%IncludePreRelease%
-preRelease:([boolean]%IncludePreRelease%)
-preRelease:([System.Convert]::ToBoolean(%IncludePreRelease%))

【问题讨论】:

【参考方案1】:

根据Convert.ToBoolean 的 Microsoft .Net 文档,传递给方法的值必须是:

要成功进行转换,值参数必须等于 Boolean.TrueString,一个值为 True 的常量, Boolean.FalseString,一个常量,其值为 False,否则必须是 空值。在将值与 Boolean.TrueString 和 Boolean.FalseString,该方法忽略大小写以及前导和 尾随空格。

如果您将 TeamCity IncludePreRelease 变量值更改为“True”或“False”(不带引号),那么它应该会转换正确。

【讨论】:

【参考方案2】:

这是一个老问题,但如果你还在寻找答案,我设法让它发挥作用。

主要技巧是您实际上不应像使用 PowerShell 那样在参数名称和值之间使用冒号(我知道,令人困惑......)。

TeamCity 似乎以不同的方式调用脚本并将参数作为字符串传递。

因此,对于您的示例,以下内容应该有效: -preRelease $%IncludePreRelease%

请注意,我在 TeamCity 变量前添加了一个美元符号,以将“true”更改为“$true”

让我知道它是否适合你

谢谢!

【讨论】:

帮助了我。谢谢!【参考方案3】:

不,这仍然行不通。似乎 TC 无论如何都会将值视为字符串。也许答案来自允许这样做的 TC 版本,但最新版本没有。

没有冒号:

[16:18:37]Step 1/6: Migrate Up (Powershell)
[16:18:37][Step 1/6] PowerShell Executable: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
[16:18:37][Step 1/6] PowerShell arguments: [-NonInteractive, -ExecutionPolicy, ByPass, -File, C:\BuildAgent\work\f2797fec10821a01\data\Migration\MigrateUp.ps1, "data\change scripts", DB, xxxxxxx, sa, *******, -NoExec, $false]
[16:18:37][Step 1/6] C:\BuildAgent\work\f2797fec10821a01\data\Migration\MigrateUp.ps1 : A positional parameter cannot be found that accepts argument '$false'.

带冒号:

 [16:18:37]Step 2/6: Migrate Up (Powershell)
 [16:18:37][Step 2/6] PowerShell Executable: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
 [16:18:37][Step 2/6] PowerShell arguments: [-NonInteractive, -ExecutionPolicy, ByPass, -File, C:\BuildAgent\work\f2797fec10821a01\data\Migration\MigrateUp.ps1, "data\change scripts", DB, xxxxxx, sa, *******, -NoExec:$false]
 [16:18:37][Step 2/6] C:\BuildAgent\work\f2797fec10821a01\data\Migration\MigrateUp.ps1 : Cannot process argument transformation on parameter 'NoExec'. Cannot convert value "System.String" to type "System.Management.Automation.SwitchParameter". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.

删除 [switch] 也不起作用,因为您给它的任何值都不会被视为布尔值 - 而是分配给布尔值的字符串 - 因此,所有布尔运算都将是 $true

换句话说,您发送的任何内容都会如下所示:

0 => '0' 1 => '1' $false => '$false' $true => '$true'

(都不是== $false,但都等价于$true)

我不知道如何让 TC 接受布尔值! 我能做的最好的就是假设参数是一个字符串并在我的脚本内部使用 System.Convert.ToBoolean() ...

【讨论】:

总结一下:下面的解决方案都不适合我(-File 参数很卑鄙),因此我不得不将脚本参数类型更改为[String] 并按如下方式使用它: $([System.Convert]::ToBoolean($preRelease)【参考方案4】:

让开关的传递完全依赖于配置参数:

    创建配置参数时,选择类型“复选框”。 在“检查值”中,输入“-preRelease”。 将“未检查的值”留空。 只需将“%IncludePreRelease%”附加到您的脚本参数。勾选参数时会传递“-preRelease”(=true),不勾选时会省略(=false)。

这对我使用 TeamCity 10.0.4 有效。

【讨论】:

【参考方案5】:

我知道这是一个迟到的答案,但我刚刚有一位同事在工作中偶然发现了同样的问题并发现了这个问题。

如果我们暂时忘记 TC,如果您想从 cmd(不是 powershell 控制台)执行相同的命令,确切的命令将是:

powershell.exe -File script.ps1 -preRelease

此命令将开关设置为 True。这里重要的是命令首先由 shell (cmd) 解析。

因为shell是cmd,所以不会执行命令行中的powershell代码。

例如:

powershell -File script.ps1 -preRelase:"([System.Convert]::ToBoolean(%IncludePreRelease%))"

在第一次通过 cmd 解析后,它最终是:

powershell -File script.ps1 -preRelase:"([System.Convert]::ToBoolean(True))"

所以preRelease 标志被设置为整个字符串,这给了你准确的信息

Cannot process argument transformation on parameter 'preRelease'. 
Cannot convert value "System.String" to type 
"System.Management.Automation.SwitchParameter"

基于documentation,当使用-File 时,您要么传递开关参数,要么不传递。似乎没有办法传递TrueFalse 值。

要使其工作从 -File 更改为 -Command,如下所示:

powershell -Command .\script.ps1 -preRelease:$%IncludePreRelease%

现在,回到 TeamCity。 Teamcity 似乎不支持上面的 -Comand 。他们通过将整个脚本作为脚本块转储到命令行中来支持它,这可能会导致非常有趣的错误。

解决办法是将Script改成Source并在脚本内容里面添加

.\script.ps1 -preRelease:$%env.IncludePreRelease%

【讨论】:

以上是关于如何从 TeamCity 构建配置中设置 PowerShell 开关参数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 java 中获取 Teamcity 配置的值?

TeamCity 是不是支持执行其他 TeamCity 构建的构建步骤?

如何配置 TeamCity 构建代理以通过 SOCKS 代理使用 git 和 git:// 协议?

如何在 Nuxt 配置中设置 .env 文件路径?

如何在 Teamcity 中归档构建配置?

如何在 Angular 2 Http Observable 请求中设置间隔