C# 支持Whatif并确认响应

C# 支持Whatif并确认响应,c#,powershell,cmdlet,pscmdlet,C#,Powershell,Cmdlet,Pscmdlet,这里和其他地方都有大量问题,解释了如何将-Confirm在整个cmdlet中传播到嵌套cmdlet等。但是,我没有找到如何将响应传播到该提示。也就是说,一旦用户回答此提示 [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): 。。。我们可以合理地假设,我的cmdlet现在可以根据用户对该提示的响应进行操作。这在一定程度上是正确的:Suspend[S]和Help[?]都是本地

这里和其他地方都有大量问题,解释了如何将
-Confirm
在整个cmdlet中传播到嵌套cmdlet等。但是,我没有找到如何将响应传播到该提示。也就是说,一旦用户回答此提示

[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
。。。我们可以合理地假设,我的cmdlet现在可以根据用户对该提示的响应进行操作。这在一定程度上是正确的:
Suspend[S]
Help[?]
都是本地化的操作,它们工作正常

但我的主要问题是认识到所有人都是,以及所有人都是。 在C#(通过
Cmdlet.ShouldProcess()
)和PowerShell(通过
$PSCmdlet.ShouldProcess()
)中,只能得到一个布尔结果,我只能从中推测:

  • true
    为[Y]或[A]
  • false
    为[N]或[L]
我最初希望,
应该继续
利用内部cmdlet状态来实现这一区别,但脚本cmdlet的实验表明情况并非如此

事实上,我发现thusfar唯一可能的解决方法是(大约2007年!)PowerShell的Should Process函数,大概是在引入“官方”的
Cmdlet.Should Process
$PSCmdlet.Should Process
之前

我发现很难相信PowerShell团队忘记了区分所有人的是/是和所有人的否/否;相反,我认为我只是忽略了它


因此,我的简短问题是:对于编译cmdlet和脚本cmdlet,我如何区分
Yes
yestoall
No
No toall

我相信
yestoall
选项的意思是“是的,对我当前正在处理的所有项目执行此操作”,而不是“是的,执行所有可能的操作,不要再问我”。测试此操作的一种方法是将数组通过管道传输到支持ShouldProcess的函数,该函数在内部调用内部函数(也支持ShouldProcess)一次只调用一个项。您将看到,至少在我的Win 8.1机器上的PowerShell v4.0上,我通过管道将数组传输到的外部函数不会请求数组中的其他项。但是,内部函数会多次调用,而不是使用数组进行输入调用一次,每次调用时都会请求一次d

我们可以使用以下函数和内部函数测试此行为:

function Test-ShouldProcess
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    PARAM (
        [Parameter(ValueFromPipeline = $true)]
        $InputObject
    )

    PROCESS
    {
        if ($PSCmdlet.ShouldProcess($InputObject, "Do stuff to it"))
        {
            Write-Host "Doing stuff to $InputObject"
            Test-ShouldProcess_InnerFunc -InputObject $InputObject
        }
    }
}

function Test-ShouldProcess_InnerFunc
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    PARAM (
        [Parameter(ValueFromPipeline = $true)]
        $InputObject
    )

    PROCESS
    {
        if ($PSCmdlet.ShouldProcess($InputObject, "Do internal stuff to it"))
        {
            Write-Host "Doing internal stuff to $InputObject"
        }
    }
}
如果我们通过管道将数组连接到函数来调用外部函数,如下所示:

"item1", "item2" | Test-ShouldProcess -Confirm
假设我们在每个提示符上都响应“Yes to all”,我们将得到以下输出:

Confirm
Are you sure you want to perform this action?
Performing the operation "Do stuff to it" on target "item1".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): A
Doing stuff to item1

Confirm
Are you sure you want to perform this action?
Performing the operation "Do internal stuff to it" on target "item1".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): A
Doing internal stuff to item1
Doing stuff to item2

Confirm
Are you sure you want to perform this action?
Performing the operation "Do internal stuff to it" on target "item2".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): A
Doing internal stuff to item2
请注意,它请求一次“向它发送内容”,然后请求一次“向它发送内部内容”。在内部函数执行后,下一行是外部函数在数组第二项上的输出,没有提示,因为我们回答“全部是”“。第二个项的外部函数再次以单个项调用的形式调用内部函数,因此PowerShell再次提示用户

PowerShell再次提示的原因是,这是处理新数据集的新指令。因此,只要是处理数据列表的同一指令,“Yes for all”将不会再次要求列表中的后续项,但对于新指令或新数据集,它应该再次要求


如果用户根本不希望提示确认,则用户不应使用
-confirm
开关,甚至可能更改
ConfirmPreference
设置,或者使用
-Force
开关。我对您的回答的反应是:谢谢!Robert,您提供了一些有用的见解,了解功能是如何自包含的,并且不需要基于机制实现的额外输出。但我对你回答内容的反应是:哇!这是一个糟糕的用户体验。本质上,您所说的是PowerShell提供了代码编写者能够理解/欣赏的提示,但这对代码用户来说不是很有用。代码编写者可以选择使用基于集合的操作编写代码,这样用户就不会获得这种体验。我不确定PowerShell应该如何以不同的方式处理它。我看到的另一个选择是,
对所有人都是
意味着
不要再向我要求任何东西
,这是我个人不喜欢的。我看到了
不要再向我索要这组数据
是一个好的实现。此外,如果用户根本不希望收到任何提示,则不应添加
-Confirm
开关。