【问题标题】:Using -Confirm in Powershell在 Powershell 中使用 -Confirm
【发布时间】:2016-10-25 04:28:02
【问题描述】:

我试图了解 $?$lastexitcode 变量与 Powershell cmdlet 中的 -Confirm 标志之间的关系。

比如说你用-confirm运行一个命令,它会相应地提示你采取行动:

PS C:\temp> rm .\foo.txt -confirm
Confirm

Are you sure you want to perform this action?

Performing the operation "Remove Directory" on target "C:\temp\foo.txt".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):n

PS C:\temp> $?

True

我知道从技术上讲该命令运行成功,但如果用户选择“否”,则该命令不会运行。

我的问题是如何获得用户对-Confirm 标志的回答?

【问题讨论】:

  • 问题标题询问如何使用-Co​​nfirm,而实际问题是如何从-Confirm获取用户输入。对于像我一样只是在寻找如何使用确认的人,请考虑使用[cmdletbinding(SupportsShouldProcess)] 以及围绕相关逻辑的if 块if ($PSCmdlet.ShouldProcess("The Item" , "The Change")) {。这是一种巧妙的内置方式来添加确认,前提是您不需要获取用户的答案。如需参考,请参阅sqldbawithabeard.com/2018/01/25/…

标签: powershell


【解决方案1】:

$?$LastExitCode-Confirm 彼此完全不相关。

$? 是一个 automatic variable,带有一个布尔值,指示最后一个 (PowerShell) 操作是否成功执行。

$LastExitCode 是一个 automatic variable,带有最后执行的外部命令的退出代码(整数值)。

-Confirm 是一个 common parameter,用于控制 cmdlet 是否提示用户确认其操作。

据我所知,PowerShell 不会将给-Confirm 提示的答案存储在任何地方,因此如果您需要该响应以获取其他内容,则必须使用prompt the user yourself,例如像这样:

function Read-Confirmation {
  Param(
    [Parameter(Mandatory=$false)]
    [string]$Prompt,
    [Parameter(Mandatory=$false)]
    [string]$Message
  )

  $choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
  $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
  $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))

  -not [bool]$Host.UI.PromptForChoice($Message, $Prompt, $choices, 1)
}

$doRemove = if ($PSBoundParameters['Confirm'].IsPresent) {
  Read-Confirmation -Prompt 'Really delete'
} else {
  $true
}

if ($doRemove) {
  Remove-Item .\foo.txt -Force
}

【讨论】:

    【解决方案2】:

    AFAIK,无法捕获用户对确认提示的响应;它不是 PowerShell 命令历史记录的一部分,虽然您可能能够以某种方式从缓冲区获取信息,但这些信息仅在默认 PowerShell 主机中受支持,因为其他主机将使用不同的缓冲区。在这种情况下,最好使用 if 语句在脚本中单独进行确认。

    $userAnswer = Read-Host "Are you sure you wish to proceed?"
    if($userAnswer -eq "yes"){
        rm .\foo.txt
    }    
    

    然后只需使用 $userAnswer 变量来了解您的用户的响应。或者,您可以通过检查操作是否完成来确定他们的答案。这将是我的首选方法,因为这样您可以确定文件已被删除,而不是假设文件已被删除,因为 cmdlet 已成功执行并且用户已确认(考虑到 remove-item 经过了难以置信的良好测试,可靠性在这里可能没有任何不同,但是如果您使用的是某种第三方库,它可能会有所不同),如下所示。

    rm .\foo.txt -Confirm
    
    if(Test-Path .\foo.txt){
        $success = $false
    } else {
        $success = $true
    }
    

    如果您真的需要知道它是否由于错误或用户拒绝而无法删除,您可以执行类似

    的操作
    rm .\foo.txt -Confirm
    
    
    if(Test-Path .\foo.txt){
        $success = $false
    } else {
        $success = $true
    }
    
    if(!($success) -and (!($?))){
        $status = "Previous command failed"
    } elseif (!($success) -and $?){
        $status = "User cancelled operation"
    } 
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-08-30
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 2011-11-03
      相关资源
      最近更新 更多