Versioninfo is gone too. A workaround is to use start-threadjob instead.
get-childitem file | start-job { $input.basename } | receive-job -wait -auto
file
# no output
Name Value
---- -----
PSVersion 7.0.0
PSEdition Core
GitCommitId 7.0.0
OS Microsoft Windows 10.0.14393
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Datetime's seems to be an exception, the scriptproperty becomes a string:
get-date | start-job { $input.datetime } | receive-job -wait -auto
Monday, March 23, 2020 8:34:23 AM
The behavior is certainly surprising.
What properties BaseName and VersionInfo (and Group, Size, UnixMode and User) have in common is not only that they're ETS type members, but, specifically, of type ScriptProperty.
While (static NoteProperty copies of the values of) the conceptually related CodeProperty members _are_ included, (static copies of) the ScriptProperty members seem to be omitted entirely from the (de)serialized objects.
@SeeminglyScience, can you shed light on this?
A workaround is to use
start-threadjobinstead.
Indeed; because a _thread_ job executes in-process, the remoting / background (out-of-process) serialization infrastructure isn't involved, and the new thread receives the caller's object _as-is_ (if it is an instance of a reference type), which by definition maintains type fidelity.
Note that Start-ThreadJob is more than just a workaround: in most use cases, it is preferable to Start-Job (child process-based jobs), for type fidelity, execution speed, and resource use.
@jszabo98 , [datetime] is not an exception per se: a handful of well-known types are deserialized with type fidelity (see this SO answer), and [datetime] (System.DateTime) is among them.
The question is whether all non-well-known types - those that are _emulated_ with [psobject] - lack static copies of ScriptProperty members.
@SeeminglyScience, can you shed light on this?
Depends on the thread that the serializer is called on. For example, do this:
[Management.Automation.PSSerializer]::Deserialize([Management.Automation.PSSerializer]::Serialize((gi .)))|gm
BaseName is present with the above. In order for ScriptProperty's to be serialized the following conditions need to be met:
In other words, you need to call it from the pipeline thread while controlling pipeline execution, otherwise it isn't safe. My guess is that Start-Job calls the serializer on a different thread for performance.
Thanks, @SeeminglyScience.
It looks like Invoke-Command is also affected - and therefore, I presume, all remoting:
# No output.
ELEV> icm -computername . { param($fi) $fi | gm BaseName } -args (gi /)
Minishells seem to be the only exception; there, inclusion of ScriptPropertys currently _does_ work - or can you think of others?:
# OK
PS> pwsh -nop -c { param($fi) $fi | gm BaseName } -args (gi /)
TypeName: Deserialized.System.IO.DirectoryInfo
Name MemberType Definition
---- ---------- ----------
BaseName NoteProperty string BaseName=/
iirc minishell doesn't actually use the remoting protocol, just serializes over standard in/out. Export-CliXml probably works too.
Thanks, @SeeminglyScience; you're correct about Export-CliXml (and ConvertTo-Xml).
gi / | Export-CliXml t.xml; sls -quiet BaseName -lp t.xml; ri t.xml # $true
gi / | ConvertTo-Xml -As String | sls BaseName -quiet # $true