{"id":3201,"date":"2010-01-07T11:04:08","date_gmt":"2010-01-07T11:04:08","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2010\/01\/07\/how-objects-are-sent-to-and-from-remote-sessions\/"},"modified":"2019-02-18T13:06:01","modified_gmt":"2019-02-18T20:06:01","slug":"how-objects-are-sent-to-and-from-remote-sessions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/how-objects-are-sent-to-and-from-remote-sessions\/","title":{"rendered":"How objects are sent to and from remote sessions"},"content":{"rendered":"<p>Instead of piping unstructured text, Windows PowerShell pipes objects between commands in a pipeline.&#160; As a consequence PowerShell remoting also deals with objects when passing data to and from remote sessions.&#160; This post explains how remote objects are serialized and which types of objects can be sent with full fidelity.&#160; You might want to refer to this post when <a href=\"http:\/\/blogs.msdn.com\/powershell\/archive\/2009\/12\/29\/arguments-for-remote-commands.aspx\">passing arguments to remote commands<\/a> or when designing remoting-friendly cmdlets or functions.<\/p>\n<h3>Property bags<\/h3>\n<p>You might have noticed \u201cDeserialized\u201d prefix in front of type names of some objects received from a remote session:<\/p>\n<pre>PS C:\\&gt; $s = New-PSSession localhost\nPS C:\\&gt; Invoke-Command $s { Get-Process } | Get-Member\n\n\n   <strong>TypeName: Deserialized.System.Diagnostics.Process\n...<\/strong><\/pre>\n<p>Objects that have the &quot;Deserialized.&quot; prefix in their type names are property bags that contain a deserialized representation of public properties of the corresponding remote, live objects. As you can see in the output of Get-Member those property bags don&#8217;t expose any methods except ToString(), because usually methods cannot be invoked in the remote session (for example, System.Diagnostics.Process.Kill() can&#8217;t act on a remote process). Similarly setting and getting property values of the property bags doesn&#8217;t execute any code (for example WorkingSet property of Deserialized.System.Diagnostics.Process.WorkingSet is only a snapshot and doesn&#8217;t get updated when the remote process uses more memory). <\/p>\n<p>Serialization settings (i.e. serialization depth) are controlled to some extent by the extended type system and types.ps1xml files.&#160; See an <a href=\"http:\/\/blogs.msdn.com\/powershell\/archive\/2007\/05\/01\/object-serialization-directives.aspx\">older post<\/a> for more details.<\/p>\n<h3>Primitive types<\/h3>\n<p>Some objects can be deserialized into a &quot;live&quot; object. An example are some primitive types, like integers:<\/p>\n<pre>PS C:\\&gt; $s = New-PSSession\nPS C:\\&gt; Invoke-Command $s { 123 } | Get-Member\n\n\n   <strong>TypeName: System.Int32<\/strong>\n...<\/pre>\n<p>Below is a list of all primitive (serialization-wise) types:<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.byte.aspx\">Byte<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.sbyte.aspx\">SByte<\/a>, Byte[] <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.int16.aspx\">Int16<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.int32.aspx\">Int32<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.int64.aspx\">Int64<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.uint16.aspx\">UInt16<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.uint32.aspx\">UInt32<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.uint64.aspx\">UInt64<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.decimal.aspx\">Decimal<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.single.aspx\">Single<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.double.aspx\">Double<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.timespan.aspx\">TimeSpan<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.datetime.aspx\">DateTime<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.progressrecord(VS.85).aspx\">ProgressRecord<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.char.aspx\">Char<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.string.aspx\">String<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xml.xmldocument.aspx\">XmlDocument<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.securestring.aspx\">SecureString<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.boolean.aspx\">Boolean<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.guid.aspx\">Guid<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.uri.aspx\">Uri<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.version.aspx\">Version<\/a> <\/li>\n<\/ul>\n<h3>Almost-primitive types<\/h3>\n<p>Some types are not deserialized with full fidelity, but nevertheless behave as primitive types for most practical purposes. <\/p>\n<p>For example <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.enum.aspx\">Enums<\/a> are deserialized into an underlying integer (with a preserved ToString value).&#160; The deserialized value is almost indistinguishable from the original enum, because PowerShell can implicitly cast from the integer to the original enum type.&#160; One can also request an explicit cast: scripters can just use the scripting language and .NET developers can call into one of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.languageprimitives(VS.85).aspx\">LanguagePrimitives<\/a> methods to perform a cast (using those methods will make the cast go through the scripting engine and take account of PSObject wrapping and other casting quirks).<\/p>\n<p>Similarly, deserializer will preserve contents of lists, but might change the actual type of the container. The change of the underlying container type is usually invisible, because there is a built-in cast from any container to an appropriate array. Below is a list of recognized and handled container types:<\/p>\n<ul>\n<li>Lists (all types implementing <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.collections.ienumerable.aspx\">IEnumerable<\/a>) are deserialized into an <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.collections.arraylist.aspx\">ArrayList<\/a> <\/li>\n<li>Dictionaries (all types implementing <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.collections.idictionary.aspx\">IDictionary<\/a>) are deserialized into a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.collections.hashtable.aspx\">Hashtable<\/a> <\/li>\n<\/ul>\n<p>The bottom line of this section is that non-primitive types can be remoting-friendly as long as they support casting from a primitive value.<\/p>\n<h3>Rehydration<\/h3>\n<p>PowerShell exposes a mechanism by which third parties can instruct the deserializer to &quot;rehydrate&quot; additional types into &quot;live&quot; objects.&#160; Rehydration is done by casting the deserialized property bag to the type specified in &quot;TargetTypeForDeserialization&quot; property in the Types.ps1xml file.&#160; Below is an example taken out of $pshome\\types.ps1xml, that shows how rehydration is set up for System.Net.IPAddress type:<\/p>\n<pre>   \n    &lt;Type&gt;\n         &lt;Name&gt;Deserialized.System.Net.IPAddress&lt;\/Name&gt;\n         &lt;Members&gt;\n             &lt;MemberSet&gt;\n                &lt;Name&gt;PSStandardMembers&lt;\/Name&gt;\n                &lt;Members&gt;\n                    &lt;NoteProperty&gt;\n                        &lt;Name&gt;TargetTypeForDeserialization&lt;\/Name&gt;\n                        &lt;Value&gt;Microsoft.PowerShell.DeserializingTypeConverter&lt;\/Value&gt;\n                    &lt;\/NoteProperty&gt;\n                &lt;\/Members&gt;\n              &lt;\/MemberSet&gt;\n          &lt;\/Members&gt;\n    &lt;\/Type&gt;<\/pre>\n<p>The Microsoft.PowerShell.DeserializingTypeConverter is a special class that inherits from System.Management.Automation.PSTypeConverter and provides details of type conversion from Deserialized.System.Net.IPAddress to a live IPAddress object.&#160; The rehydration of IPAddress simply passes a deserialized ToString value to the static IPAddress.Parse method, but reusing of the type casting mechanism lets other parties provide rehydration that performs arbitrarily complex operations.<\/p>\n<p>We provide built-in rehydration for some of PowerShell types\u2026 :<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.psprimitivedictionary(VS.85).aspx\">PSPrimitiveDictionary<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.switchparameter(VS.85).aspx\">SwitchParameter<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.pslistmodifier(VS.85).aspx\">PSListModifier<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.pscredential(VS.85).aspx\">PSCredential<\/a> <\/li>\n<\/ul>\n<p>\u2026 as well as for some types from base class libraries:<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.net.ipaddress.aspx\">IPAddress<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.net.mail.mailaddress.aspx\">MailAddress<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.globalization.cultureinfo.aspx\">CultureInfo<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.cryptography.x509certificates.x509certificate2.aspx\">X509Certificate2<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.cryptography.x509certificates.x500distinguishedname.aspx\">X500DistinguishedName<\/a> <\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.accesscontrol.directorysecurity.aspx\">DirectorySecurity<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.accesscontrol.filesecurity.aspx\">FileSecurity<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.accesscontrol.registrysecurity.aspx\">RegistrySecurity<\/a> <\/li>\n<\/ul>\n<p>Thanks, <\/p>\n<p>Lukasz Anforowicz [MSFT] <\/p>\n<p>Windows PowerShell Developer <\/p>\n<p>Microsoft Corporation<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Instead of piping unstructured text, Windows PowerShell pipes objects between commands in a pipeline.&#160; As a consequence PowerShell remoting also deals with objects when passing data to and from remote sessions.&#160; This post explains how remote objects are serialized and which types of objects can be sent with full fidelity.&#160; You might want to refer [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[8],"class_list":["post-3201","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-remoting"],"acf":[],"blog_post_summary":"<p>Instead of piping unstructured text, Windows PowerShell pipes objects between commands in a pipeline.&#160; As a consequence PowerShell remoting also deals with objects when passing data to and from remote sessions.&#160; This post explains how remote objects are serialized and which types of objects can be sent with full fidelity.&#160; You might want to refer [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/3201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=3201"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/3201\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=3201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=3201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=3201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}