问题
pracl is a sysinternal command that can be used to list the ACLs of a directory. I have a list of shares and I want to create a csv file such that for each ACL entry, I want the share path in one column and share permission in the next. I was trying to do that by using the following code
$inputfile = "share.txt"
$outputFile = "out.csv"
foreach( $path in Get-Content $inputfile)
{
$results=.\pracl.exe $path
{
foreach ($result in $results) {write-host $path,$line}
}
$objResult = [pscustomobject]@{
Path = $Path
Permission = $line
}
$outputArray += $objResult
$objresult
}
$outputArray | Export-Csv -Path $outputfile -NoTypeInformation
It failed with the following error :-
Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
At C:\Users\re07393\1\sample.ps1:14 char:1
+ $outputArray += $objResult
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any suggestions ?
回答1:
You're trying to create an array of [pscustomobject]
s in your $outputArray
variable iteratively, using +=
, but you're not initializing $outputArray
as an array - see the bottom section for an explanation of the resulting behavior.
Thus, the immediate solution to your problem is to do just that:
# Do this before your `foreach` loop, then `+=` will work for appending elements.
$outputArray = @()
However, using +=
to add to arrays is inefficient, because in reality a new array instance must be created every time, because arrays are immutable data structures. That is, every time +=
is used, PowerShell creates a new array instance behind the scenes to which the existing elements as well as the new element are copied.
A simpler and much more efficient approach is to let PowerShell create an array for you, by using the foreach
loop as an expression and assigning it to a variable as a whole:
That is, whatever is output in every iteration of the loop is automatically collected by PowerShell:
A simplified example:
# Create an array of 10 custom objects
[array] $outputArray = foreach ($i in 1..10) {
# Create and implicitly output a custom object in each iteration.
[pscustomobject] @{
Number = $i
}
}
Note the use of type constraint [array]
to the left of $outputArray
, which ensures that the variable value is always an array, even if the loop happens to produce just one output object (in which case PowerShell would otherwise just store that object itself, and not wrap it in an array).
Note that you can similarly use for
, if
, do
/ while
/ switch
statements as expressions.
In all cases, however, as of PowerShell 7.0, these statements can only serve as expressions by themselves; regrettably, using them as the first segment of a pipeline or embedding them in larger expressions does not work - see this GitHub issue.
As for what you tried:
$outputArray += $objResult
Since you didn't initialize $outputArray
before the loop, the variable is implicitly created in the loop's first iteration:
If the LHS variable doesn't exist yet, +=
is effectively the same as =
: that is, the RHS is stored as-is in the LHS variable, so that $outputArray
now contains a [pscustomobject]
instance.
In the second iteration, because $outputArray
now has a value, +=
now tries to perform a type-appropriate +
operation (such as numeric addition for numbers, and concatenation for strings), but no +
(op_Addition()
) operation is defined for type [pscustomobject]
, so the operation fails with the error message you saw.
来源:https://stackoverflow.com/questions/59277625/powershell-piping-output-of-pracl-command-to-array