【问题标题】:PowerShell Param string always in single quotePowerShell 参数字符串始终在单引号中
【发布时间】:2018-06-13 08:05:25
【问题描述】:

我有一个带有强制参数的脚本,我们用它来安装一些 SQL 组件,包括用户名和密码,如下所示:

param(    
[Parameter(Mandatory=$True,HelpMessage="SQL Server password")]
    [ValidateNotNullOrEmpty()]
    [string] $SqlServerPassword
)

因此,当用户运行此脚本时,他/她将需要包含 -SqlServerPassword 'SpecialCharacters' 变量字符串。我知道最好的做法是将字符串放在单引号内,但这是训练我们的一些安装管理员的一条艰难道路,而且由于我们的密码库包含特殊字符而没有单引号会导致问题。

我怎样才能重写上面的内容以确保即使用户通过密码而不是单引号,它也将是单引号?谢谢!

【问题讨论】:

  • 好吧,首先,如果您在您的环境中支持所有这些版本的 powershell,您应该考虑标准化。
  • 另外,您能否扩展一下 "..因为我们的密码库包含没有单引号的特殊字符会导致问题。"?我不明白你的意思。
  • @EBGreen 我得到标准化并同意。但就目前而言,在我们重新设计某些东西之前,我必须处理这个问题,因为人们忘记了,这是一个持续的痛苦。它只是一个随机密码生成器。
  • @EBGreen 道歉,我误解了 - 我们在整个企业中使用 PS 版本 5。
  • 啊......好吧,如果我有机会,我会玩这个。我可以重现它。这是一个minimal reproducible example 给任何想要的人:function foo{param($in) Write-Host $in}; foo abcd$123 我怀疑是否有解决方案。你永远不能完全超越愚蠢的程序。

标签: powershell


【解决方案1】:

如果要将字符串作为参数传递,则无法完成您的要求,因为这将需要停用命令行解析器 - 识别单个参数的机制,计算其中包含的变量引用和子表达式,并将它们绑定到参数。

使用一组有限的特殊字符,您可以忽略解析器绑定的值并手动解析原始命令行$MyInvocation.Line,但这不仅是不明智的,它还会与诸如|;

但是,您可以通过交互式提示实现您想要的。 虽然如果用户碰巧没有在命令行上传递 -SqlServerPassword 参数,您的代码也会收到这样的提示,但它并不能防止可能不正确的命令行使用。 (此外,这种自动提示对用户不友好,并且有一些怪癖,例如无法以! 开头的值)。

如果可行,您可以要求用户使用Read-Host以交互方式输入值(并且不允许将值作为参数传递),在这种情况下引用不需要 - 也不能 - 使用:

param(
  # Do NOT define $SqlServerPassword as a parameter (but define others)
)

# Prompt the user for the password.
# The input is invariably treated as a literal.
Write-Host "Please enter the SQL Server password:"
[string] $SqlServerPassword = Read-Host

# Validate the user's input.
if (-not $SqlServerPassword) { Throw 'Aborted.' }
# ...

注意:Read-Host 有一个-Prompt 参数,它直接接受一个提示字符串,但是如果你使用它,你将无法输入以! 开头的值;因此,提示是用上面单独的Write-Host 语句编写的。

【讨论】:

  • 我对此进行了测试,它确实接受带有特殊字符的密码;但是,如果密码以 !这可能是一个潜在的问题。我很好奇这应该放在 param() 内部还是外部?所以在脚本中,有各种参数,SQL密码只有一个,还有用户,还有其他密码。我可以使用提示,我看到它确实有效,但我是放在 param() 内部还是外部?就像在下面一样。所以我让我的 param() 注释掉密码并将 [string] $SqlServerPassword = Read-Host 放在外面?谢谢!
  • @DangeRuss: 是的,提示应该进入你的函数的主体 - 就在 param() 块之后 - 或者,如果它是 begin / process 的高级函数/end 块,在 begin 块中。另一种选择是坚持使用原始参数,但使其成为非强制性参数,然后,如果传递了一个参数,则显示其值并要求用户确认/修改它 - 这样,他们就会看到他们想要传递的内容由于没有引用,没有通过。如果未传递任何参数,则使用如上所示的提示。
  • @DangeRuss:以! 开头的密码不是答案中的解决方案中的问题,因为它避免了自动提示和使用Read-Host's -Prompt 参数。
  • 谢谢!我昨天对此进行了测试,提示有效并保留特殊字符,无论它们是什么。 :-)
猜你喜欢
  • 2022-01-12
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
相关资源
最近更新 更多