2

我正在尝试编写一个 PowerShell 脚本,它将生成一个包含两列的信息表:名称和日期(将从第三方应用程序中检索 - 在本例中为 svn.exe)。

整个脚本运行良好,但我正在努力获取服务器发送回 DataTable 的日期。这是我的脚本的简化版本:

# Set up a DataTable and initialise columns
$table = New-Object system.Data.DataTable “Test Table”
$col1 = New-Object system.Data.DataColumn Name,([string])
$col2 = New-Object system.Data.DataColumn DateFromServer,([DateTime])
$table.columns.add($col1)
$table.columns.add($col2)

# Create a new row and add the data
$row = $table.NewRow()
$row.Name = "Test"
$lastCommit = GetDateFromExternalApp
$lastCommit.GetType() # this returns DateTime as I would expect
$row.DateFromServer = $lastCommit # this throws up an error
$table.Rows.Add($row)

# Output the table
$table | Format-Table -AutoSize

# This function simulates what the actual function does
# (the real one goes to SVN and pulls down data, but it
# ends up with the same resulting date)
Function GetDateFromExternalApp
{   
    $externalAppDate = "2012-09-17T16:33:57.177516Z"

    return [DateTime]($externalAppDate)
}

问题(在上面脚本的注释中指出)是,虽然该函数似乎很高兴返回一个 DateTime 实例,但当我尝试将其添加到表行的 DateFromServer 列中时,它会抛出一个错误:

Exception setting "DateFromServer": "Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.IConvertible'.Couldn't store <18/09/2012 2:33:57 AM> in DateFromServer  Column.  Expected type is DateTime." At line:13 char:6
+ $row. <<<< DateFromServer = $lastCommit
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

但是,对 $lastCommit.GetType() 的调用表明这确实是一个 DateTime - 事实上,如果我在脚本中的某处添加这一行:

$lastCommit

然后我可以看到一个格式很好的日期时间,表明它确实在解析它并正确转换它:

Date        : 18/09/2012 12:00:00 AM
Day         : 18
DayOfWeek   : Tuesday
DayOfYear   : 262
Hour        : 2
Kind        : Local
Millisecond : 177
Minute      : 33
Month       : 9
Second      : 57
Ticks       : 634835324371775160
TimeOfDay   : 02:33:57.1775160
Year        : 2012
DateTime    : Tuesday, 18 September 2012 2:33:57 AM

因此,我对为什么会出现上述异常感到非常困惑。我意识到 PowerShell 的函数返回值与 C# 不同,但在我看来,函数返回的是正确的类型!

4

3 回答 3

4

这里的问题是由于 PowerShell 的类型适配系统中的一个错误(如果您还没有这样做,我建议您向 Microsoft 报告此问题)。

在 PowerShell 中处理对象时,实际上是在使用PSObject包装器。大多数调用(如GetType)被转发到底层对象,但您可以添加不与对象本身交互的其他成员:

PS> Get-Date | Add-Member NoteProperty Yowza 'for example' -PassThru | Format-List y*
Yowza : for example
Year  : 2012


通常这不是问题,因为 PowerShell 具有广泛的类型强制功能。但是,在这种情况下,用于支持属性访问语法DataRow的类型似乎存在错误。DataRowAdapter如果您直接使用索引器$row['DateFromServer'] = $lastCommit而不是$row.DateFromServer,则在将值发送到 .NET 类型之前会正确解包该值。

您也可以通过自己解开值来解决这个问题,或者使用强制转换(如vonPryz 已经展示的那样:)[DateTime]$lastCommit,或者通过检索BaseObject( $lastCommit.PSObject.BaseObject)。

于 2012-09-29T00:22:32.163 回答
3

我也想知道这种行为的原因。

无论如何,您可以通过将日期变量强制转换为 DateTime 或明确将其声明为 1 来解决此问题。像这样,

...
$row.DateFromServer = [DateTime]$lastCommit # Doesn't throw exception
...

或者

...
[DateTime]$lastCommit = GetDateFromExternalApp
$row.DateFromServer = $lastCommit # Doesn't throw exception
...
于 2012-09-19T05:56:52.187 回答
0

我怀疑原因如错误消息中所述:

“无法将'System.Management.Automation.PSObject'类型的对象转换为'System.IConvertible'类型......预期类型是DateTime。” 在行:13 字符:6

这就是说 PowerShell 尝试将 $lastCommit 转换为日期和时间但失败了。最好的方法是,正如 vonPryz 建议的那样 - 将其转换为 [datetime]

要更清楚地看到问题,请尝试同时查看:$lastcommit.gettype() 和 $row.DateFromServer.gettype()

我没有要检查的 GetDateFromExternalApp

于 2012-09-19T09:43:29.033 回答