function - Powershell implicitly converting arrays preventing use with Select -Property in v2 -
i struggling powershell implicitly modifying structure of data in powershell 2 exclusively. same logic works fine in powershell 4.
i've created helper function given field, alias and/or block expression can feed second function builds name/expression array can passed select -property request. worked fine in powershell 4 i'm working in mixed environment , when tried use on powershell 2 server script failed returning datatype conversion error.
cannot convert system.management.automation.psobject 1 of following types {system.string, system.management.automation.scriptblock}. + categoryinfo : invalidargument: (:) [select-object], notsupportedexception + fullyqualifiederrorid : dictionarykeyunknowntype,microsoft.powershell.commands.selectobjectco mmand + pscomputername : ####
i have rebuild array in calling function because explicit conversion array raises same exception.
if ($psversiontable["psversion"].major -eq 2) { #write-host "rebuilding setting" $origprops = [system.array](get-selectpropertyarray2 $propstoselect) $props = @() ($i =0 ; $i -lt $origprops.count ; $i++) { #write-host $i $props += @{n=([system.array]$origprops)[$i]["n"];e=(([system.array]$origprops)[$i]["e"])} } }
the following insufficient:
[system.array](get-selectpropertyarray2 $propstoselect)
when gettype() @ initialization, addition array , return statements type system.object, system.array
however in calling function becomes system.hashtable
here example of using function:
$propstoselect = @("name","path","pspath") # get-selectpropertyarrayset takes field return, alias , optional code block (to override default) $propstoselect += get-selectpropertyarrayset "." "asp_appallowclientdebug" { (get-webconfigurationproperty -filter /system.webserver/asp -name appallowclientdebug -pspath $pspath).value } $propstoselect += get-selectpropertyarrayset "." "asp_appallowdebugging" { (get-webconfigurationproperty -filter /system.webserver/asp -name appallowdebugging -pspath $pspath).value } $props = (get-selectpropertyarray2 $propstoselect) # following line 1 fails $config = get-item $pspath | select -property $props
the following line 1 fails unless rebuild array shown above.
$config = get-item $pspath | select -property $props
when write out types, following results:
ps c:\scripts\ps\bits> $p = get-selectpropertyarray2 $set init: ispublic isserial name basetype -------- -------- ---- -------- true true object[] system.array inc alias: ispublic isserial name basetype -------- -------- ---- -------- true true object[] system.array return: ispublic isserial name basetype -------- -------- ---- -------- true true object[] system.array ps c:\scripts\ps\bits> $p.gettype() ispublic isserial name basetype -------- -------- ---- -------- true true hashtable system.object
as can see last 1 quite different, if use on select statement fail exception shown previously.
here functions code:
<# .synopsis generates psobject field/alias/expression set use get-selectpropertyarray2 function. .description generates psobject field/alias/expression set use get-selectpropertyarray2 function. alias property optional .example get-selectpropertyarrayset "name" .example get-selectpropertyarrayset "accessflags" "access flags" .example get-selectpropertyarrayset "accessflags" "access flags" .example $propstoselect = @( (get-selectpropertyarrayset "name"), (get-selectpropertyarrayset "accessflags" "access flags"), (get-selectpropertyarrayset "authanonymous" "auth anonymous") ) get-selectpropertyarray2 $propstoselect .parameter field [string] name of field select .parameter alias [string] alias name of field select .parameter expression [scriptblock] script block use capturing data, allows custom field definitions outside standard aliasing. #> function get-selectpropertyarrayset { [cmdletbinding()] param( [parameter(mandatory=$true)] [alias("f")] [string]$field, [parameter(mandatory=$false)] [alias("a")] [string]$alias, [parameter(mandatory=$false)] [alias("e")] [scriptblock]$expression ) #write-host "building property set $field, $alias"# $expression" new-object psobject -property @{field=$field; alias=$alias; expression=$expression} }
and second function (the lines write out data types included commented out):
<# .synopsis generates array of script blocks can passed select statement. aliasing field name. .description generates array of script blocks can passed select statement. aliasing field name. input psobject field , alias property example: field: alias: ----------- ------------ name name myfield myfield alias helper function get-selectpropertyarrayset can used create psobject. .example $propstoselect = @( (get-selectpropertyarrayset "name"), (get-selectpropertyarrayset "accessflags" "access flags"), (get-selectpropertyarrayset "authanonymous" "auth anonymous") ) $propstoselect | get-selectpropertyarray2 .example $propstoselect = @( (get-selectpropertyarrayset "name"), (get-selectpropertyarrayset "accessflags" "access flags"), (get-selectpropertyarrayset "authanonymous" "auth anonymous") ) get-selectpropertyarray2 $propstoselect .example $propstoselect = @( (new-object psobject -property @{field="name"}), (new-object psobject -property @{field="accessflags"; alias="access flags"}), (new-object psobject -property @{field="authanonymous"; alias="auth anonymous"}) ) get-selectpropertyarray2 $propstoselect .parameter propertiestoselect [psobject] array containing field/alias pair use #> function get-selectpropertyarray2 { [cmdletbinding()] param( [parameter(mandatory=$true,valuefrompipeline=$true)] [alias("prop")] [psobject]$propertiestoselect ) begin { #initialize property-array select-object $proparray = @() #write-host "init" #write-host init: #$proparray.gettype() | out-host } process { #create script block each field in input array/pipeline #write-host "start" #$propertiestoselect | select field,alias foreach ($propertyset in $propertiestoselect) { $sb = $null if ($propertyset.gettype().name -eq "string") { #write-host string found $fieldname = $propertyset $fieldalias = $null } else { #write-host object found $fieldname = $propertyset.field $fieldalias = $propertyset.alias #use provided expression if present , valid type if ($propertyset.expression) { #write-host "expression found" #$propertyset.expression.gettype().name switch ($propertyset.expression.gettype().name) { "scriptblock" { #write-host "expression [scriptblock]" $sb = $propertyset.expression } "string" { #write-host "expression [string], converting [scriptblock]" $sb = [scriptblock]::create($propertyset.expression) } } } } if (! ($sb)) { <#write-host "no sb, using default";#> $sb = [scriptblock]::create("`$_.`"$fieldname`"") } #"mapping field: {0} --> {1}" -f $fieldname,$fieldalias |write-host if ($fieldalias) { #write-host inc alias: #$proparray.gettype() | out-host $proparray += @{n=[string]$fieldalias;e=($sb)} } else #singleton - no alias { #write-host inc field: #$proparray.gettype() |out-host $proparray += @{n=[string]$fieldname;e=($sb)} } } # return script block array #write-host "end" #write-host "<--$propertiestoselect" } end { #write-host "return:" #write-host return: #$proparray.gettype() |out-host return $proparray } }
there 2 differences in v2 vs v4 related issue:
objects returned
return
statement, wrappedpsobject
in v2:[type]::gettypearray(@(&{return "name"}))[0].fullname
return
system.management.automation.psobject
in v2 ,system.string
in v4.select-object
cmdlet in v2 can not handle wrapped objectsproperty
parameter:select-object (,[psobject]"name")
error in v2, ok in v4.
ps:
can ask 1 thing? benefits have this:
$propstoselect = @( get-selectpropertyarrayset "name" get-selectpropertyarrayset "accessflags" "access flags" get-selectpropertyarrayset "authanonymous" "auth anonymous" ) $props = get-selectpropertyarray2 $propstoselect
or this:
$propstoselect = @( new-object psobject -property @{field="name"} new-object psobject -property @{field="accessflags"; alias="access flags"} new-object psobject -property @{field="authanonymous"; alias="auth anonymous"} ) $props = get-selectpropertyarray2 $propstoselect
over this:
$props = @( "name" @{expression="accessflags"; name="access flags"} @{expression="authanonymous"; name="auth anonymous"} )
?
Comments
Post a Comment