如果省略必需的 *pipeline* 参数,是否可以强制 PowerShell 脚本抛出异常?

2023-12-13

当省略必需参数时,交互式 PowerShell 会话会提示用户。Shay Levy 提供了一个解决方法对于这个问题。问题是当您使用管道绑定参数时,解决方法不起作用。

考虑这个例子:

function f {
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeLineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$a=$(throw "a is mandatory, please provide a value.")
    )
    process{}
}

$o = New-Object psobject -Property @{a=1}
$o | f

尽管如此,这还是引发了异常$o.a是一个非常适合绑定的值f -a。由于某种原因 PowerShell 评估参数的默认值$a即使有一个值$a这注定要与管道绑定。

当交互式运行时缺少强制参数时,是否有其他方法可以强制 PowerShell 抛出异常?


为什么这很重要?浪费程序员的时间。就是这样:

  • 堆栈跟踪深度为 20 次调用是很正常的。当调用堆栈深处的调用由于未收到强制参数而阻塞时,调试效率会变得非常低。没有堆栈跟踪,没有错误消息,也没有上下文。您看到的只是参数值的提示。祝你好运,准确地猜出为什么会发生这种情况。您始终可以调试解决方案,但这会花费比应有的时间更多的时间,因为您没有从抛出的异常中获取通常会得到的信息。

  • 假设您正在运行一系列配置测试用例并且one1000人有这个问题。平均而言,其中 500 个测试用例未运行。因此,在此测试运行中您只能获得一半案例的测试结果。如果这些测试运行过夜,您可能还需要再等待 24 小时才能获得结果。所以现在你的迭代速度变慢了。


这不起作用的原因是管道参数具有不同的值,具体取决于您是否处于Begin {}, Process {}, or End {}堵塞。在某些时候,默认值会被评估,因此会抛出异常。这是我不喜欢那个特定黑客的原因之一。

合适的解决方案(我希望)

我非常喜欢它,所以我写了一篇关于它的博客文章所以我希望你觉得它有用。

function Validate-MandatoryOptionalParameters {
[CmdletBinding()]
param(
    [Parameter(
        Mandatory=$true
    )]
    [System.Management.Automation.CommandInfo]
    $Context ,

    [Parameter(
        Mandatory=$true,
        ValueFromPipeline=$true
    )]
    [System.Collections.Generic.Dictionary[System.String,System.Object]]
    $BoundParams ,

    [Switch]
    $SetBreakpoint
)

    Process {
        foreach($param in $Context.Parameters.GetEnumerator()) {
            if ($param.Value.Aliases.Where({$_ -imatch '^Required_'})) {
                if (!$BoundParams[$param.Key]) {
                    if ($SetBreakpoint) {
                        $stack = Get-PSCallStack | Select-Object -Index 1
                        Set-PSBreakpoint -Line $stack.ScriptLineNumber -Script $stack.ScriptName | Write-Debug
                    } else {
                        throw [System.ArgumentException]"'$($param.Key)' in command '$($Context.Name)' must be supplied by the caller."
                    }
                }
            }
        }
    }
}

我认为这样做的最大优点是,无论您有多少参数或它们的名称是什么,它都会以相同的方式被调用。

关键是你只需为每个以以下开头的参数添加一个别名即可Required_.

Example:

function f {
[CmdletBinding()]
param(
    [Parameter(
        ValueFromPipeline=$true
    )]
    [Alias('Required_Param1')]
    $Param1
)

    Process {
        $PSBoundParameters | Validate-MandatoryOptionalParameters -Context $MyInvocation.MyCommand
    }
}

根据我们的聊天对话和您的用例,我设置了一个断点而不是抛出。看起来它可能有用,但不确定。更多信息在帖子中。

也可作为GitHub要点(其中包括基于评论的帮助)。


我认为解决这个问题的唯一方法是检查进程块中的值。

Process {
    if (!$a) {
        throw [System.ArgumentException]'You must supply a value for the -a parameter.'
    }
}

如果您控制脚本的调用,您可以使用powershell.exe -NonInteractive并且应该抛出(或至少退出)而不是提示。

验证函数示例

function Validate-Parameter {
[CmdletBinding()]
param(
    [Parameter(
        Mandatory=$true , #irony
        ValueFromPipeline=$true
    )]
    [object]
    $o ,

    [String]
    $Message
)

    Begin {
        if (!$Message) {
            $Message = 'The specified parameter is required.'
        }
    }

    Process {
        if (!$o) {
            throw [System.ArgumentException]$Message
        }
    }
}

# Usage

