[英]Error when creating a New-Object PSObject
This powershell script takes up to 8 rows in a csv file and combines them into one row by duplicating the columns, and then saving in a result file (the first result file saved fine).这个 powershell 脚本在 csv 文件中最多占用 8 行,并通过复制列将它们组合成一行,然后保存在结果文件中(第一个结果文件保存得很好)。 If there are 16 rows in the csv it is meant to save a second result file etc.
如果 csv 中有 16 行,则意味着保存第二个结果文件等。
eg in rows.csv:例如在 rows.csv 中:
first_field second_field third_field fourth_field第一场第二场第三场第四场
ball bat racket club球棒球拍俱乐部
orange banana mango pear橙色香蕉芒果梨
In result1.csv:在结果 1.csv 中:
first1 second1 third1 fourth1 first2 second2 third2 fourth2第一1 第二1 第三1 第四1 第一2 第二2 第三2 第四2
ball bat racket club orange banana mango pear球棒球拍俱乐部橙色香蕉芒果梨
I get an error:我得到一个错误:
New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter 'Property'. Specified method is not supported.
At C:csv.ps1:19 char:42
+ $results = New-Object PSObject -Property $details
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand
Note that the first new-object creation worked ok on line 16. In Powershell ISE if I rerun the script it errors on line 16 too.请注意,第 16 行的第一个新对象创建工作正常。在 Powershell ISE 中,如果我重新运行脚本,它也会在第 16 行出错。 I have no idea what is wrong here but assume I need to destroy the PSObject after saving each csv file?
我不知道这里出了什么问题,但假设我需要在保存每个 csv 文件后销毁 PSObject?
$csvObjects = import-csv C:\rows.csv
$results = @()
$counter=1
foreach ($item in $csvObjects){
$detailsnew = [ordered] @{
"first$counter" = $item.'First_field'
"second$counter" = $item.'Second_field'
"third$counter" = $item.'Third_field'
"fourth$counter" = $item.'Fourth_field'
}
$details += $detailsnew
# modulus comparison returns remainder - write out file every 8
if ($counter % 8 -eq 0) {
if ($counter -eq 8) {
#works on line below on first run but fails on subsequent runs within Powershell ISE
$results = New-Object PSObject -Property $details
}
if ($counter -eq 16) {
# fails on line below
$results2 = New-Object PSObject -Property $details
}
$quotient = $counter / 8
$results | export-csv -Path c:\result"$quotient".csv -noType
$details = @()
$results = @()
}
$counter++
}
#write out final file if number not divisible by 8
if (-not($counter % 8 -eq 0)) {
$results += New-Object PSObjectF -Property $details
$modulo = $counter % 8
$quotient_plus1 = (($counter-$modulo) / 8) +1
$results | export-csv -Path C:\result"$quotient_plus1".csv -noType
}
tl;dr tl;博士
$details = @()
should be $details = [ordered] @{}
$details = @()
应该是$details = [ordered] @{}
To also make repeated executions from the ISE work as intended, place another $details = [ordered] @{}
statement before the loop.为了使ISE 的重复执行也按预期工作,请在循环之前放置另一个
$details = [ordered] @{}
语句。
In the very first loop iteration, $details
is initially undefined , and $details += $detailsnew
assigns the $detailsnew
(ordered) hash table (an [ordered] @{... }
hash table in PowerShell is of type System.Collections.Specialized.OrderedDictionary
) as-is to $details
(that is, with $details
undefined, +=
effectively behaves the same as =
).在第一个循环迭代中,
$details
最初是undefined ,并且$details += $detailsnew
分配$detailsnew
(ordered) hash table (an [ordered] @{... }
hash table in PowerShell is type System.Collections.Specialized.OrderedDictionary
)原样到$details
(即, $details
未定义时, +=
实际上与=
行为相同)。
The $detailsnew
hash tables created in the next 7 iterations are then merged by +=
into the hash table already stored in $details
.在接下来的 7 次迭代中创建的
$detailsnew
hash 表然后通过+=
合并到已存储在$details
中的 hash 表中。
After the 8th iteration, you mistakenly (re-)initialize $details
as an array ( @()
), which is the source of the problem: subsequent use of +=
then adds a new array element to $details
instead of merging the hash table entries, and passing an array rather than a hash table (or any dictionary type that implements System.Collections.IDictionary
) to New-Object
's -Property
parameter then - predictably - fails.在第 8 次迭代之后,您错误地(重新)将
$details
初始化为数组( @()
),这是问题的根源:随后使用+=
然后将新的数组元素添加到$details
而不是合并 hash表条目,并将数组而不是 hash 表(或任何实现System.Collections.IDictionary
的字典类型)传递给New-Object
的-Property
参数,然后 - 可以预见 - 失败。
$details
as an ordered hash table: $details = [ordered] @{}
$details
初始化为有序的 hash 表: $details = [ordered] @{}
In Powershell ISE if I rerun the script it errors on line 16 too.
在 Powershell ISE 中,如果我重新运行脚本,它也会在第 16 行出错。
The PowerShell ISE dot-sources the scripts it runs , which means that variables from previous invocations can linger . PowerShell ISE 对其运行的脚本进行点源,这意味着来自先前调用的变量可能会持续存在。
As an aside: This equally applies to Visual Studio Code with its PowerShell extension , which you should consider migrating to [1] .顺便说一句:这同样适用于带有PowerShell 扩展名的 Visual Studio Code,您应该考虑将其迁移到[1] 。 However, there you can opt to create a new, temporary session instead , as described in the bottom section of this answer .
但是,您可以选择创建一个新的临时 session ,如本答案底部所述。
In your case, this means that $details
already is an array in the very first iteration when you re-execute the script in the ISE.在您的情况下,这意味着当您在 ISE 中重新执行脚本时,
$details
在第一次迭代中已经是一个数组。
[1] The PowerShell ISE is no longer actively developed and there are reasons not to use it (bottom section). [1] PowerShell ISE 不再积极开发,并且有理由不使用它(底部)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.