{"id":4837,"date":"2012-10-12T00:01:00","date_gmt":"2012-10-12T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/10\/12\/understanding-simplified-foreach-syntax-in-powershell-3-0\/"},"modified":"2012-10-12T00:01:00","modified_gmt":"2012-10-12T00:01:00","slug":"understanding-simplified-foreach-syntax-in-powershell-3-0","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/understanding-simplified-foreach-syntax-in-powershell-3-0\/","title":{"rendered":"Understanding Simplified Foreach Syntax in PowerShell 3.0"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, talks about the simplified Foreach syntax in Windows PowerShell 3.0 and provides guidance on when to use which syntax.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. I finally had a bit of time to get some stuff done that I had been needing to do, such as submitting my session proposals for the <a href=\"http:\/\/powershell.org\/summit\/\" target=\"_blank\">Windows PowerShell Summit<\/a>, and registering for Windows PowerShell Saturday in Atlanta. It is amazing how much time simple things seem to take. Both of these events will be really cool. Of course, the one I am concentrating on right now is <a href=\"http:\/\/powershellsaturday.com\/003\" target=\"_blank\">Windows PowerShell Saturday #003<\/a> in Atlanta, Georgia on October 27, 2012.<\/p>\n<h2>PowerShell 3.0 simplified Foreach-Object syntax<\/h2>\n<p>One of the cool things about Windows PowerShell 3.0 is the simplified syntax. Whereas the simple syntax for the <b>Where-Object<\/b> is straightforward, the simple syntax for the <b>Foreach-Object<\/b> cmdlet does not work the way one might expect. For example, using the simple <b>Where-Object<\/b> works as illustrated in the following example.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process | where name -match word<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">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<\/p>\n<p style=\"padding-left: 30px\">&#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;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; 687&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp; 72940&nbsp;&nbsp;&nbsp;&nbsp; 135240&nbsp;&nbsp; 717&nbsp;&nbsp;&nbsp; 68.11&nbsp;&nbsp; 1208 WINWORD<\/p>\n<p>For reference, the Windows PowerShell 1.0 and Windows PowerShell 2.0 syntax of the previous command are shown here.<\/p>\n<p style=\"padding-left: 30px\">Get-Process | where {$_.name -match &#8216;word&#8217;}<\/p>\n<p>Now, there is also a simplified syntax for the <b>Foreach-Object<\/b> cmdlet. It is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process -Name w* | foreach name<\/p>\n<p style=\"padding-left: 30px\">wininit<\/p>\n<p style=\"padding-left: 30px\">winlogon<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">wmpnetwk<\/p>\n<p style=\"padding-left: 30px\">WUDFHost<\/p>\n<p>The old Windows PowerShell 1.0 and Windows PowerShell 2.0 way of doing this is shown here.<\/p>\n<p style=\"padding-left: 30px\">Get-Process -Name w* | foreach {$_.name}<\/p>\n<p>As you can see, the old method requires a script block and the automatic variable <b>$_<\/b>.<\/p>\n<p>Incidentally, it seems that the <b>$_<\/b> automatic variable is hard for some people to understand&mdash;or at least it seems to bother some people. (That is what I hear. Personally, in all the years I have been teaching Windows PowerShell to people, I have never run across someone who had a major problem with the <b>$_<\/b> automatic variable, but that is just my experience. I can certainly conceive of someone not liking the <b>$_<\/b> automatic variable.)<\/p>\n<h2>Problems with the simple Foreach-Object syntax<\/h2>\n<p>Wow, it is great! We have a simple <b>Foreach-Object<\/b> syntax! The problem is that it is really simple (meaning that it does not do what I would like it to do&mdash;at least not exactly). Most of the time, when I am using the <b>Foreach-Object<\/b> cmdlet, I am doing something. If I only wanted the names from a collection, I would probably use the <b>Select-Object<\/b> cmdlet as shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process -Name w* | select name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Name<\/p>\n<p style=\"padding-left: 30px\">&#8212;-<\/p>\n<p style=\"padding-left: 30px\">wininit<\/p>\n<p style=\"padding-left: 30px\">winlogon<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">wmpnetwk<\/p>\n<p style=\"padding-left: 30px\">WUDFHost<\/p>\n<p>But I might be interested in doing something to the names, like using the <b>ToUpper<\/b><i> <\/i>method from the System.String .NET Framework class. In the old days, this is the syntax I would use:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process -Name w* | foreach {$_.name.toupper()}<\/p>\n<p style=\"padding-left: 30px\">WININIT<\/p>\n<p style=\"padding-left: 30px\">WINLOGON<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">WMPNETWK<\/p>\n<p style=\"padding-left: 30px\">WUDFHOST<\/p>\n<p>Therefore, I should be able to do the same thing in the new simplified syntax as shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process -Name w* | foreach name.toupper()<\/p>\n<p style=\"padding-left: 30px\">At line:1 char:45<\/p>\n<p style=\"padding-left: 30px\">+ Get-Process -Name w* | foreach name.toupper()<\/p>\n<p style=\"padding-left: 30px\">+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~<\/p>\n<p style=\"padding-left: 30px\">An expression was expected after &#8216;(&#8216;.<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : ParserError: (:) [], ParentContainsErrorRecordExcepti<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; on<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : ExpectedExpression<\/p>\n<p>Nope. It does not work. Bummer! So, I can go back to my &ldquo;old&rdquo; syntax, or I can use the new <b>$PSItem<\/b> variable. Because, some people do not like the <b>$_<\/b> automatic variable, a new <b>$PSItem<\/b> variable is created, to do the same thing. Personally, I never use it because it is too much typing. It is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-Process -Name w* | foreach {$psitem.name.toupper()}<\/p>\n<p style=\"padding-left: 30px\">WININIT<\/p>\n<p style=\"padding-left: 30px\">WINLOGON<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">WMPNETWK<\/p>\n<p style=\"padding-left: 30px\">WUDFHOST<\/p>\n<p>There is a way to use the simple syntax, and to avoid using the <b>$_<\/b> or the <b>$PSItem<\/b> automatic variables. It involves using my group and dot technique. This is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; (Get-Process -Name w* | foreach name).toupper()<\/p>\n<p style=\"padding-left: 30px\">WININIT<\/p>\n<p style=\"padding-left: 30px\">WINLOGON<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">WMPNETWK<\/p>\n<p style=\"padding-left: 30px\">WUDFHOST<\/p>\n<p>This syntax is just a bit shorter, but is not necessarily any cleaner than the other two ways of doing this. What happens is that the first command returns the names, and because of the way that Windows PowerShell&nbsp;3.0 does the automatic <b>Foreach<\/b> to permit working with a collection, it calls the <b>ToUpper<\/b><i> <\/i>method. This could also be written as shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; (Get-Process -Name w*).name.toupper()<\/p>\n<p style=\"padding-left: 30px\">WININIT<\/p>\n<p style=\"padding-left: 30px\">WINLOGON<\/p>\n<p style=\"padding-left: 30px\">WINWORD<\/p>\n<p style=\"padding-left: 30px\">WMPNETWK<\/p>\n<p style=\"padding-left: 30px\">WUDFHOST<\/p>\n<p>In the example above, the <b>Foreach<\/b><i> <\/i>happens automatically; and therefore, it does not need to be explicitly called. In fact, this is the way that I would more than likely write this code. To me it is readable, it is certainly cleaner, and when you understand that Windows PowerShell&nbsp;3.0 provides direct access to properties from a collection (the automatic <b>Foreach<\/b>), it makes sense.<\/p>\n<p>These commands and their associated output are shown in the image that follows.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3058.hsg-10-12-12-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3058.hsg-10-12-12-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Join me tomorrow when I will talk about more cool Windows PowerShell stuff.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about the simplified Foreach syntax in Windows PowerShell 3.0 and provides guidance on when to use which syntax. Microsoft Scripting Guy, Ed Wilson, is here. I finally had a bit of time to get some stuff done that I had been needing to do, such as submitting my [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,362,3,45],"class_list":["post-4837","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-powershell-3","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about the simplified Foreach syntax in Windows PowerShell 3.0 and provides guidance on when to use which syntax. Microsoft Scripting Guy, Ed Wilson, is here. I finally had a bit of time to get some stuff done that I had been needing to do, such as submitting my [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4837","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=4837"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4837\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=4837"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=4837"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=4837"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}