5

Take the simple HashTable:

$data = @{
    First = 'Justin';
    Last = 'Dearing';
    StartDate = Get-Date '2002-03-23';
}

The key StartDate seems to contain a DateTime.

C:\Users\zippy\Documents> $data.StartDate.GetType().FullName
System.DateTime

However, if I attempt to perform binary serialization on it, I get an exception complaining that PSObject is not serializable.

$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $data)
$ms.Close()

Throws:

DocumentsException calling "Serialize" with "2" argument(s): "Type 'System.Management.Automation.PSObject' in Assembly 'System.Management.Automation, Versio
n=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable."
At C:\Users\jdearing\AppData\Local\Temp\b8967f99-0a24-41f7-9c97-dad2bc288bd9.ps1:12 char:14
+ $bf.Serialize <<<< ($ms, $data)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

This message goes away and everything works if I use an explicit cast to [DateTime] like so:

$data = @{
    First = 'Justin';
    Last = 'Dearing';
    StartDate = [DateTime] (Get-Date '2002-03-23');
}

So is Get-Date not really returning a DateTime, or is some other powershell oddity at work here.

Justin Dearing
  • 14,270
  • 22
  • 88
  • 161
  • I think everything in PS defaults to `PSObject` unless you explicitly define the type. It does dynamic datatype conversions, so it could just be returning a string that it interprets as a `System.Datetime` at runtime. – JNK Mar 09 '12 at 15:39
  • @JNK but why Object.GetType() interpret something as a DateTime that the binary formatter interprets as PSObject? – Justin Dearing Mar 09 '12 at 15:41
  • This is just guessing, but maybe because it's being interpreted at runtime (since you are running the `GetType()` method of a PSObject) - the binary formatter is a system class, not a PS class – JNK Mar 09 '12 at 15:44
  • 2
    ( get-Date '2002-03-23' ) -IS [psobject] True -- ( get-Date '2002-03-23' ) -IS [datetime] True -- [datetime]( get-Date '2002-03-23' ) -IS [datetime] True -- [datetime]( get-Date '2002-03-23' ) -IS [psobject] False – CB. Mar 09 '12 at 15:49
  • @Christian I think that's an answer, post it and I'll upvote. – JNK Mar 09 '12 at 15:53
  • @Christian you should make that an answer – Justin Dearing Mar 09 '12 at 15:53

2 Answers2

5

Based on MSDN:

PSOobject Class:

Encapsulates a base object of type Object or type PSCustomObject to allow for a consistent view of any object within the Windows PowerShell environment.

( get-Date '2002-03-23' ) -IS [psobject]
True

( get-Date '2002-03-23' ) -IS [datetime]
True

[datetime]( get-Date '2002-03-23' ) -IS [datetime]
True

[datetime]( get-Date '2002-03-23' ) -IS [psobject]
False
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CB.
  • 58,865
  • 9
  • 159
  • 159
3

Every object in PowerShell is actually wrapped mostly transparently in a PSObject. I say mostly transparently, because there are more than a few bugs in PowerShell that omit to remove the wrapper before leaking the object to another API. This causes all sorts of issues, much like the one you see now. Search connect.microsoft.com/powershell for PSObject wrapper. I believe this is no longer an issue in v3 with the new DLR-based engine.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
x0n
  • 51,312
  • 7
  • 89
  • 111
  • Just fired up VirtualBox and the code does work. Thanks for clarifying. – Justin Dearing Mar 09 '12 at 21:02
  • 1
    here's another example where psobject screws things up; http://stackoverflow.com/questions/837095/why-does-powershells-return-keyword-cause-type-errors – x0n Mar 11 '12 at 02:53