{"id":3011,"date":"2010-05-01T10:18:00","date_gmt":"2010-05-01T10:18:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2010\/05\/01\/a-powershell-wander-toolbox-mindset-expandproperty-dmzs-and-remote-profiles\/"},"modified":"2019-02-18T13:05:56","modified_gmt":"2019-02-18T20:05:56","slug":"a-powershell-wander-toolbox-mindset-expandproperty-dmzs-and-remote-profiles","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/a-powershell-wander-toolbox-mindset-expandproperty-dmzs-and-remote-profiles\/","title":{"rendered":"A PowerShell Wander:  ToolBox Mindset, \u2013ExpandProperty, DMZs and Remote Profiles"},"content":{"rendered":"<p><P>I was reading <A href=\"http:\/\/searchsystemschannel.techtarget.com\/generic\/0,295582,sid99_gci1508144,00.html\" target=\"_blank\">PowerShell remoting in Windows Server 2008 R2<\/A>.&nbsp; The great thing about this article is that it documents how to use Group Policy to enable PSRemoting on lots of machines automatically.&nbsp; In the article there was the following heads up: <\/P>\n<P><FONT color=\"#0000ff\"><EM><B>Warning:<\/B> <BR>Commands that are executed against a remote machine do not have access to information defined within your local profile. As such, commands that use a function or alias defined in your local profile will fail unless they are defined on the remote machine as well.<\/EM><\/FONT><\/P>\n<P><EM><\/EM><\/P>\n<P>The great thing about PowerShell is that it is a <STRONG>toolbox<\/STRONG>.&nbsp; <\/P>\n<P>The great thing about toolboxes is that they have general purpose utilities that creative people can use their inspiration to do things that the tool designers didn\u2019t think of when they developed the tool.&nbsp; One of my favorite examples of this came from a problem with SELECT.&nbsp; SELECT is a utility which selects a set of properties from the incoming object.&nbsp; It creates a new object and adds those selected properties as NoteProperties on that new object.&nbsp; e.g.<\/P>\n<P><FONT size=\"3\"><FONT face=\"Courier New\"><FONT color=\"#000080\">PS&gt; <STRONG>Get-Process *ss <\/STRONG><\/FONT><\/FONT><\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">Handles&nbsp; NPM(K)&nbsp;&nbsp;&nbsp; PM(K)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS(K) VM(M)&nbsp;&nbsp; CPU(s)&nbsp;&nbsp;&nbsp;&nbsp; Id ProcessName <BR>&#8212;&#8212;-&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp; &#8212;&#8211;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211; &#8212;&#8211;&nbsp;&nbsp; &#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp; &#8212; &#8212;&#8212;&#8212;&#8211; <BR>&nbsp;&nbsp;&nbsp; 917&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14&nbsp;&nbsp;&nbsp;&nbsp; 3420&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2364&nbsp;&nbsp;&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp; 9.97&nbsp;&nbsp;&nbsp; 424 csrss <BR>&nbsp;&nbsp;&nbsp; 771&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 27&nbsp;&nbsp;&nbsp;&nbsp; 3484&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13428&nbsp;&nbsp; 189&nbsp;&nbsp; 108.02&nbsp;&nbsp;&nbsp; 512 csrss <BR>&nbsp;&nbsp; 1989&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 45&nbsp;&nbsp;&nbsp; 18272&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 17820&nbsp;&nbsp;&nbsp; 87&nbsp;&nbsp;&nbsp; 95.83&nbsp;&nbsp;&nbsp; 556 lsass <BR>&nbsp;&nbsp;&nbsp;&nbsp; 30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 476&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 124&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp; 0.06&nbsp;&nbsp;&nbsp; 320 smss <\/FONT><\/P>\n<P><BR><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <STRONG>Get-Process *ss |Select ID,Handles,ProcessName<\/STRONG> <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Handles ProcessName <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;- &#8212;&#8212;&#8212;&#8211; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 424&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 930 csrss <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 512&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 770 csrss <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 556&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1984 lsass <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 320&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 30 smss <\/FONT><\/P>\n<P><BR><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <STRONG>Get-Process *ss |Select ID,Handles,ProcessName |Get-Member<\/STRONG> <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">&nbsp;&nbsp; TypeName: Selected.System.Diagnostics.Process <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemberType&nbsp;&nbsp; Definition <BR>&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8212;-&nbsp;&nbsp; &#8212;&#8212;&#8212;- <BR>Equals&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool Equals(System.Object obj) <BR>GetHashCode Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int GetHashCode() <BR>GetType&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type GetType() <BR>ToString&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ToString() <BR>Handles&nbsp;&nbsp;&nbsp;&nbsp; NoteProperty System.Int32 Handles=925 <BR>Id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NoteProperty System.Int32 Id=424 <BR>ProcessName NoteProperty System.String ProcessName=csrss <BR><\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <STRONG>Get-Process *ss |Select ProcessName<\/STRONG> <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">ProcessName <BR>&#8212;&#8212;&#8212;&#8211; <BR>csrss <BR>csrss <BR>lsass <BR>smss<\/FONT><\/P>\n<P><EM><\/EM><\/P>\n<P><EM>Sidenote: notice that the TYPE of the result is <STRONG>Selected.<\/STRONG>System.Diagnostics.Process.&nbsp; We did that in V2 to be consistent with our principle of always trying to help you keep track of where information came from.&nbsp; The idea is that if you are debugging a script and have an examine an object and see this typename, you have more information about where it came from to help debug your script.<\/EM><\/P>\n<P>Anyway, that is great but notice what happens when you select a single property you get an object with a single property.&nbsp; Often you just want the values of the property not an object with a single property.&nbsp; The solution to that has been:<\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <\/FONT><FONT size=\"3\"><FONT face=\"Courier New\"><FONT color=\"#000080\"><STRONG>Get-Process *ss |foreach {$_.ProcessName} <BR><\/STRONG>csrss <BR>csrss <BR>lsass <BR>smss<\/FONT><\/FONT><\/FONT><\/P>\n<P>That works but I don\u2019t like it very much.&nbsp; We had lots of discussions about what to do about this.&nbsp; Some people wrote a function which did this operation and thought we should include it in the next version.&nbsp; Others felt like we ought to put a switch on Select which say something like \u2013VALUEONLY.&nbsp; It was Lee Holmes that pointed out that we already support this.&nbsp; I looked at him like he had a rat\u2019s tail hanging out of his mouth when he said that.&nbsp; He said that Select \u2013ExpandProperty did the trick.&nbsp; This switch was designed to work with objects that have properties which are collections.&nbsp; For instance:&nbsp; <\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt;<STRONG> Get-Service WinMgmt |Select DependentServices<\/STRONG> <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">DependentServices <BR>&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; <BR>{wscsvc, SharedAccess, iphlpsvc} <BR><\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <STRONG>Get-Service WinMgmt |Select -ExpandProperty DependentServices<\/STRONG> <\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">Status&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DisplayName <BR>&#8212;&#8212;&nbsp;&nbsp; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8212;&#8211; <BR>Running&nbsp; wscsvc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Security Center <BR>Stopped&nbsp; SharedAccess&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Internet Connection Sharing (ICS) <BR>Running&nbsp; iphlpsvc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IP Helper<\/FONT><\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\"><\/FONT><\/P>\n<P>Pretty cool right?&nbsp; This tool was designed to work on properties which are collections.&nbsp; Lee Holmes wondered, \u201cWhat would it do on a property which wasn\u2019t a collection?\u201d.<\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\">PS&gt; <STRONG>Get-Process *ss |Select -ExpandProperty ProcessName<\/STRONG> <BR>csrss <BR>csrss <BR>lsass <BR>smss<\/FONT><\/P>\n<P>OH YEAH BABY!&nbsp; You asked for it you got it!&nbsp; Using the toolkit mindset, Lee was able to figure out that we already supported this function.&nbsp; (You might point out that this is longer than the foreach but it turns out to be a ton easier because of tab completion.)<\/P>\n<P>So \u2013 what does this have to do with the remoting warning about not having access to any of the functions you defined in your profile file?&nbsp; Well, it turns out that the command Invoke-Command has a parameter \u2013FILEPATH which allows you to specify a file that you want to run on the remote machine.&nbsp; We added this feature to help people machine machines in <A href=\"http:\/\/en.wikipedia.org\/wiki\/Demilitarized_zone_(computing)\" target=\"_blank\">DMZs<\/A> where it can be difficult to ensure that the script you want to run will be on that machine and it can be difficult for that machine to have access to a shared folder of scripts.&nbsp; We send the file across and execute it so there is deployment free script execution.&nbsp; (This is a super important feature that people haven\u2019t quite tuned into yet.&nbsp; I\u2019m going to write a blog in the future about how to use this capability to use PowerShell as a bootstrap management agent to do all of your management functions.)&nbsp; So the example of this is something like<\/P>\n<P><FONT size=\"3\"><FONT face=\"Courier New\"><FONT color=\"#000080\">PS&gt; <STRONG>$DmzMachines = New-PSSession -ComputerName (cat DmzMachines.txt)<\/STRONG> <BR>PS&gt; <STRONG>Invoke-Command $DmzMachines -FilePath c:\\scripts\\Get-Inventory.ps1<\/STRONG> <BR><\/FONT>\u2026.<\/FONT><\/FONT><\/P>\n<P>PowerShell transfers and executes the Get-Inventory.ps1 script to all the machines.&nbsp; From there, you can connect the dots to putting the functions you want everywhere into a file called RemoteProfile and doing the following:<\/P>\n<P><FONT color=\"#000080\" size=\"3\" face=\"Courier New\"><STRONG>PS&gt; Invoke-Command $DmzMachines -FilePath c:\\scripts\\RemoteProfile.ps1<\/STRONG><\/FONT><\/P>\n<P><BR>Be aware that this mechanism has limitations.&nbsp; In a local profile, you can invoke other files on your system.&nbsp; Using this technique, those files aren\u2019t on the other system so that won\u2019t work \u2013 the files have to be self contained.&nbsp; That is why I called it RemoteProfile.ps1 .&nbsp; I keep it separate from my normal profile.<\/P>\n<P>Enjoy! <\/P>\n<P>Jeffrey Snover [MSFT] <BR>Distinguished Engineer <BR>Visit the Windows PowerShell Team blog at:&nbsp;&nbsp;&nbsp; <A href=\"http:\/\/blogs.msdn.com\/PowerShell\">http:\/\/blogs.msdn.com\/PowerShell<\/A> <BR>Visit the Windows PowerShell ScriptCenter at:&nbsp; <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\">http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx<\/A><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was reading PowerShell remoting in Windows Server 2008 R2.&nbsp; The great thing about this article is that it documents how to use Group Policy to enable PSRemoting on lots of machines automatically.&nbsp; In the article there was the following heads up: Warning: Commands that are executed against a remote machine do not have access [&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":[],"class_list":["post-3011","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>I was reading PowerShell remoting in Windows Server 2008 R2.&nbsp; The great thing about this article is that it documents how to use Group Policy to enable PSRemoting on lots of machines automatically.&nbsp; In the article there was the following heads up: Warning: Commands that are executed against a remote machine do not have access [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/3011","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=3011"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/3011\/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=3011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=3011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=3011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}