重用管道的自定义对象时出现意外结果

时间:2018-03-09 11:24:28

标签: powershell pipeline psobject new-object

前段时间我更改了Join-Object cmdlet,这似乎导致了一个在我的任何测试中都没有显示的错误。
更改的目标主要是代码最小化并尝试通过准备自定义PSObject并在管道中重复使用来提高性能 由于Join-Object cmdlet相当复杂,我创建了一个简化的cmdlet来显示具体问题:
(PowerShell版本为:[INFO] Scanning for projects... [INFO] [INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building FAM.Automation.Selenium 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ FAM.Automation.Selenium --- [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.6.1:compile (default-compile) @ FAM.Automation.Selenium --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ FAM.Automation.Selenium --- [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.6.1:testCompile (default-testCompile) @ FAM.Automation.Selenium --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.19.1:test (default-test) @ FAM.Automation.Selenium --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.201 s [INFO] Finished at: 2018-03-09T19:02:34+08:00 [INFO] Final Memory: 11M/155M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project FAM.Automation.Selenium: Unable to parse configuration of mojo org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test for parameter suiteXmlFiles: Basic element 'suite' must not contain child elements -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginConfigurationException

5.1.16299.248

直接测试输出完全符合我的预期:

Function Test($Count) {
    $PSObject = New-Object PSObject -Property @{Name = $Null; Value = $Null}
    For ($i = 1; $i -le $Count; $i++) {
        $PSObject.Name = "Name$i"; $PSObject.Value = $i
        $PSObject
    }
}

假设我是否将结果分配给变量(例如Test 3 | ft Value Name ----- ---- 1 Name1 2 Name2 3 Name3 )并不重要,但确实如此:

$a

所以,除了分享这段经历之外,我想知道这是编程缺陷还是PowerShell bug / quirk?

1 个答案:

答案 0 :(得分:3)

您的原始方法在概念上确实存在缺陷,因为您多次输出相同的对象,反复修改其属性

输出中的差异由管道的逐项处理解释

  • 输出到控制台(通过ft / Format-Table)打印{em>当前状态$PSObject在每次迭代中,它表明一切都很好。

  • 相比之下,捕获变量会在所有迭代完成后反映$PSObject的状态,此时它只包含最后次迭代的值,Name33

您可以验证输出数组$a确实引用了相同的自定义对象三次,如下所示:

[object]::ReferenceEquals($a[0], $a[1]) # $True
[object]::ReferenceEquals($a[1], $a[2]) # $True

因此,解决方案是每次迭代中创建一个独特的[pscustomobject]实例

PSv3 + 提供用于创建自定义对象的语法糖:您可以将哈希表(文字)转换为[pscustomobject]。由于这也每次都会创建一个新实例,因此您可以使用它来简化您的功能:

Function Test($Count) {
  For ($i = 1; $i -le $Count; $i++) {
    [pscustomobject] @{ Name = "Name$i"; Value = $i  }
  }
}

这是您自己的与PSv2兼容的解决方案

Function Test($Count) {
    $Properties = @{}
    For ($i = 1; $i -le $Count; $i++) {
        $Properties.Name = "Name$i"; $Properties.Value = $i
        New-Object PSObject -Property $Properties
    }
}