Process {
    $a | Validate-Parameter -Message "-a is a required parameter"
    $a,$b,$c,$d | Validate-Parameter
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果省略必需的 *pipeline* 参数,是否可以强制 PowerShell 脚本抛出异常? 的相关文章

随机推荐

  • 为什么我们必须在内部类中将静态变量声明为final? [复制]

    这个问题在这里已经有答案了 我的代码是这样的 public class BookStore class Enumerator1 static int b 0 requires final public String searchBook f
  • 跨域请求和JQuery

    我尝试使用 getJSON 通过 jquery 向 Web 服务发出跨域请求 它工作正常 但是 当我尝试在 Internet Explorer 7 或 8 中发出相同的请求时 该请求永远不会发送 有人有主意吗 JSONP 就是为了这个目的而
  • 在 Perl 中如何找到所有重定向后的最终 URL?

    可以说我有 http www ritzcarlton com 这将我重定向到 http www ritzcarlton com en Default htm Perl 有没有办法在所有重定向后找到最终网址 使用 LWP 将为您遵循重定向 然
  • 在 JavaScript 中反转字符串

    我正在尝试反转输入字符串 var oneway document getElementById input field value var backway oneway reverse 但萤火虫告诉我oneway reverse 不是一个函
  • VS2015 中的 CoreCLR 控制台应用程序项目中没有本机代码调试?

    我真的很想跳过 CoreCLR 新的项目结构 nuget 合并到构建系统 文件系统报告更改时自动刷新解决方案以及针对多个平台只是我想从旧的 csproj net 继续前进的部分原因4 x 的东西 我的主要用例之一是使用 C 探索多平台游戏引
  • 如何将“字符串列表”变成真正的列表?

    我正在开一个 txt文件 并且必须使用其中的列表来执行我正在编写的函数 这是文本文件中给出的列表之一 24 72 95 100 59 80 87 n Using strip 它摆脱了 n 所以就变成 24 72 95 100 59 80 8
  • 递归 JSON 架构

    我正在尝试为带有子菜单的菜单创建正确的 JSON 架构 所以我应该从 item 定义一个数组 其中应包含三个项目 1 显示名称 2 URL 和子项 应该是具有相同结构的对象数组 此时我得到了这个 type array additionalP
  • main() 总是返回 int? [复制]

    这个问题在这里已经有答案了 可能的重复 C C 中 main 应该返回什么 为什么我们在c 中给出int main而不是void main 我开始学习 C 时 我想到了以下问题 main 总是返回 int 我不能声明无效主 代替int ma
  • 更改列表框中所选项目的背景颜色

    首先 我在这里和网络上搜索 发现很多解决方案如何更改 WPF 中列表框中所选项目的背景颜色 但没有找到如何在 Windows 应用商店应用程序中更改它 这个框架有点不同 我无法使用任何解决方案 我用这个 http social msdn m
  • Android:使用两个 ValueEventListener 从 firebase 数据库获取数据(在 Arraylist 过期之前设置适配器)

    我正在开发一个应用程序 数据库中有医生和患者等用户 患者数据和患者中可能有医生userIduserId在医生数据中 因为在应用程序中医生会看到有关他 她的患者的一些信息 我开发了这段代码 但在设置适配器之前我无法将患者信息添加到Arrayl
  • 使用增强几何从点到线的垂直地理距离

    我想得到距一点的垂直距离 t 到一条线段 p q 垂线不能与直线相交 p q 在这种情况下我想延长线路 p q 假设 然后绘制垂线以获得距离 p q t 都是 GPS 坐标 我正在使用增强几何 typedef boost geometry
  • 根据过去 90 天的登录情况计算活跃用户数

    我正在尝试进行一个查询 该查询将生成一个列表 显示我们每月有多少活跃用户 我们将活跃用户定义为过去 90 天内登录的用户 我可以通过这个轻松定义我们现在拥有的活跃用户数量 SELECT COUNT DISTINCT user id FROM
  • 检查对象 HashSet 的相等性

    我正在尝试比较两个哈希集Definition输入为EqualityComparer
  • Linux 中的 R 有哪些可用的 IDE? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 Linux 中的 R 有哪些好的 IDE 我尝试过 Rcmdr 和 Eclipse 但似乎都不具有与 Windows 中的 Tinn R 相同的可用性 还有其他选择吗 这是一个新来者
  • IP 地址的正则表达式

    我尝试使用以下源代码提取 wan ip 的值 IP 地址 怎么了 我确信正则表达式模式是正确的 String input var product pic fn var firmware ver 20 02 024 var wan ip 92
  • Ruby 中相当于 Java 中的“this”函数的是什么?

    在Java中 有一个 this 函数指向它的方法 Ruby 中有类似的东西吗 例如 有没有 def method this method end 等价的是self 这也是隐含的 所以self first name是相同的first name
  • 离子无限滚动

    我使用 wordpress 作为应用程序的后端 我想使用无限滚动 但我在连接文章时遇到问题 我正在使用工厂调用该服务 factory Worlds function http var worlds storageKey worlds fun
  • API Application Insights 良好使用实践

    我读过这个文档 https learn microsoft com en us azure application insights app insights api custom events metrics 有许多不同的 API 方法来
  • Django 查询集返回 DurationField 值(以秒为单位)

    我有两个模型 Post Comment 评论与帖子有 FK 关系 现在我想返回所有帖子及其 响应时间 我得到的响应时间是timedelta格式 我可以在几秒钟内收到它吗 我试过ExtractSecond但这不是我要找的 base posts
  • 如果省略必需的 *pipeline* 参数,是否可以强制 PowerShell 脚本抛出异常?

    当省略必需参数时 交互式 PowerShell 会话会提示用户 Shay Levy 提供了一个解决方法对于这个问题 问题是当您使用管道绑定参数时 解决方法不起作用 考虑这个例子 function f CmdletBinding param