首页 > 解决方案 > 带有字符串参数和脚本文件的奇怪 powershell 行为

问题描述

我有一个powershell脚本文件,如下

param(
[parameter(Mandatory = $true)]
[string] $db_server,
[parameter (Mandatory = $true)]
[string[]] $db_server_list

)

write-output "My DB server is $db_server"
foreach ($list in $db_server_list)
{
    write-output $list
}

让我们假设文件保存为 script1.ps1

在我的开发笔记本电脑上,我可以毫无问题地从 Visual Studio 代码运行它。

.\script1.ps1 -db_Server 'my_db_server,999' -db_server_list ("server1,5694","server2,7788")

它运行良好,db_Server 的值是指定的 my_db_server,999 并且我能够循环通过 db_Server_list 而不会丢失作为端口号的逗号。

我正在从外部编排程序调用该文件,并这样做。我需要跑步

powershell.exe  .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list ("server1,5694","server2,7788")

突然间我得到了错误。

无法处理参数“db_server”上的参数转换。无法将值转换为 System.string 类型。我不希望 db_server 成为一个数组,即使它有一个逗号,我需要它作为一个字符串返回,因为我将它用于连接字符串,如果逗号后的值被剥离,它将破坏我的脚本。

请注意,这只发生在我调用 powershell.exe scriptfile.ps1 时。从 VS 代码运行不会导致此类错误。

谢谢大家。

我又跑了一遍,还是同样的问题。 在此处输入图像描述

我需要添加 powershell.exe 的原因是因为我从 ansible playbook 调用脚本。

标签: powershell

解决方案


笔记:

  • Ansible还提供了该ansible.windows.win_shell模块,它使用一个shell来处理指定的命令行,这个 shell就是PowerShell。

    • 如果您使用此方法,则可以按原样使用原始 PowerShell 命令(请注意,我已删除(...)传递给的数组周围的不必要-db_server_list并已切换为单引号):

      .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list 'server1,5694', 'server2,7788'
      
  • 相比之下,如果您使用ansible.windows.win_command则不涉及任何 shell,并且您确实必须调用 (Windows) PowerShell 的 CLI,powershell.exe, , , , , , 如下所示。


注意

  • 下面的命令旨在从PowerShell外部运行,并且只能在那里工作[1];从PowerShell内部开始,您不需要调用powershell.exe,但如果这样做,则在这种情况下,您必须将所有内容包含在 in 之后-c"..."这也可以在 PowerShell 外部工作),或者仅从 PowerShell 内部,{ ... }- 但请注意,对于从 OUTSIDE PowerShell 调用时给定的命令行是否有效,这两种方法都不是有效的测试

  • 如果要调用 from cmd.exe,通常最好将传递给-c( -command) 的整个参数列表包含在 中"...",以防止对特殊字符的无意解释,例如前面&的 by cmd.exe。这在无外壳调用场景中是不必要的,例如使用或来自计划任务。ansible.windows.win_command

  • 无论哪种方式,如果您希望"PowerShell 的-c参数将字符视为(最终)执行的命令的一部分,则必须将它们转义\"-在命令行解析期间会去除未转义 "的字符,这解释了为什么您的尝试不起作用:,当从 PowerShell 外部传递时,最终被视为,这是损坏的语法-db_server_list ("server1,5694","server2,7788")
    -db_server_list (server1,5694,server2,7788)

  • 相比之下,'字符不需要转义并且切换到'...'专门使用参数提供了最简单的解决方案。

powershell.exe -c .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list 'server1,5694', 'server2,7788'

[1] 它在 PowerShell 中不起作用的原因是调用PowerShell 会话解释了'...'字符串,并且在这种情况下传递了它们的内容unquoted,因为内容恰好不包含空格字符。

[2] 请注意pwshPowerShell (Core) 7+ CLI 现在默认-File改为。有关如何解析传递给( ) 的参数、与( ) 参数并列以及何时使用哪个参数 的详细信息,请参阅此答案。-c-Command-f-File


推荐阅读