【问题标题】:Pass null datetime parameter in powershell在PowerShell中传递空日期时间参数
【发布时间】:2019-10-16 16:22:01
【问题描述】:

所以我有一个 powershell 脚本,它将区域和日期时间作为输入,并在脚本内部调用存储过程。

存储过程有两个输入——区域和日期时间戳;日期时间戳始终为空。我该如何解析它?

function Reset {

param ([string]$region,[nullable[Datetime]]$statustimestamp)

        $conn = New-Object System.Data.SqlClient.SqlConnection("Server=SQL,15010; Database='STG';User ID=SVC;Password=password;Integrated Security=FALSE")
        $conn.Open()
        $cmd = $conn.CreateCommand()
        $cmd.CommandText = "dbo.Reset'$region' ,'$statustimestamp'"
        $adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
        $dataset = New-Object System.Data.DataSet
        [void]$adapter.Fill($dataset)
        $dataset.tables[0]
        $cmd.CommandText    
        $dataset.Tables[0] | Export-CSV M:\MyReport.csv -encoding UTF8 -NoTypeInformation    
        Write-Host 'New report M:\MyReport.csv has been successfully generated' 
    }

我执行为

Rest -region IN -statustimestamp NULL

我收到以下错误

重置:无法处理参数“statustimestamp”的参数转换。无法将值“NULL”转换为类型“System.DateTime”。
错误:字符串未被识别为有效的日期时间。有一个从索引 0 开始的未知单词。
在 line:1 char:59
+ 重置 -region AU -statustimestamp NULL
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Reset], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Reset

【问题讨论】:

  • 你可以在没有日期参数的情况下调用你的函数,比如Rest -region IN

标签: powershell


【解决方案1】:

补充dee-see's helpful answer

注意:无论您的参数如何声明,脚本/函数中的$PSBoundParameters.ContainsKey('<parameter-name>') 会告诉您参数是否显式传递给给定参数(默认值不不计算);例如,在您的问题中调用(是否成功),$PSBoundParameters.ContainsKey('statustimestamp') 将指示 $true

如果您希望您的参数值为$null省略

将您的参数简单地声明为[Datetime] $statustimestamp 并且在调用时不向其传递任何参数;然后$statustimestamp隐式成为$null

# Declare a parameter in a script block (which works like a function)
# and invoke the script block without an argument for that parameter:
PS> & { param([Datetime] $statustimestamp) $null -eq $statustimestamp }

True  # $statustimestamp was $null

如果您想支持明确地将$null 作为参数传递:

如果您声明一个 强制 参数,这可能是必要的,但您希望允许 $null 作为应使用默认值的显式信号。

不幸的是,参数声明的细节目前取决于参数的数据类型是引用类型(例如[string][System.IO.FileInfo])还是值类型(例如[int][datetime]
您可以检查给定类型的 .IsValueType 属性以了解它是值类型($true) 还是引用类型($false);例如:[datetime].IsValueType 产生 $true)。

如果参数类型是引用类型,可以使用[AllowNull()]属性:

PS> & { 
  param(
    [AllowNull()]
    [Parameter(Mandatory)]
    [System.IO.FileInfo] $Foo  # System.IO.FileInfo is a *reference type*
  )
  $null -eq $Foo 
} -Foo $null

True  # $Foo was $null

不幸的是,相同的技术不适用于 值类型,例如 [DateTime],因此您的 参数确实必须输入为 [Nullable[DateTime],就像你的问题一样:

PS> & { 
  param(
    [Parameter(Mandatory)]
    [AllowNull()] # Because the parameter is mandatory, this is *also* needed.
    [Nullable[DateTime]] $Foo  # System.DateTime is a *value type*
  )
  $null -eq $Foo 
} -Foo $null

True  # $Foo was $null

注意:这些要求 - 需要注意值类型和引用类型之间的区别以及需要使用 [Nullable[T]] 类型 - 对于 PowerShell 来说是模糊且不具有特征的。

取消这些要求以支持统一的方法(使其适用于值类型,就像它已经适用于引用类型一样)this proposal on GitHub的主题。

【讨论】:

    【解决方案2】:

    PowerShell 中的 Null 由 $null 而不是 NULL 表示,这就是错误消息说字符串 NULL 无法转换为(可为空)DateTime 的原因。

    Rest -region IN -statustimestamp $null
    

    您也可以完全省略-statustimestamp 参数。

    【讨论】:

    • "您也可以完全省略 -statustimestamp 参数。" - 你可以,但这意味着一个微小的变化,即$PSBoundParameters 将不再包含statustimestamp 的条目
    • 传递 $null 或不解析参数确实有助于执行。但它默认为 1/1/1900 12:00:00 AM,我想将值传递给它 null
    • 我能够通过在我的脚本中使用 Exec 来超越它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多