3

I am finding that in some circumstances, powershell 2.0 is passing Object[] arrays containing PSObjects - instead of the real contained types - when passed as a param to .Net code. I think this is a powershell 2.0 bug, but I can't find any mention of it.

$Source = @" 
public static class DotNetTypeInfo
{ 
    public static string TypeOfNthElement(object[] oa, int n)
    {
        return oa[n].GetType().ToString();
    }    
} 
"@ 
Add-Type -TypeDefinition $Source -Language CSharp  

$h = @{}
$h.foo = "bar"
#$h["foo"] = "bar" # uncomment this to fix! (Why?)

$testdata = @($h) # To .net, passed Object[] containing PSObject, not Hashtable!

# other examples that behave similarly badly - uncomment to try
$a = (1,2) # should result in an arry of System.Int32
function getA() { $a } # uncaptured value returned
function getB() { return $a } # explicit return
# $testdata = $a    # this works fine
# $testdata  = getA # also fine
# $testdata  = getB # To .net, passed Object[] containing PSObject, not Int32!

Write-Host "From powershell"
'  $testdata[0].GetType()         ' + $testdata[0].GetType().ToString()
Write-Host "From .Net"
'  TypeOfNthElement($testdata,0)  ' + [DotNetTypeInfo]::TypeOfNthElement($testdata,0)

This prints:

From powershell
  $testdata[0].GetType()         System.Collections.Hashtable
From .Net
  TypeOfNthElement($testdata,0)  System.Management.Automation.PSObject

The last line is very surprising; the C# code is receiving an Object[] containing PSObject instead of an Object[] containing Hashtable. This makes it impossible to use with existing .Net libraries that aren't expecting a PSObject.

Curiously, I can work around the problem if I use $h["foo"] = "bar" instead of $h.foo = "bar".

I also see similar effects depending on how you return values from a function - uncomment the getA and getB examples to try.

By request - selected highlights from $psversiontable, edited for brevity:

Key   : CLRVersion, Value : 2.0.50727.5472
Key   : BuildVersion, Value : 6.1.7601.17514
Key   : PSVersion, Value : 2.0
Key   : PSCompatibleVersions, Value : {1.0, 2.0}
Key   : SerializationVersion, Value : 1.1.0.1

I can replicate this problem using powershell 2.0 on XP, Win7 and Windows Server 2008 R2

bacar
  • 9,761
  • 11
  • 55
  • 75
  • if you're still watching - can I get an explanation for the downvote? – bacar Feb 11 '14 at 10:02
  • I can't find whether PS 2 is still patched/maintained, but I've [submitted a bug report](https://connect.microsoft.com/PowerShell/feedback/details/817702/powershell-2-0-sometimes-passes-a-psobject-instead-of-its-base-object-to-net-code) – bacar Feb 18 '14 at 11:44

1 Answers1

0

I tried your code on a W2K3 Box with PowerShell V2.0, and the third test returned ["hello","world"].

I can receive you error if getdata3 looks like :

function getdata3()
{
  $a
  return " "
}

So my conclusion is that you've got some "hidden" character in your script code, that was lost in the copy/past to this question.

On more thing : Can you give the values of $psversiontable on your PowerShell ?

JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • Do you look for hidden characters in the source ? – JPBlanc Feb 09 '14 at 19:33
  • I've pasted it as is _from_ SO back into a script, same problem. So I don't have anything that you don't have here. – bacar Feb 09 '14 at 23:32
  • Your function should not raise that error either (there is no circular reference). I get the same problem as you with this function, and it goes away if I remove the `return` keyword. So I think you may have replicated the problem. – bacar Feb 10 '14 at 00:01
  • revamped the Q with lots of new info. – bacar Feb 11 '14 at 00:19