<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://vexx32.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vexx32.github.io/" rel="alternate" type="text/html" /><updated>2022-07-30T06:01:39-04:00</updated><id>https://vexx32.github.io/feed.xml</id><title type="html">Clear-Script</title><subtitle>Rain Sallow | PowerShell Enthusiast | @vexx32 /u/ta11ow</subtitle><entry><title type="html">Verify Your Module's Help with Pester v5</title><link href="https://vexx32.github.io/2020/07/08/Verify-Module-Help-Pester/" rel="alternate" type="text/html" title="Verify Your Module's Help with Pester v5" /><published>2020-07-08T00:00:00-04:00</published><updated>2020-07-08T00:00:00-04:00</updated><id>https://vexx32.github.io/2020/07/08/Verify-Module-Help-Pester</id><content type="html" xml:base="https://vexx32.github.io/2020/07/08/Verify-Module-Help-Pester/">&lt;p&gt;If anyone's not yet aware, &lt;a href=&quot;https://github.com/pester/pester&quot;&gt;Pester&lt;/a&gt; recently released a new major version: 5.0.
This comes with a slew of breaking changes and some fancy new functionality, and some pretty solid performance improvements to boot.
A user in the PowerShell &lt;a href=&quot;https://aka.ms/psdiscord&quot;&gt;Discord&lt;/a&gt; server recently came across some tests written for Pester v4 that they wanted to refactor for use in Pester v5.
I decided to take a thorough look, and it proved to be quite a bit more complicated than I'd initially expected, mainly due to the way the tests were written.&lt;/p&gt;

&lt;h2 id=&quot;what-worked-in-pester-v4&quot;&gt;What Worked in Pester v4&lt;/h2&gt;

&lt;p&gt;The original code we'll be hacking away at comes fom &lt;a href=&quot;https://lazywinadmin.com/2016/05/using-pester-to-test-your-comment-based.html&quot;&gt;François-Xavier Cat (aka lazywinadmin)&lt;/a&gt; and looks like this:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Describe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;AdsiPS Module&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Tags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Module&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Import Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#import-module C:\Test\AdsiPS\AdsiPS.psd1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#$FunctionsList = (get-command -Module ADSIPS).Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FunctionsList&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get-command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ADSIPS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-FilterScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CommandType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-eq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Function'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;FOREACH&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FunctionsList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Retrieve the Help of the function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Full&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alertSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-split&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\n'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

        &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Parse the function using AST&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$AST&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.Language.Parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Content&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;function:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - Help&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Synopsis&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Synopsis&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Notes - Author&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Francois-Xavier Cat&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Notes - Site&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lazywinadmin.com&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Notes - Twitter&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@lazywinadmin&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Notes - Github&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;github.com/lazywinadmin&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Get the parameters declared in the Comment Based Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RiskMitigationParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Whatif'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Confirm'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HelpParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parameter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-NotIn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RiskMitigationParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Get the parameters declared in the AST PARAM() Block&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ASTParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ParamBlock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;variablepath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;userpath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FunctionsList&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get-command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-FilterScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CommandType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-eq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Function'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;



            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Parameter - Compare Count Help/AST&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HelpParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-eq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ASTParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Parameter Description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;If&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ASTParameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# IF ASTParameters are found&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HelpParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForEach-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Parameter &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - Should contains description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Examples&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Example - Count should be greater than 0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;examples&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BeGreaterthan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Examples - Remarks (small description that comes with the example)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Example&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;examples&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Example - Remarks on &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remarks&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There's a lot going on here, but there are a few things I'd specifically like to point out that will cause us some particular difficulty.
First on the list is the very frequent shifting of scope and shared information between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Describe&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; blocks and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; blocks which make up the actual tests.
This &lt;em&gt;can&lt;/em&gt; be an issue in Pester v4 as well, but you'll generally only notice that if the code being used generates errors.&lt;/p&gt;

&lt;p&gt;For a concrete example, look at how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Help&lt;/code&gt; is used in the above code – it's created in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Describe&lt;/code&gt; block and used again in both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; blocks.
It's unlikely, but if that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Get-Help&lt;/code&gt; call generates an error, the entire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Describe&lt;/code&gt; test would fail, halting all subsequent tests.
With the way these tests are set up, whichever functions have yet to be tested would simple &lt;em&gt;not get tested&lt;/em&gt;.
That isn't a huge issue in this specific case, but it's definitely something to keep in mind.&lt;/p&gt;

&lt;p&gt;When writing Pester tests, you generally want to follow a couple very broad rules (among others):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;As much code as possible should be &lt;em&gt;inside&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeAll&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeEach&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterAll&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterEach&lt;/code&gt; block.
This ensures that when errors occur, they register as a test failure without necessarily breaking the rest of the tests completely.&lt;/li&gt;
  &lt;li&gt;Code used to generate test cases should utilize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt; wherever possible.
This lets you offload all the looping logic to Pester itself, and tends to make tests run a little more smoothly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While you can (yes, even in v5) utilise a standard loop to generate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; test cases, you will very quickly run into issues doing that in v5.
Part of that is due to the split behaviour of Discovery and Run in Pester v5, so let's cover that real quick.&lt;/p&gt;

&lt;h3 id=&quot;testing-phases-in-pester-v5&quot;&gt;Testing Phases in Pester v5&lt;/h3&gt;

&lt;p&gt;In Pester v5, tests happen in two &lt;em&gt;very&lt;/em&gt; distinct phases.
First, there's a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt; phase:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;During &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt;, code in the main body of the test file, as well as code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Describe&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; blocks, is executed.
This allows you to generate test cases, iteratively create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; blocks directly, and gives Pester a chance to evaluate its test plan ahead of time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Second, there's the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run&lt;/code&gt; phase:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;During the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run&lt;/code&gt; phase, only code &lt;strong&gt;inside&lt;/strong&gt; an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; block will be run.
This &lt;em&gt;does&lt;/em&gt; include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;It&lt;/code&gt; blocks and test cases that were generated by code run during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt;, but variables created during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt; are typically not available during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run&lt;/code&gt;.
For that reason, I'd recommend moving all your test case generation to proper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt; usage first — it's the only supported way to make data from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt; available during &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;limitations-of--testcases&quot;&gt;Limitations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;At the time of writing, it's not yet possible replicate fully what the above code is doing by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt;.
If you examine the code, you can see it's actually generating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; blocks.
This is still doable in Pester v5, but passing data from there into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run&lt;/code&gt; phase can get a bit tricky.
However, we'll do our best!&lt;/p&gt;

&lt;h2 id=&quot;prepare-for-pester-v5&quot;&gt;Prepare for Pester v5&lt;/h2&gt;

&lt;p&gt;The initial code is working from an assumption that all public functions for our module are contained in individual function files under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Public&lt;/code&gt; folder in the module.
We can break away from this assumption by simply querying the imported module for its exported commands, which will include compiled cmdlets as well.&lt;/p&gt;

&lt;p&gt;The other side of things is that in order to pass data from the Discovery phase to the test runs, we'll need to utilize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt; quite heavily.
This could be done purely with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-TestCases&lt;/code&gt;, by including the command names and all other information as part of the test case.
Doing things that way works quite well, but you will lose the ability to have each command in its own Context block.
If that doesn't bother you, feel free to go that route!
Personally, I appreciate the extra clarity of having a complete block for each command.&lt;/p&gt;

&lt;p&gt;Below is a rewritten version of the above script, which should be fully compatible with Pester v5.
There are some design changes here and there, but the vast majority of the above script has been retained.
It includes a couple of variables for a module name, which should let you substitute any module name in to test against that module.&lt;/p&gt;

&lt;p&gt;You'll notice I have a habit of placing code explicitly in regions marked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Discovery&lt;/code&gt;.
This is purely something I do for clarity; Pester doesn't require it, and won't recognise it differently to anything else.
I'm hopeful that at some point in future Pester will provide an explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeDiscovery&lt;/code&gt; block for this purpose, but I'm unsure as to when that's likely to be implemented.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#region Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'MyModule'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#endregion Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BeforeAll&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'MyModule'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Describe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; Sanity Tests - Help Content&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Tags&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Module'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#region Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# The module will need to be imported during Discovery since we're using it to generate test cases / Context blocks&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ShouldProcessParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'WhatIf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Confirm'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Generate command list for generating Context / TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ModuleName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CommandList&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Module&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.ExportedFunctions.Keys&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Module&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.ExportedCmdlets.Keys&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#endregion Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CommandList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - Help Content&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#region Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Full&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Parameter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-ErrorAction&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ignore&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-notin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ShouldProcessParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForEach-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Ast&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Ast will be $null if the command is a compiled cmdlet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ast&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;function:/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ErrorAction&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ignore&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ast&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Parameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Examples&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Examples&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Example&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForEach-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Example&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#endregion Discovery&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;has help content for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-Not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;contains a synopsis for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Synopsis&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-Not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;contains a description for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-Not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lists the function author in the Notes section for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AlertSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-split&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\n'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeLike&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Author: *&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# This will be skipped for compiled commands ($Ast.Ast will be $null)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;has a help entry for all parameters of &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Ast&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Ast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Ast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Ast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Body&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ParamBlock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Because&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'the number of parameters in the help should match the number in the function script'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;has a description for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; parameter -&amp;lt;Name&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Description&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-Not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Because&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;parameter &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Name&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; should have a description&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;has at least one usage example for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Examples&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeGreaterOrEqual&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lists a description for &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Command&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; example: &amp;lt;Title&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-TestCases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Examples&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Remarks&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-Not&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-BeNullOrEmpty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Because&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;example &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Example&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; should have a description!&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="powershell" /><category term="testing" /><category term="modules" /><category term="help" /><category term="Pester" /><category term="PowerShell" /><category term="modules" /><category term="BuildHelpers" /><category term="comment-based help" /><category term="cbh" /><summary type="html">If anyone's not yet aware, Pester recently released a new major version: 5.0. This comes with a slew of breaking changes and some fancy new functionality, and some pretty solid performance improvements to boot. A user in the PowerShell Discord server recently came across some tests written for Pester v4 that they wanted to refactor for use in Pester v5. I decided to take a thorough look, and it proved to be quite a bit more complicated than I'd initially expected, mainly due to the way the tests were written.</summary></entry><entry><title type="html">ScriptBlocks and GetNewClosure()</title><link href="https://vexx32.github.io/2020/05/30/Scriptblock-GetNewClosure/" rel="alternate" type="text/html" title="ScriptBlocks and GetNewClosure()" /><published>2020-05-30T00:00:00-04:00</published><updated>2020-05-30T00:00:00-04:00</updated><id>https://vexx32.github.io/2020/05/30/Scriptblock-GetNewClosure</id><content type="html" xml:base="https://vexx32.github.io/2020/05/30/Scriptblock-GetNewClosure/">&lt;p&gt;Before we even begin, let's just take a moment to remember something very important.
In PowerShell, &lt;em&gt;everything&lt;/em&gt; is an object.
Although you'll normally see scriptblocks used to declare functions, or perhaps as a command parameter, and so on… they are themselves just an object.&lt;/p&gt;

&lt;p&gt;That means you can do funny things like just arbitrarily assigning them to variables so you can use them later:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\Users'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you run that code, you'll some some interesting results.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$path&lt;/code&gt; variable is never defined in the scriptblock, so it actually retrieves the variable from the parent scope when it's invoked.
Handy!
Well, sometimes, anyway.
This is how scriptblocks tend to work for the most part, but it's not always what you want.&lt;/p&gt;

&lt;h2 id=&quot;capturing-state&quot;&gt;Capturing State&lt;/h2&gt;

&lt;p&gt;Let's take a look at how we might want to process a JSON blob into a more usable PowerShell object.
Special thanks to user @MTG on the &lt;a href=&quot;https://aka.ms/psslack&quot;&gt;PowerShell Slack&lt;/a&gt; workspace for the fantastic test case here.
Our JSON blob looks a bit like this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;server1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;28361&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;active&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;itemId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;71418&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;itemValue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dk09230&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;servicetag&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldDescription&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;itemId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;71318&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;itemValue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fieldDescription&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, we're looking to get out a flat object, which contains the following properties:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;All the &quot;items&quot; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;items&lt;/code&gt; as their own individual properties, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fieldName&lt;/code&gt; is the property name, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;itemValue&lt;/code&gt; is the property value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's probably a decent number of ways to handle this, but it's difficult to handle it well if you have a handful of these JSON objects, and everything has a different set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;items&lt;/code&gt; that you need as individual properties.
Without hard-coding handling for each type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item&lt;/code&gt; you might happen across in the real world, how do you (reasonably neatly) handle the variant properties you might be getting back here?&lt;/p&gt;

&lt;p&gt;There are probably quite a few rabbit holes we could go down to help sort this out, and I'm sure somewhere in there we'd have some folks using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invoke-Expression&lt;/code&gt; sooner or later.
I'd rather not, so let's take a bit of a look at what scriptblocks can do for us.&lt;/p&gt;

&lt;p&gt;Returning to our earlier PowerShell example, let's see how we can modify the scriptblock behaviour a bit to make things work for us.&lt;/p&gt;

&lt;h2 id=&quot;getnewclosure&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetNewClosure()&lt;/code&gt;&lt;/h2&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetNewClosure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\Users'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$myScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you try to run this code, you'll something a bit interesting.
Unlike the first example, where changing the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$path&lt;/code&gt; before invoking the scriptblock the second time changes the output, this scriptblock does the exact same things both times.
Ignoring the changed value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$path&lt;/code&gt; &lt;em&gt;completely&lt;/em&gt; and just using the original value that it had when the scriptblock was created.
More properly, the value as it was when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetNewClosure()&lt;/code&gt; method was used to create a copy of the scriptblock (we're discarding the original un-enclosed copy of the scriptblock in this instance).&lt;/p&gt;

&lt;p&gt;That doesn't look super useful here, but it will help us, since it allows us to use the same code to create a collection of scriptblocks that behave slightly differently.
Here's how I ended up framing the code:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConvertFrom-Json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Properties&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Name'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Id'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Active'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$field&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$object&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$field&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fieldName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Expression&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$field&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;itemValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;GetNewClosure&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Select-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Properties&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To explain a little… If you weren't aware, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Select-Object&lt;/code&gt; takes strings, scriptblocks, and/or hashtables as input for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Property&lt;/code&gt;, and I'm building the collection of properties ahead of time here.
That lets me use slightly neater syntax, but if you really wanted to you could pass that array literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@( ... )&lt;/code&gt; directly to the command as well.
First, we simply add the direct properties we want from the original object as strings.
Then, using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreach&lt;/code&gt; loop I can build the hashtables necessary to add a calculated property to the final object for every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item&lt;/code&gt; that was attached to the original object.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetNewClosure()&lt;/code&gt; here lets us use the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$field&lt;/code&gt; in the scriptblock and have it refer to the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item&lt;/code&gt; from the original object by capturing the state of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$field&lt;/code&gt; when it was created and always using that.
This is important, because without it, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Select-Object&lt;/code&gt; will just invoke that scriptblock as-is, and it will always be referring to the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$field&lt;/code&gt; value for each of the properties, which is not what we want.&lt;/p&gt;

&lt;p&gt;There might be other ways to handle this, but probably not many ways that are quite this elegant.
The only one that really comes to mind is perhaps looping over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$object.items&lt;/code&gt; and &lt;em&gt;repeatedly&lt;/em&gt; calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Select-Object&lt;/code&gt;… which is much less readable, and probably a lot slower overall.&lt;/p&gt;

&lt;p&gt;It's not often I see a good use case for it, but I'm always glad I'm aware of it when I need it!&lt;/p&gt;</content><author><name></name></author><category term="powershell" /><category term="scripting" /><category term="tips" /><category term="scriptblock" /><summary type="html">Before we even begin, let's just take a moment to remember something very important. In PowerShell, everything is an object. Although you'll normally see scriptblocks used to declare functions, or perhaps as a command parameter, and so on… they are themselves just an object.</summary></entry><entry><title type="html">Handling PowerShell's Versatile Subexpressions</title><link href="https://vexx32.github.io/2020/02/24/Handling-PowerShell-Subexpressions/" rel="alternate" type="text/html" title="Handling PowerShell's Versatile Subexpressions" /><published>2020-02-24T00:00:00-05:00</published><updated>2020-02-24T00:00:00-05:00</updated><id>https://vexx32.github.io/2020/02/24/Handling-PowerShell-Subexpressions</id><content type="html" xml:base="https://vexx32.github.io/2020/02/24/Handling-PowerShell-Subexpressions/">&lt;p&gt;I've always been a fan of using subexpressions to tidy up my code.
They tend to help me collect and store output where I need it, without requiring that I add complex loops and delve into .NET collection types.
The pattern seems to be a bit of a rarity among a lot of other scripters I see, so I thought I'd write a post on subexpressions and all the ways you can use them!&lt;/p&gt;

&lt;p&gt;I'll also be covering use of scriptblocks as anonymous functions — invoking them immediately as you define them — since that's rather similar to how subexpressions work.&lt;/p&gt;

&lt;h2 id=&quot;subexpressions-and-anonymous-functions&quot;&gt;Subexpressions and Anonymous Functions&lt;/h2&gt;

&lt;p&gt;Subexpressions are kind of like an inline function that always gets invoked immediately.
You define a set of commands that all get invoked one after another, and then PowerShell processes all the output and either stores or outputs the results.
The only thing you &lt;strong&gt;can't&lt;/strong&gt; do with them is store the commands inside and execute them later.
A subexpression is always evaluated at the point in the script where it's declared.&lt;/p&gt;

&lt;p&gt;True anonymous functions in PowerShell are also available in the form of inline scriptblock invocations.
If you choose, you &lt;em&gt;can&lt;/em&gt; actually store the scriptblock itself — the function definition, essentially — and invoke it multiple times.&lt;/p&gt;

&lt;p&gt;Something to note that's shared between all subexpressions (as well as scriptblocks) is that the end of a line does &lt;strong&gt;not&lt;/strong&gt; terminate the subexpression.
Only the matching closing parenthesis closes off the subexpression.
This actually includes explicit line endings with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt; as well, and this is why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;( )&lt;/code&gt; is not a true subexpression:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# This line will throw a parse error; the expression ends before the closing parenthesis&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Conversely, this line is perfectly fine; the subexpression allows the use of line endings within it&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let's take a closer look at the types of subexpression PowerShell has available.&lt;/p&gt;

&lt;h3 id=&quot;types-of-subexpressions&quot;&gt;Types of Subexpressions&lt;/h3&gt;

&lt;p&gt;Without lumping in anonymous functions as a kind of subexpression (which they &lt;em&gt;sort of&lt;/em&gt; are, but we'll look at that in a minute), there are two types of subexpression in PowerShell:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Syntax&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Name&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Example&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$( )&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Subexpression&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$String = &quot;This script has $(Get-Random) functions.&quot;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@( )&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Array Subexpression&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Values = @(1, 2, 3, 4)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;regular-subexpressions&quot;&gt;Regular Subexpressions&lt;/h4&gt;

&lt;p&gt;I think most folks will typically see subexpressions used to insert data into a string, just like in the above example.
This is a great use for it, and it's a function exclusive to this type of subexpression.&lt;/p&gt;

&lt;p&gt;But it's far from &lt;em&gt;all&lt;/em&gt; you can do with it.
Notice I mentioned a moment ago that you can have line breaks in subexpressions.
That opens up a few interesting possibilities here, especially because each line is considered a totally separate statement:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$SomeValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Test-Connection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1.1.1.1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SomeValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-lt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What are you looking at me like that for?
Yes, it's perfectly legal (and quite useful on occasion!) syntax to drop an entire statement block into a subexpression.
Ifs, switches, loops, you name it.
Pretty much any language statement is a legal entry in a subexpression, and though I'd advise against it you &lt;em&gt;can&lt;/em&gt; do odd things like embedding an entire if statement into a string.
More to the point, though, what kind of result would you expect to find in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Values&lt;/code&gt; when all's said and done?&lt;/p&gt;

&lt;p&gt;It might not be immediately obvious if you're not accustomed to seeing this, but you'll get a single flat array stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Values&lt;/code&gt; when the subexpression completes.
Each statement within the subexpression executes in order and submits its output to the pipeline.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Test-Connection&lt;/code&gt; (at least in PowerShell 6.2+) this means that 4 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PingStatus&lt;/code&gt; objects are output and subsequently stored into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Values&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; statement is evaluated, and the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt; is output and subsequently stored.&lt;/li&gt;
  &lt;li&gt;The expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1..20&lt;/code&gt; is evaluated, and an array with values &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20&lt;/code&gt; are output.
Note that this output is still over a pipeline, so the array is ultimately split up again and sent to output one item at a time.
This will become important later.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, our end result, if we'd written it all out manually, would look a bit like this:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Final array size: 25&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# First four values -&amp;gt; Test-Connection Output (if using PS Core 6.2.x / 7)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Test-Connection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1.1.1.1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Fifth value -&amp;gt; result of the if statement&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SomeValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-lt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Remaining values -&amp;gt; contents of array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that it doesn't matter here whether we drop a scalar value or an array value into the subexpression.
As long as we leave a line-break between our expressions, each array is unwrapped as it goes over the pipeline, and then all the results are tossed into a single array at the end.
This is part of the essentials of pipeline behaviour, but I'm sure quite a few folks won't expect to see any pipeline behaviour arise from the above example.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;💡 &lt;strong&gt;Remember&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Every statement in PowerShell that doesn't itself store or redirect output elsewhere uses the standard output pipeline.
This includes statements within subexpressions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yes, before you ask… all of this &lt;em&gt;still&lt;/em&gt; applies when you have a subexpression inside a string.
The only additional thing to note in that case is that you're always going to end up converting to a string value at the end.
This can occasionally cause some unintended behaviour, since the behaviour when converting an array to a string depends on the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OFS&lt;/code&gt;.
Usually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OFS&lt;/code&gt; is unset, and a space is used to separate the items in the array.
if you set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OFS&lt;/code&gt; to, say, a comma, this behaviour changes.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The values are &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;The&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;are&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OFS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The values are &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;The&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;are&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just one little detail to keep in mind. 🙂&lt;/p&gt;

&lt;h4 id=&quot;array-subexpressions&quot;&gt;Array Subexpressions&lt;/h4&gt;

&lt;p&gt;Array subexpressions work &lt;strong&gt;almost&lt;/strong&gt; exactly the same was as regular subexpressions.
They have two key differences:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You cannot directly insert an array subexpression into a string.&lt;/li&gt;
  &lt;li&gt;The result of an array subexpression is always (as the name implies) an array.
(Specifically, it will always be an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[object[]]&lt;/code&gt; array.)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;📝 &lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Array subexpressions will only wrap the output in an array if the output is not already an array.
In other words, it guarantees the output will ultimately be an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[object[]]&lt;/code&gt; array.
If the result is a single item, it will be boxed into an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[object[]]&lt;/code&gt; array, and if it's an array of another type, it will box each item and hand back an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object[]&lt;/code&gt; array.
In most cases, PowerShell will already have boxed the output as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[object[]]&lt;/code&gt; due to its pipeline processing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In every other way, they work identically to standard subexpressions.
You'll most often see these used as an &quot;explicit&quot; variant of defining an array.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While this can be used for clarity, it is in effect somewhat redundant.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; comma operator is what's actually creating the array in this instance.
The subexpression operator simply ensures the result is in fact an array.&lt;/p&gt;

&lt;h3 id=&quot;inline-scriptblock-invocations&quot;&gt;Inline Scriptblock Invocations&lt;/h3&gt;

&lt;p&gt;Scriptblocks can be defined and used directly in a script, much like a subexpression.
Unlike subexpressions, however, scriptblocks are usually used to store code — they won't be invoked unless you use one of the invocation operators.
A scriptblock, as the name implies, is just a block of script.
Any valid PowerShell code is valid here, with only a scant few exceptions.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# `&amp;amp;` or `.` must be used to invoke the scriptblock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Results&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$folders&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Directory&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$folders&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This has a similar effect to using a subexpression.
However, using a scriptblock creates a new scope — any new variables or other scoped data will not be available outside the scriptblock.
In the above example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$folders&lt;/code&gt; variable becomes unavailable as soon as you step outside the scriptblock once again.&lt;/p&gt;

&lt;p&gt;The other option is to dot-source the scriptblock.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Results&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$folders&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Directory&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$folders&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this instance, both the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Results&lt;/code&gt; variable and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$folders&lt;/code&gt; variable would become available in the same scope after the scriptblock finishes executing.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ &lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Dot-sourcing a scriptblock is more expensive in terms of performance than simply invoking it.
Generally speaking, invoking the scriptblock should be the typical case, and dot-sourcing should be an exception to the rule.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;getnewclosure&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}.GetNewClosure()&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Something to note about scriptblocks is that you can store them for later invocation, like an impromptu function.
Those of you coming from a C# background are probably already familiar with lambda expressions — this is something similar.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# output: 24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# output: 36&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, although the scriptblock is indeed a stored &lt;em&gt;action&lt;/em&gt;, its effect still depends on the code around it.
In some cases, you won't want this context-sensitive behaviour as much.
For these cases, you can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.GetNewClosure()&lt;/code&gt; on the scriptblock to effectively tie it to the context where it was defined.&lt;/p&gt;

&lt;p&gt;If we apply that to the above example, you can see it in action:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetNewClosure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# output: 24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# output: 24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is, no matter where you call the scriptblock from, it behaves the same way.
It's hard to see how this is useful here, but it comes in &lt;em&gt;very&lt;/em&gt; handy if you ever need to handle events in PowerShell.&lt;/p&gt;

&lt;p&gt;Events in C# are pretty easy to work with.
In PowerShell, they can be problematic, since there's no guarantee an event will be invoked in the same context that it was registered in.
It can very easily end up being called from a completely separate thread.
This means that the scriptblock has to be effectively self-contained — if you need to reference anything that's defined or created outside the scriptblock itself, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetNewClosure()&lt;/code&gt; comes in very handy.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Get-Collection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CmdletBinding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.PSDataCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$sb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$null&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-eq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;COLLECTION IS NULL OH NO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Collection length is now &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetNewClosure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_DataAdding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$sb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$PSCmdlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$col&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Collection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Credit to &lt;a href=&quot;https://twitter.com/SeeminglyScienc&quot;&gt;Patrick Meinecke&lt;/a&gt; for the lovely example here.&lt;/p&gt;

&lt;p&gt;Essentially what's going on here is we're creating a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PSDataCollection&lt;/code&gt;, and then registering a scriptblock to its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataAdding&lt;/code&gt; event.
This event triggers whenever you add items to the collection.
Here, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetNewClosure()&lt;/code&gt; allows the scriptblock to reference its own parent collection directly, without fear that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$collection&lt;/code&gt; variable won't exist when the event fires.&lt;/p&gt;

&lt;p&gt;Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.Add()&lt;/code&gt; causes the event to fire as the new data is added, and the reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$collection&lt;/code&gt; is maintained.
You won't always need this capability, but it's a very handy tool to keep on hand for when you do need it!&lt;/p&gt;

&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting it All Together&lt;/h2&gt;

&lt;p&gt;I've often found that this kind of thing is best illustrated by example, so I'll try to make this part a bit more on the side of showing than telling.&lt;/p&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;h4 id=&quot;generating-a-list-of-arguments-for-a-native-command&quot;&gt;Generating a List of Arguments for a Native Command&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'docker'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$args&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'rm'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Force&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'-f'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Out-Null&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, we're invoking an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm&lt;/code&gt; command with Docker, and we want to wrap it in a PowerShell function.
We can expose a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Force&lt;/code&gt; parameter that it respects, and altering the arguments is as simple as adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; argument or not.
Rather than complicate things by trying to add it in later, or duplicating the code completely and having two paths (one with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; and one without), we can just add an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; statement directly in the subexpression.&lt;/p&gt;

&lt;p&gt;Personally, I prefer this kind of methodology over manually manipulating strings any day, especially since that usually leads to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invoke-Expression&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;creating-match-patterns&quot;&gt;Creating Match Patterns&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$DomainPattern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.com'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.co.uk'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.de'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ForEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Escape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-join&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'|'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ExoMailbox&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-ResultSize&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Unlimited&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UserPrincipalName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DomainPattern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we put together an array of domain names, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[regex]::Escape()&lt;/code&gt; on each of them so we can use them as literals in a regex expression, and then join on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; which is a logical OR separator in regex.
The end result is that we can filter by the regular expression and get any of the objects where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UserPrincipalName&lt;/code&gt; contains any of the designated domain names.
It's a great example of when you can use the multiline syntax for an array subexpression.
Using a multi-line statement is perfectly optional here; the above &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$DomainPattern&lt;/code&gt; declaration is identical to the following:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$DomainPattern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.com'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.co.uk'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'domain.de'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ForEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Escape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-join&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'|'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are a couple of reasons I tend to prefer the multiline syntax:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Shorter line lengths tend to be a bit easier for me to read; I prefer to scan primarily down a script rather than both down &lt;em&gt;and&lt;/em&gt; across.&lt;/li&gt;
  &lt;li&gt;Breaking the statement over a couple of lines actually makes collaborative coding easier.
In a line-by-line diff (the sort you'll see with Git and also with pull requests on Github and similar platforms), the multiline version is &lt;em&gt;much&lt;/em&gt; easier on the eyes when you're adding or removing items from the array.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;collating-output-from-multiple-sources&quot;&gt;Collating Output from Multiple Sources&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$FileList&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Dir1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Dir2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-Recurse&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FileList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rename-Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-NewName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.old&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we're able to collate the output from &lt;em&gt;multiple&lt;/em&gt; discrete commands and put them into a single array.
This example is a little contrived, since you can do a similar thing in &lt;em&gt;most&lt;/em&gt; cases just by supplying multiple items to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Path&lt;/code&gt;.
However, if you ever have a case where you need to search through each path a little differently (using different filters, for example), this can come in handy.&lt;/p&gt;

&lt;p&gt;I also quite like that you can effectively &lt;strong&gt;join&lt;/strong&gt; two separate pipelines together and continue them in a third pipeline!&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Dir1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-notmatch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\d'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Dir2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Recurse&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-gt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;4kb&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sort-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Select-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Export-Csv&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CsvFile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The syntax can at times be a bit awkward, so feel free to play with it a little until it looks somewhat acceptable to you.
I haven't needed this more than once or twice, but I rather like the idea that I can sort of funnel many things into a single pipeline if I need to.&lt;/p&gt;

&lt;h3 id=&quot;familiarity&quot;&gt;Familiarity&lt;/h3&gt;

&lt;p&gt;I think a lot of users will likely be confused at first if they see a subexpression pushed to its limits.
You can go quite a ways into the weeds with them if you really have a need to.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Items&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Assertions&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-eq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is divisible by 3&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-gt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is more than 16&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lucky day!&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Today's not very lucky for you...&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Your Lucky Numbers are...&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Random&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Random&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Min&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Max&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-join&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Assertions&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Random&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Push any errors back to the regular output stream here&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resolve-DnsName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;google.com&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Items&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-join&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;' | '&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Would you ever &lt;em&gt;need&lt;/em&gt; to?
Probably not.
Clearly this is quite a contrived example, but it serves to show just how much you can throw into a single subexpression.
Yes, if you wanted to, you could use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$()&lt;/code&gt; the same way &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@()&lt;/code&gt; is used here, if you needed to.&lt;/p&gt;

&lt;p&gt;Sometimes you'll find the alternative is significantly longer, more convoluted, and quite a bit slower.
There are advantages to be had in being able to contain so many different constructs inside a single statement, from time to time.&lt;/p&gt;

&lt;p&gt;I would definitely be wary of trying to encapsulate &lt;em&gt;too&lt;/em&gt; many complicated statements into a single subexpression, to be sure.
Knowing it's possible just ensures you have the option open to you, should you ever need it.&lt;/p&gt;</content><author><name></name></author><category term="powershell" /><category term="code style" /><category term="good practices" /><category term="subexpression" /><category term="functional" /><category term="style" /><summary type="html">I've always been a fan of using subexpressions to tidy up my code. They tend to help me collect and store output where I need it, without requiring that I add complex loops and delve into .NET collection types. The pattern seems to be a bit of a rarity among a lot of other scripters I see, so I thought I'd write a post on subexpressions and all the ways you can use them!</summary></entry><entry><title type="html">Building Arrays and Collections in PowerShell</title><link href="https://vexx32.github.io/2020/02/15/Building-Arrays-Collections/" rel="alternate" type="text/html" title="Building Arrays and Collections in PowerShell" /><published>2020-02-15T00:00:00-05:00</published><updated>2020-02-15T00:00:00-05:00</updated><id>https://vexx32.github.io/2020/02/15/Building-Arrays-Collections</id><content type="html" xml:base="https://vexx32.github.io/2020/02/15/Building-Arrays-Collections/">&lt;p&gt;Well, it's certainly been a while since I posted on here.
Trying to get back into the swing of things for 2020 now that I'm mostly settled in at my new job.
So, let's take a look at a classic problem that never fails to confuse folks just getting into PowerShell.
I've also seen plenty of more experienced folks trip over it quite a lot, so here we are.&lt;/p&gt;

&lt;p&gt;Before we begin, many thanks to Chris Dent for asking me to put this together and the basis for the recommendations at the end!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#background-information&quot;&gt;Background Information&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#background---collections-in-net&quot;&gt;Background - Collections in .NET&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#icollection&quot;&gt;ICollection&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#collections-in-powershell&quot;&gt;Collections in PowerShell&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#common-patterns&quot;&gt;Common Patterns&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#use-of--to-build-arrays&quot;&gt;Use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; to Build Arrays&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#whats-wrong-with-this-picture&quot;&gt;What's Wrong with this Picture&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#using-an-expandable-list&quot;&gt;Using an Expandable List&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#why-use-a-list&quot;&gt;Why Use a List&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#using-the-pipeline&quot;&gt;Using the Pipeline&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#working-with-collections&quot;&gt;Working With Collections&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#new-object-vs-new-vs-casting&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-Object&lt;/code&gt; v.s. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::new()&lt;/code&gt; v.s. Casting&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#adding-many-items-to-an-existing-collection&quot;&gt;Adding Many Items to an Existing Collection&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#general-recommendations&quot;&gt;General Recommendations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;background-information&quot;&gt;Background Information&lt;/h2&gt;

&lt;p&gt;The term &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collection&lt;/code&gt; is often bandied about, so let's define it concretely before we get started, shall we?
In general parlance, a &lt;em&gt;collection&lt;/em&gt; is generally considered to be a pretty broad term.
In its simplest usage, it just refers to a set of individual items.
Oftentimes, these items may be related to one another in some way.&lt;/p&gt;

&lt;h3 id=&quot;background---collections-in-net&quot;&gt;Background - Collections in .NET&lt;/h3&gt;

&lt;p&gt;In the .NET ecosystem, the term &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collection&lt;/code&gt; has a pretty well-defined meaning.
A &quot;collection&quot; is any type of object that implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ICollection&lt;/code&gt; interface.
Seems a bit circular, right?
Let's look at what that actually means and take a quick refresher on what an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interface&lt;/code&gt; actually is in .NET for those of you who're not familiar.
From the C# Programming Guide's &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/&quot;&gt;page on interfaces&lt;/a&gt;, we get this definition:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An interface contains definitions for a group of related functionalities that a non-abstract class or a struct must implement.&lt;/p&gt;

  &lt;p&gt;By using interfaces, you can, for example, include behavior from multiple sources in a class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a bit of a wordy definition, but it does the job.
In practical terms, an interface is a way of defining a required set of properties or methods that must be defined by any other type that wants to inherit from or &lt;em&gt;implement&lt;/em&gt; this interface.
It's a way of being able to define standard ways of interacting with more than one kind of object.&lt;/p&gt;

&lt;h3 id=&quot;icollection&quot;&gt;ICollection&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.icollection?view=netcore-3.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ICollection&lt;/code&gt;&lt;/a&gt; is a fairly simple interface that has a few demands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Methods
    &lt;ul&gt;
      &lt;li&gt;CopyTo(Array array, int index)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Properties
    &lt;ul&gt;
      &lt;li&gt;Count&lt;/li&gt;
      &lt;li&gt;IsSynchronized&lt;/li&gt;
      &lt;li&gt;SyncRoot&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not a whole lot, huh?
So for a type to be an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ICollection&lt;/code&gt;, it needs to guarantee these things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CopyTo()&lt;/code&gt; method that you can use to copy its items into an array of your choosing starting from the requested index.&lt;/li&gt;
  &lt;li&gt;It has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Count&lt;/code&gt; property that will give you the current number of items in that collection.&lt;/li&gt;
  &lt;li&gt;It has the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IsSynchronized&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SyncRoot&lt;/code&gt; properties.
For collections that utilise this functionality, these can be used to determine whether a collection's state is synchronised across threads.
One example of a collection that allows you to create synchronised versions, you can check out &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.hashtable?view=netcore-3.1&quot;&gt;Hashtable&lt;/a&gt; and its static method &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.hashtable.synchronized?view=netcore-3.1&quot;&gt;Synchronized()&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fairly straightforward on the whole, I suppose.
Interfaces can get quite complex, and there are two main extensions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ICollection&lt;/code&gt; in use in .NET Core: &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.ilist?view=netcore-3.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IList&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.idictionary?view=netcore-3.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IDictionary&lt;/code&gt;&lt;/a&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IList&lt;/code&gt; types represent a &quot;flat&quot; collection, where it's simply an ordered list of items.
On the other side of things, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IDictionary&lt;/code&gt; represents a less-strictly-ordered set of key/value pairs where a given key (often a string such as a name) is used to access the relevant item directly.&lt;/p&gt;

&lt;h2 id=&quot;collections-in-powershell&quot;&gt;Collections in PowerShell&lt;/h2&gt;

&lt;p&gt;The main type of collection in use in PowerShell is the humble &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;, at least in terms of what is often available directly from a script.
Behind the murky curtain, PowerShell actually utilises the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Collections.ArrayList&lt;/code&gt; type quite heavily in its pipeline processor.&lt;/p&gt;

&lt;p&gt;Partially as a result of that, arrays (and more specifically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object[]&lt;/code&gt;) are the backbone of PowerShell scripting.
In the vast majority of cases, you're going to be handling arrays unless you deliberately choose to use another type of collection to handle output.
Let's take a look at some fairly common methods of handling collections of items in PowerShell, shall we?&lt;/p&gt;

&lt;h3 id=&quot;common-patterns&quot;&gt;Common Patterns&lt;/h3&gt;

&lt;h4 id=&quot;use-of--to-build-arrays&quot;&gt;Use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; to Build Arrays&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Seems pretty simple and sound, at least at first glance.
So… spot anything amiss?&lt;/p&gt;

&lt;p&gt;The pattern here is &quot;create the collection object, and then add each item to it one at a time&quot;.
This works quite well for some collection types, but not so well for others.
In fact, for arrays specifically it's technically not &lt;em&gt;possible&lt;/em&gt; to do this — arrays are actually fixed-size collections.
If you call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$array.Add(10)&lt;/code&gt; you'll get an error stating as much.
But this still works, somehow, and it's all thanks to some ✨ PowerShell magic! ✨&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ &lt;strong&gt;Behind the Scenes&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;PowerShell's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; operators are designed to work with arrays in a relatively unusual way.
When you try to add items to an array like this, what &lt;em&gt;actually&lt;/em&gt; happens goes something like this:&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;PowerShell checks the size of the collection in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$array&lt;/code&gt; and the number of items being added to it (in this case, just one each time).&lt;/li&gt;
    &lt;li&gt;PowerShell creates a &lt;em&gt;completely different&lt;/em&gt; array of the correct size.&lt;/li&gt;
    &lt;li&gt;The original array is copied into this new array, along with the new item(s).&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;This is also why it's perfectly possible to join two arrays together with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; operators.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;whats-wrong-with-this-picture&quot;&gt;What's Wrong with this Picture&lt;/h5&gt;

&lt;p&gt;The missing piece here, and &quot;what's wrong&quot; in some ways is that this operation can become prohibitively expensive.
For smaller arrays, it's not a concern at all.
The main problem is that we won't always know ahead of time how big our collection might become.&lt;/p&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$array&lt;/code&gt; is quite large (say somewhere in the realm of 5,000-10,000 items), then generating new arrays every single time you add just a couple of items becomes &lt;strong&gt;very&lt;/strong&gt; expensive to do.
A new array, even if it's empty, requires allocation of memory so that the array has enough space to exist in a single region of memory.
Adding a single item to a 10,000 item array means reserving a new block of memory, enough to hold &lt;em&gt;another&lt;/em&gt; 10,001 items, then copying everything across.&lt;/p&gt;

&lt;p&gt;Notice that I didn't mention anything about deleting the original array.
This is because PowerShell can't necessarily assume you're &lt;em&gt;definitely&lt;/em&gt; wanting to completely remove the original array.
You might have another variable storing a reference to that same array in a completely different scope, after all.
Checking for that every time you want to add things to an array would &lt;strong&gt;also&lt;/strong&gt; be prohibitively expensive.&lt;/p&gt;

&lt;p&gt;So what happens, then?
The original array will sit around in memory until the .NET garbage collection routines realize that it's not needed by anything anymore.
In some cases, that can mean it sits around for quite a while before that memory is freed up again.&lt;/p&gt;

&lt;p&gt;For smaller collections, of course, this isn't really an issue at all.
However, this is a very easy pattern to fall into, so it can come back to bite you when you least expect it.
Let's look at a few other ways to approach this task.&lt;/p&gt;

&lt;h4 id=&quot;using-an-expandable-list&quot;&gt;Using an Expandable List&lt;/h4&gt;

&lt;p&gt;.NET contains quite a few types of lists.
If you look at the types that implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IList&lt;/code&gt; you'll see there are quite a few available options.
Oftentimes older blog posts or code examples will have &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=netcore-3.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt;&lt;/a&gt; as their collection of choice.
Personally, I've never liked using ArrayList directly.
As I mentioned above, PowerShell uses it behind the scenes extensively — but I'd be willing to bet that if they had the time available, more than a few people on the PowerShell team would &lt;em&gt;love&lt;/em&gt; to replace it with something more modern.
I know I would; ArrayList comes from the very old days of .NET, hailing all the way back to .NET v1 if I recall correctly.&lt;/p&gt;

&lt;p&gt;In fact, the documentation page for ArrayList warns against its continued use:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ &lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;We don't recommend that you use the ArrayList class for new development.
Instead, we recommend that you use the generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; class.
The ArrayList class is designed to hold heterogeneous collections of objects.
However, it does not always offer the best performance.
Instead, we recommend the following:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;For a heterogeneous collection of objects, use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;Object&amp;gt;&lt;/code&gt; (in C#) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List(Of Object)&lt;/code&gt; (in Visual Basic) type.&lt;/li&gt;
    &lt;li&gt;For a homogeneous collection of objects, use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; class.
See Performance Considerations in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; reference topic for a discussion of the relative performance of these classes.
See Non-generic collections shouldn't be used on GitHub for general information on the use of generic instead of non-generic collection types.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, for completeness' sake, I'll include an example of what using an ArrayList looks like — but I wouldn't recommend ever using it.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# There are multiple ways to create the original ArrayList, but this is one of the simplest and easiest to use.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Collections.ArrayList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Redirection to null is necessary as ArrayList outputs an index number for each added item.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$null&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, let's say we follow that recommendation from the ArrayList documentation, and want to use a generic List instead.
What even is &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netcore-3.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; anyway?
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; is a &lt;strong&gt;generic&lt;/strong&gt; type, which in simple terms just means it has a bit of a fluid definition.
You can define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; in terms of what type of object you want it to work with or (in the case of List, at least) store, where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is the type of object you're storing in it.
For a list comprised entirely of numbers, we might use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;int&amp;gt;&lt;/code&gt; to store them.&lt;/p&gt;

&lt;p&gt;Why would we use this over ArrayList?
In PowerShell there isn't a massive difference here, but for me personally it comes down to a few things.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You can create a List that only stores a specific type, which means you can catch mistakes earlier.
Adding other types of items to that list will either have them converted to the List's designated type, or will throw an error stating that it was the wrong type.&lt;/li&gt;
  &lt;li&gt;Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add()&lt;/code&gt; method on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; doesn't create incidental output like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt;'s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add()&lt;/code&gt; method does, so you have less chance to miss things and pollute your output stream.&lt;/li&gt;
  &lt;li&gt;Given the assertion in the &lt;em&gt;documentation&lt;/em&gt;, no less, that ArrayList is recommended against, I would assume two things:
    &lt;ul&gt;
      &lt;li&gt;There is the possibility at any point that the .NET / .NET Core team will eventually deprecate it completely and possibly even remove it from .NET at that point or afterwards.&lt;/li&gt;
      &lt;li&gt;No further work is being done on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt;, and if there are any improvements to be had you will likely only find them in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Given that, I'd choose to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; instead of ArrayList in every single case.
When using it, there's one question you need to ask before using it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What kind of objects am I storing in this list?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you know ahead of time that you plan on storing more than one type of item in the list, you have two choices:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use a common parent type or interface, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Exception&lt;/code&gt; is the parent type of any Exception-typed object in .NET, so using that base type allows you to store &lt;em&gt;any&lt;/em&gt; other Exception object.&lt;/li&gt;
  &lt;li&gt;Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object&lt;/code&gt; type, which is &lt;strong&gt;the&lt;/strong&gt; parent type for everything in .NET.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our previous examples, we're simply storing numbers.
Let's see how that looks with a generic List, shall we?&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Collections.Generic.List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# No redirection needed here, List&amp;lt;T&amp;gt; does not emit data from Add()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That certainly looks a little tidier.
The long type name is a bit much at times, but at least in PowerShell 5.1 and up, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using namespace System.Collections.Generic&lt;/code&gt; to let you just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[List[int]]&lt;/code&gt; if you prefer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;📝 &lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;While the .NET documentation frequently uses the C# syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;, when we get to PowerShell we actually use square brackets to indicate the generic type parameter instead.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; instead becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[List[T]]&lt;/code&gt;, and in practical usage &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is replaced with another type name.
This is purely a syntactical difference between C# and PowerShell — in both cases we're referring to the same .NET type.
In F# you'd write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;'T&amp;gt;&lt;/code&gt; and in Visual Basic it looks instead like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List(Of T)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;why-use-a-list&quot;&gt;Why Use a List&lt;/h5&gt;

&lt;p&gt;Lists are fantastic for cases where you don't know the collection size ahead of time.
If you knew the size ahead of time, you can simply pre-allocate an array of the correct type and size anyway:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-lt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In PowerShell, they're best used in cases where you need to be adding to the collection from multiple places in your code, &lt;strong&gt;and&lt;/strong&gt; you want the order of items to stay the same as the order you put them into the collection.
They're also the most effective way to build multiple collections in a single loop statement, if that's something you need to do.&lt;/p&gt;

&lt;h4 id=&quot;using-the-pipeline&quot;&gt;Using the Pipeline&lt;/h4&gt;

&lt;p&gt;I mentioned earlier that PowerShell already heavily uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt; in its pipeline processor.
We can actually take advantage of this without ever needing to use ArrayList ourselves directly.
This style of building collections looks a lot more like coding in a functional language than the other options, so it may confuse some folks who aren't accustomed to coding this way.
However, it's perfectly valid and quite flexible in nature.&lt;/p&gt;

&lt;p&gt;The above examples coded this way would look a little more like this:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# This value is not stored anywhere and becomes part of the &quot;output&quot; from the loop statement.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you're not familiar with this kind of pattern, you're probably wondering how on Earth that even works.
In PowerShell, unlike most .NET languages (and indeed many other programming languages in general), allows you to assign a variable to the &quot;result&quot; of a statement, regardless of whether that statement is a keyword-based loop or a complete pipeline.
Any uncaptured output will then be funneled into that variable and stored as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[object[]]&lt;/code&gt; (an array of objects) in the variable.&lt;/p&gt;

&lt;p&gt;Because this utilises the built-in PowerShell pipeline (which, remember, uses ArrayList to handle output), there is no additional overhead of creating another type of collection here.
We're just using what PowerShell has always been ready to provide for us.
This is also one of the simplest ways to keep your code highly compatible across PowerShell versions with minimal effort.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ &lt;strong&gt;Compatibility&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;This pattern works with &lt;em&gt;all&lt;/em&gt; released versions of PowerShell, even back to version &lt;strong&gt;1&lt;/strong&gt;.
For compatibility, it's the absolute best option.
And thankfully, it's one of the most effective options as well!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This pattern works with all PowerShell control-flow statements, which include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreach&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do..until&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do..while&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try..catch..finally&lt;/code&gt; (and there's probably a couple I forgot to mention, but will still work as well!)
It also works seamlessly with pipelines, no matter how lengthy they get:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$pictures&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Filter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Recurse&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Where-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-gt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1MB&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Select-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;working-with-collections&quot;&gt;Working With Collections&lt;/h3&gt;

&lt;h4 id=&quot;new-object-vs-new-vs-casting&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-Object&lt;/code&gt; v.s. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::new()&lt;/code&gt; v.s. Casting&lt;/h4&gt;

&lt;p&gt;This is more of a general point to make about creating new objects in PowerShell, but if you're not aware it bears mention here too.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-Object&lt;/code&gt; is, not to put too fine a point on it, quite slow.
At least compared to alternatives.&lt;/p&gt;

&lt;p&gt;Syntax like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$list = [System.Collections.Generic.List[int]]::new()&lt;/code&gt; is fairly new, first available in PowerShell 5.1.
If compatibility is your main concern, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::new()&lt;/code&gt; is not the first choice, to be sure.
However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-Object&lt;/code&gt; should &lt;em&gt;still&lt;/em&gt; be the last choice, generally being reserved for COM objects and similar otherwise difficult to construct items.&lt;/p&gt;

&lt;p&gt;Syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$list = [System.Collections.Generic.List[int]]@()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[System.Collections.Generic.List[int]] $list = @()&lt;/code&gt; will work all the way back to version 2 of PowerShell.
For a compromise between compatibility and speed I'd go for one of those.&lt;/p&gt;

&lt;h4 id=&quot;adding-many-items-to-an-existing-collection&quot;&gt;Adding Many Items to an Existing Collection&lt;/h4&gt;

&lt;p&gt;If you have a List collection and want to add multiple items to it quickly, rather than using any kind of loop you can actually add them in directly.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; has an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRange()&lt;/code&gt; method that allows you to add multiple items at once:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Collections.Generic.List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]@(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddRange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;5..10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Note - for strongly-typed lists you will need to cast the array you're adding to the relevant array type explicitly:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Collections.Generic.List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]@(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddRange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;general-recommendations&quot;&gt;General Recommendations&lt;/h2&gt;

&lt;p&gt;Taking all the above into account, we can establish some broad recommendations when handling collections of items in PowerShell.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If you &lt;em&gt;can&lt;/em&gt; simply assign the statement to a variable to build your collection, &lt;strong&gt;do so&lt;/strong&gt;.
It's the most compatible approach and one of the simplest ways to handle it.&lt;/li&gt;
  &lt;li&gt;If for some reason you cannot assign the statement or need to build multiple collections in the same loop, use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If you have a scenario where you need to add multiple items to a collection, use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; and make short work of it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRange()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I went into this post thinking it'd be short and sweet, but I really can't help but explain things to the &lt;em&gt;n&lt;/em&gt;th degree, can I? 😂&lt;/p&gt;

&lt;p&gt;That's all I have for now, I think.
If you have any questions or comments, feel free to leave a comment below.&lt;/p&gt;

&lt;p&gt;I'm also keeping an eye out for some more content to cover to get back into regular blog posts, so if there's something I haven't already covered that you're needing some explanation on and think I can help, give me a shout on Twitter or one of the community channels.
Have a great day! 😊&lt;/p&gt;

&lt;!-- Reference Links --&gt;</content><author><name></name></author><category term="powershell" /><category term="style" /><category term="good practices" /><category term="array" /><category term="collection" /><category term="list" /><category term="powershell" /><category term="best practices" /><category term="good practices" /><summary type="html">Well, it's certainly been a while since I posted on here. Trying to get back into the swing of things for 2020 now that I'm mostly settled in at my new job. So, let's take a look at a classic problem that never fails to confuse folks just getting into PowerShell. I've also seen plenty of more experienced folks trip over it quite a lot, so here we are.</summary></entry><entry><title type="html">Working with PowerShell's -replace Operator</title><link href="https://vexx32.github.io/2019/03/20/PowerShell-Replace-Operator/" rel="alternate" type="text/html" title="Working with PowerShell's -replace Operator" /><published>2019-03-20T00:00:00-04:00</published><updated>2019-03-20T00:00:00-04:00</updated><id>https://vexx32.github.io/2019/03/20/PowerShell-Replace-Operator</id><content type="html" xml:base="https://vexx32.github.io/2019/03/20/PowerShell-Replace-Operator/">&lt;p&gt;In case you couldn't already tell, I rather like playing around with regex in PowerShell.
There's something very enjoyable about poking it in &lt;em&gt;just&lt;/em&gt; the right way to get it to do exactly what you want.
I've already talked a bit about how we can use it to &lt;a href=&quot;/2018/11/08/Named-Regex-Matches-PSCustomObject/&quot;&gt;create PSCustomObjects&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;working-with--replace&quot;&gt;Working with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt; is a very handy operator to have quick access to in PowerShell.
In its most basic usage, it allows you to swap out bits and pieces of text, or to remove unwanted pieces from a string.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Glass half empty, glass half full.'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'glass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cup'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cup&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;half&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cup&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;half&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;full.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'[^a-z]'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Glasshalfemptyglasshalffull&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;using-match-groups&quot;&gt;Using Match Groups&lt;/h1&gt;

&lt;p&gt;With the use of parentheses to create a match group, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt; becomes even more powerful.
Stripping out everything from a string &lt;em&gt;except&lt;/em&gt; the one or two things we want is extremely simple.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'You lost your mind in the sound.'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.*(\w+)\.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'$1'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are two things to note in the above example.
First of all, that pattern would match the &lt;em&gt;entire&lt;/em&gt; string, so it would normally just remove the string.
Second, we &lt;em&gt;don't&lt;/em&gt; get the characters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$1&lt;/code&gt; back in our result.&lt;/p&gt;

&lt;p&gt;While that syntax might &lt;em&gt;look&lt;/em&gt; familiar to you from PowerShell's variables, don't be fooled.
This isn't PowerShell, at least not where it counts here.
PowerShell isn't processing that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt; symbol, and we don't want it to; that's why I used single quotes to create a literal string.&lt;/p&gt;

&lt;p&gt;Instead, this string is given to the underlying regex method, which &lt;em&gt;does&lt;/em&gt; recognise it as a variable.
In this context, that variable refers to &quot;the first match group&quot;.
Why is it 1-indexed, you might ask, when &lt;em&gt;literally everything else&lt;/em&gt; in PowerShell is 0-indexed?
Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt; is quietly &lt;em&gt;already taken&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You might recall from my previous post on regex that PowerShell has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$matches&lt;/code&gt; variable, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$matches[0]&lt;/code&gt; refers to &quot;the complete matched string&quot;.
It's the same thing here.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'hello world'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'(\w+) \w+'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'$1 $0'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the match group is respected, pulling the first word, and then the entire match is retrieved again and reinserted.
As you can imagine, this can be made incredibly complex and strange very quickly.
With a bit of tinkering and a careful eye, you can do some wonderful stuff with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt;!&lt;/p&gt;

&lt;h1 id=&quot;named-match-groups&quot;&gt;Named Match Groups&lt;/h1&gt;

&lt;p&gt;Bit of a theme with me, isn't it?
I love anything that can lend a little extra verbosity to a complicated regex pattern, a bit of self-documentation, if you will.&lt;/p&gt;

&lt;p&gt;I was tinkering around with the above syntaxes for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt; (not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt;, though, I hadn't realised that part until I started writing this post!) the other week, and got to wondering.
&lt;em&gt;Is&lt;/em&gt; there a syntax for inserting named match groups in a replace string?
It stands to reason that there &lt;em&gt;ought&lt;/em&gt; to be, doesn't it?
Nobody I asked knew a way, but then again, nobody could say for sure that it &lt;strong&gt;couldn't&lt;/strong&gt; be done, either.&lt;/p&gt;

&lt;p&gt;So, I got to tinkering.
My first attempt looked a bit like this:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Hello darkness, my old friend.'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'(hello) (?&amp;lt;Item&amp;gt;Darkness)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'$Item says $1'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;says&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;friend.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hmm. Okay, not quite there.
As expected, the unnamed group is noticed, but the named group is ignored.
A little bit more fiddling with the syntax, and I landed on the correct way to do it quite by accident.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-replace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'(hello) (?&amp;lt;Item&amp;gt;Darkness)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'${Item} says $1'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;darkness&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;says&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;friend.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Yep.
That worked, very nicely.&lt;/p&gt;

&lt;p&gt;So just remember: the temptation to obscure your code with regex is always there.
But you &lt;em&gt;have&lt;/em&gt; the tools available to make it that crucial bit more self-documenting, provided you name the bits and pieces effectively.
A well-named match string makes it entirely unnecessary to have those &lt;em&gt;four extra lines&lt;/em&gt; of comments attempting to explain what the heck is going on.&lt;/p&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;p&gt;When using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-replace&lt;/code&gt; on a string, the following tokens hold special meaning in the replacement string.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Symbol&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Meaning&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;References the complete matched pattern.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$1&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$n&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;References the &lt;em&gt;unnamed&lt;/em&gt; match group from the pattern string, starting from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$1&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${Name}&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;References the specific &lt;em&gt;named&lt;/em&gt; match group from the pattern string.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Keep your code clear and clean.
It'll save you a great many headaches, &lt;strong&gt;especially&lt;/strong&gt; when dealing with regex!&lt;/p&gt;</content><author><name></name></author><category term="PowerShell" /><category term="Regex" /><category term="powershell" /><category term="regex" /><category term="operators" /><category term="replace" /><category term="match" /><summary type="html">In case you couldn't already tell, I rather like playing around with regex in PowerShell. There's something very enjoyable about poking it in just the right way to get it to do exactly what you want. I've already talked a bit about how we can use it to create PSCustomObjects.</summary></entry><entry><title type="html">Error Handling in PowerShell - Best Practices</title><link href="https://vexx32.github.io/2019/01/31/PowerShell-Error-Handling/" rel="alternate" type="text/html" title="Error Handling in PowerShell - Best Practices" /><published>2019-01-31T00:00:00-05:00</published><updated>2019-01-31T00:00:00-05:00</updated><id>https://vexx32.github.io/2019/01/31/PowerShell-Error-Handling</id><content type="html" xml:base="https://vexx32.github.io/2019/01/31/PowerShell-Error-Handling/">&lt;p&gt;There are a few different kinds of errors in PowerShell, and it can be a little bit of a minefield on occasion.
There are always two sides to consider, too: how you &lt;em&gt;write&lt;/em&gt; code that creates errors, and how you &lt;em&gt;handle&lt;/em&gt; those errors in your own code.
Let's have a look at some ways to effectively utilise the different kinds of errors you can work with in PowerShell, and how to handle them.&lt;/p&gt;

&lt;h1 id=&quot;different-types-of-errors&quot;&gt;Different Types of Errors&lt;/h1&gt;

&lt;h2 id=&quot;terminating-errors&quot;&gt;Terminating Errors&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Terminating&lt;/strong&gt; errors are mostly an &quot;exactly what it sounds like&quot; package in general use.
They're very similar to C#'s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception&lt;/code&gt; system, although PowerShell uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorRecord&lt;/code&gt; as its base error object.
Their common characteristics are as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Trigger &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; blocks&lt;/li&gt;
  &lt;li&gt;Return control to the caller, along with the exception, if they're not handled using a try/catch block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a couple different ways to get a terminating error in PowerShell, and each has its own small differences that make them more useful in a tricky situation.&lt;/p&gt;

&lt;h3 id=&quot;throw&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Throw&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;First is your typical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; statement, which simply takes an exception message as its only input.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Something went wrong&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; creates an exception and an ErrorRecord (PowerShell's more detailed version of an exception) in a single, simple statement, and wraps them together.
Its exceptions display the entered error message, a generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RuntimeException&lt;/code&gt;, and the errorID matches the entered exception message.
The line number and position displayed from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; error message point back to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; statement itself.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; exceptions are affected by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ErrorAction&lt;/code&gt; parameters of their advanced functions.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; should generally be used for simple runtime errors, where you need to halt execution, but typically only if you plan to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; it yourself later.
There is no guarantee a user will not elect to simply ignore your error with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ErrorAction Ignore&lt;/code&gt; and continue with their lives if it is passed up from your functions.&lt;/p&gt;

&lt;h3 id=&quot;throwterminatingerror&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Next, we have a more advanced version of the throw statement. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt; is a method that comes directly from PowerShell's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PSCmdlet&lt;/code&gt; .NET class.
It is accessible only in advanced functions via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PSCmdlet&lt;/code&gt; variable.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;using&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Exception&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;error message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$Error&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.ErrorRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;errorID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.ErrorCategory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NotSpecified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TargetObject&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# usually the object that triggered the error, if possible&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$PSCmdlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ThrowTerminatingError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$Error&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, these require a little more &lt;em&gt;manual labor&lt;/em&gt;.
You can bypass some of this by &lt;em&gt;deliberately&lt;/em&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; statement and then later &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt;ing the generated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorRecord&lt;/code&gt; to pass it into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt; method directly.
This saves a decent amount of the code involved, and offloads the work to PowerShell's engine instead.
However, this will still involve essentially the same work being done, without necessarily giving you a chance to specify the finer details of the error record.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt; creates a terminating error (as the name implies), however &lt;em&gt;unlike&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; its errors are &lt;em&gt;unaffected&lt;/em&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ErrorAction&lt;/code&gt; parameters applied to the parent function.
It will also never reveal the code around it.
When you see an error thrown via this method, it will &lt;strong&gt;always&lt;/strong&gt; display only the line where the command was called, never the code within the command that actually threw the error.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt; should generally be used for &lt;em&gt;serious&lt;/em&gt; errors, where continuing to process in spite of the error may lead to corrupted data, and you &lt;strong&gt;want&lt;/strong&gt; any specified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ErrorAction&lt;/code&gt; parameter to be ignored.&lt;/p&gt;

&lt;h2 id=&quot;non-terminating-errors&quot;&gt;Non-Terminating Errors&lt;/h2&gt;

&lt;p&gt;Non-terminating errors are PowerShell's concession demanded by the fact that it is a shell that supports pipelines.
Not all errors warrant halting &lt;em&gt;all&lt;/em&gt; ongoing actions, and only need to inform the user that a minor error occurred, but continue processing the remainder of the items.&lt;/p&gt;

&lt;p&gt;Unlike terminating errors, non-terminating errors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Do &lt;strong&gt;not&lt;/strong&gt; trigger &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; blocks.&lt;/li&gt;
  &lt;li&gt;Do not affect the script's control flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;write-error&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt; is a bit like the non-terminating version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt;, albeit more versatile.
It too creates a complete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorRecord&lt;/code&gt;, which has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotSpecified&lt;/code&gt; category and some predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorCode&lt;/code&gt; properties that both refer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is a very simple and effective way to write a non-terminating error, but it is somewhat limited in its use.
While you can override its predefined default exception type, error code, and essentially everything about the generated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorRecord&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt; is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; in that it too points directly back to the line where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt; itself was called.
This can often make the error display very unclear, which is rarely a good thing.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt; is a great way to emit straightforward, non-terminating errors, but its tendency to muddy the error display makes it difficult to recommend for any specific uses.
However, as it is itself a cmdlet, it is also possible to make it create &lt;em&gt;terminating&lt;/em&gt; errors as well, by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ErrorAction Stop&lt;/code&gt; parameter argument.&lt;/p&gt;

&lt;h3 id=&quot;writeerror&quot;&gt;WriteError()&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteError()&lt;/code&gt; is the non-terminating cousin of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt;, and is also available as one of the members of the automatic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PSCmdlet&lt;/code&gt; variable in advanced functions.
It behaves similarly to its cousin in that it too hides the code that implements it and instead points back to the point where its parent function was called as the source point of the error.
This is often preferable when dealing with expected errors such as garbled input or arguments, or simple &quot;could not find the requested item&quot; errors in some cases.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Exception&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;error message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$Error&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.ErrorRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;errorID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Management.Automation.ErrorCategory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NotSpecified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TargetObject&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# usually the object that triggered the error, if possible&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$PSCmdlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$Error&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;emit-errors-responsibly&quot;&gt;Emit Errors Responsibly&lt;/h1&gt;

&lt;p&gt;There are no true hard-and-fast rules here.
If one solution works especially well for what you happen to be putting together, don't let me deter you.
However, I would urge you to consider &lt;em&gt;both&lt;/em&gt; the impact to your users as well as yourself or your team before selecting a single-minded approach to error creation.
Not all error scenarios are created equal, so it's very rare that I would recommend using one type over all others.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteError()&lt;/code&gt; is generally preferred over its cmdlet form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error&lt;/code&gt;, because it offers more control over how you emit the error.
Both tend to be used for &lt;em&gt;expected&lt;/em&gt; and technically avoidable errors that occur, but the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PSCmdlet&lt;/code&gt; method has the additional benefit of not divulging implementation details unnecessarily.&lt;/p&gt;

&lt;p&gt;If you &lt;em&gt;expect&lt;/em&gt; the error to occur sometimes, I would generally advise using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteError()&lt;/code&gt; unless the error's presence significantly impairs your cmdlet's ability to process the rest of its input, in which case I would use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThrowTerminatingError()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; is generally nice as a quick way to trigger a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; block in your own code, but I would &lt;em&gt;also&lt;/em&gt; recommend using it for: those &lt;em&gt;truly&lt;/em&gt; unexpected errors, that last-ditch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; clause after several more specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; blocks have been put in place and bypassed.
At this point, a final ending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch&lt;/code&gt; block that simply triggers a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw $_&lt;/code&gt; call to re-throw the caught exception into the parent scope and quickly pass execution back to the caller.
It's a very quick and very effective way to have the error be noticed, but should usually be kept internal to the function more than anything else, except in the last scenario mentioned.
Use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write-Error -ErrorAction Stop&lt;/code&gt; may potentially also be substituted for that purpose if you personally prefer.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;</content><author><name></name></author><category term="PowerShell" /><category term="Scripting" /><category term="Best Practices" /><category term="powershell" /><category term="pwsh" /><category term="errors" /><summary type="html">There are a few different kinds of errors in PowerShell, and it can be a little bit of a minefield on occasion. There are always two sides to consider, too: how you write code that creates errors, and how you handle those errors in your own code. Let's have a look at some ways to effectively utilise the different kinds of errors you can work with in PowerShell, and how to handle them.</summary></entry><entry><title type="html">Playing Around with System.Drawing in PowerShell</title><link href="https://vexx32.github.io/2019/01/17/Playing-Around-System-Drawing-PowerShell/" rel="alternate" type="text/html" title="Playing Around with System.Drawing in PowerShell" /><published>2019-01-17T00:00:00-05:00</published><updated>2019-01-17T00:00:00-05:00</updated><id>https://vexx32.github.io/2019/01/17/Playing-Around-System-Drawing-PowerShell</id><content type="html" xml:base="https://vexx32.github.io/2019/01/17/Playing-Around-System-Drawing-PowerShell/">&lt;p&gt;Through a bit of fiddling with &lt;a href=&quot;https://github.com/vexx32/PSWordCloud&quot;&gt;PSWordCloud&lt;/a&gt; I've found some
rather neat features of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Drawing&lt;/code&gt; that are a little on the weird side, and also not the most
discoverable, so I figured I should talk a little about them.&lt;/p&gt;

&lt;h1 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;/h1&gt;

&lt;p&gt;As I have myself only recently learned, what I've been able to do here, while available in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Drawing.Common&lt;/code&gt;, do not work especially &lt;em&gt;well&lt;/em&gt; in Linux or Mac.
&lt;a href=&quot;https://twitter.com/TylerLeonhardt&quot;&gt;Tyler&lt;/a&gt; has been road testing them for me just a little bit here
and there, and it appears that in both Linux and Mac they have a hard dependency on an external Mono
library called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libgdiplus&lt;/code&gt; that does not usually come packaged with PowerShell or .NET Core by
default.&lt;/p&gt;

&lt;p&gt;Even after this library is installed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On Linux, it appears that attempting to instantiate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Drawing.Region&lt;/code&gt; class completely crashes PowerShell.&lt;/li&gt;
  &lt;li&gt;On Mac, it seems to &lt;em&gt;work&lt;/em&gt; but I cannot guarantee its accuracy; it seems to have trouble with rendering what I asked of it quite properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;some-fun-possibilities&quot;&gt;Some Fun Possibilities&lt;/h1&gt;

&lt;p&gt;So what I've been toying with for PSWordCloud has been the ability to construct complex structures
in the abstract, and then my process has basically been to &quot;store&quot; them by adding them to a Region
object, and on each iteration I check that any new additions don't interfere or overlap with
pre-existing items.&lt;/p&gt;

&lt;p&gt;This is sort of what it looks like:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;using&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;System.Drawing&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add-Type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-AssemblyName&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;System.Drawing&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Specify System.Drawing.Common on PS Core&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Init base image and graphics drawing objects&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Image&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bitmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Width, Height&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DrawingSurface&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FromImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Initialize an empty region&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilledSpace&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Region&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilledSpace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MakeEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Pens for outlines, brushes for fills&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Brush&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SolidBrush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Black&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PenWidth&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;4.5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Pen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PenWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Word&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PointF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Drawing2d.GraphicsPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# The text to render as a path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FontFamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FontFamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# [System.Drawing.FontFamily] object, mostly has the font name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FontStyle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Bold, italic, whatever, [System.Drawing.FontStyle] enum value as an int&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FontSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Em-size of the font&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PointF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DrawLocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Location of the path in the graphics space&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Format&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# [System.Drawing.StringFormat] object with format flags etc.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DrawingSurface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DrawPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Pen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Outline text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DrawingSurface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FillPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Brush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Fill text&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Add path to region&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilledSpace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There's a lot going on that I'm going to sort of skip over here, because we can be here for &lt;em&gt;hours&lt;/em&gt;
before it's all fully explained.
Thankfully, the &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.drawing?view=netcore-2.2&quot;&gt;Microsoft docs on System.Drawing&lt;/a&gt;
are fairly complete, with some useful examples.
Explore all you like, and experiment — that's the &lt;strong&gt;fun&lt;/strong&gt; way to learn, in my opinion!&lt;/p&gt;

&lt;h1 id=&quot;checking-collisions-and-overlaps&quot;&gt;Checking Collisions and Overlaps&lt;/h1&gt;

&lt;p&gt;Now, you'll notice one interesting thing — a little bit &lt;em&gt;missing&lt;/em&gt; in the above example. That's the
sort of &quot;collision checking&quot; or intersection checking that I'm doing &lt;strong&gt;lots&lt;/strong&gt; of in PSWordCloud.
To do that, we have a fairly simple process we can follow, with one small caveat.
When we're drawing our first item, we need to &lt;em&gt;ignore&lt;/em&gt; the collision checking, because the libraries
do some funny things when trying to check collisions against an empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Region&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that mentioned, we can check for collisions based on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Region&lt;/code&gt; object using the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Region.IsVisible()&lt;/code&gt; method.
This method has a &lt;em&gt;bunch&lt;/em&gt; of &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.drawing.region.isvisible?view=netcore-2.2&quot;&gt;overloads&lt;/a&gt;,
for working with a variety of other graphical objects, both with and without reference to an
existing graphics surface object.&lt;/p&gt;

&lt;p&gt;Using this and just retrying a bunch of times as we scan across the image space, we can check any
given area for empty space.
You will, however, notice the somewhat tricky lack of an exact overload for checking the visibility
of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GraphicsPath&lt;/code&gt;.
This stymied me for a moment until I realised that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GraphicsPath&lt;/code&gt; object has a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Path.GetBounds()&lt;/code&gt; method, which returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[RectangleF]&lt;/code&gt; object.
Using this, we can check if a given path's bounds intersect with (are visible when drawn over) the
existing Region object.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$WordBounds&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Returns $true if the rectangle is within the region .IsVisible() is called on&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordIsColliding&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FilledSpace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;IsVisible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$WordBounds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that, we have the framework for figuring out whether or not objects collide, and there
are a &lt;em&gt;whole&lt;/em&gt; lot of different objects you can work with in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Drawing&lt;/code&gt; — lines, curves,
ellipses, polygons, paths, etc. And with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GraphicsPath&lt;/code&gt; objects, you can create literally
anything you want or need using its methods.&lt;/p&gt;

&lt;p&gt;Some of this stuff is really handy for creating images, and it's also &lt;em&gt;so completely outside&lt;/em&gt; the
normal bent for PowerShell folks that working with it is utterly alien for myself, and I'm sure for
many others out there.&lt;/p&gt;

&lt;p&gt;Go wild, have fun, and see what crazy things you can come up with!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;</content><author><name></name></author><category term="powershell" /><category term="graphics" /><category term="drawing" /><category term="graphics" /><category term="powershell" /><summary type="html">Through a bit of fiddling with PSWordCloud I've found some rather neat features of System.Drawing that are a little on the weird side, and also not the most discoverable, so I figured I should talk a little about them.</summary></entry><entry><title type="html">PowerShell's Functional Language Features</title><link href="https://vexx32.github.io/2019/01/10/PowerShell-Functional-Features/" rel="alternate" type="text/html" title="PowerShell's Functional Language Features" /><published>2019-01-10T00:00:00-05:00</published><updated>2019-01-10T00:00:00-05:00</updated><id>https://vexx32.github.io/2019/01/10/PowerShell-Functional-Features</id><content type="html" xml:base="https://vexx32.github.io/2019/01/10/PowerShell-Functional-Features/">&lt;p&gt;Functional languages differ from typical, more concretely object-oriented languages in a few
important ways.
One of the simplest to point out and demonstrate is that in most functional languages, every code
path returns a value — there's effectively no such thing as a method that exists purely to
create some side effect like there often is in object oriented languages.&lt;/p&gt;

&lt;p&gt;I've been meaning to write this post for a while now, ever since my post on
&lt;a href=&quot;/2018/10/26/Anonymous-Functions/&quot;&gt;Anonymous Functions&lt;/a&gt;.
I've been turning over in my head the similarities PowerShell has to some functional languages,
particularly F#, so I thought it was about time I wrote about it!&lt;/p&gt;

&lt;p&gt;I'll restrict my comments here to languages I know pretty well myself, so that really only leaves me
with C#, F#, and PowerShell at the time of writing.
I have some experience in a few others, but they're all pretty thoroughly object-oriented languages,
so I'll leave them aside for the time being.&lt;/p&gt;

&lt;h1 id=&quot;functional-concepts&quot;&gt;Functional Concepts&lt;/h1&gt;

&lt;p&gt;Before I even begin, yes, PowerShell breaks a &lt;em&gt;lot&lt;/em&gt; of functional programming rules.
I'm not here to pretend it doesn't, that would be silly.
However, it's worth looking at PowerShell's features from a functional language perspective from
time to time, because it can really help you grasp those unfamiliar concepts at times, and it's also
quite fun to just use another lens once in a while.
It can really change how you approach your code.&lt;/p&gt;

&lt;p&gt;I'll be borrowing the core concepts list from &lt;a href=&quot;https://thesocietea.org/2016/12/core-functional-programming-concepts/&quot;&gt;this article&lt;/a&gt;
in the interest of keeping things as straightforward as possible.
Functional programming concepts can be a bit weird to wrap your head around for those of us really
accustomed to the more object-oriented concepts.&lt;/p&gt;

&lt;h2 id=&quot;concept-1-functions-are-pure&quot;&gt;Concept 1: Functions are Pure&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;A function called multiple times with the same arguments will always return the same value.
Always.&lt;/p&gt;

  &lt;p&gt;No side effects occur throughout the function’s execution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'll be honest, I've never actually used a functional programming language where this is strictly
true and properly enforceable.
F# &lt;em&gt;can&lt;/em&gt; certainly write very pure functions, but it's also tied to .NET, which means a whole heap
of side effects available for use and abuse at a moment's notice.&lt;/p&gt;

&lt;p&gt;Similarly, PowerShell &lt;em&gt;can&lt;/em&gt; have pure functions, but mostly… doesn't.
Being an automation tool, a great many parts of PowerShell exist precisely &lt;em&gt;because&lt;/em&gt; of their side
effects, and rightly so.&lt;/p&gt;

&lt;h2 id=&quot;concept-2-functions-are-first-class-citizens&quot;&gt;Concept 2: Functions are First-Class Citizens&lt;/h2&gt;

&lt;p&gt;However, in some ways its functions &lt;em&gt;are&lt;/em&gt; first-class citizens.
PowerShell has both script functions and cmdlets, which differ in quite a few ways, but in &lt;em&gt;both&lt;/em&gt;
cases they are themselves a type of object that can be manipulated and worked with.
Cmdlets are their own class type itself, which inherit from the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Management.Automation.Cmdlet&lt;/code&gt; base class.&lt;/p&gt;

&lt;p&gt;Functions are themselves also a type of object — each function can be worked with as an
instance of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Management.Automation.FunctionInfo&lt;/code&gt; class, and after storing a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionInfo&lt;/code&gt; object, you can later execute it.
However, you can't simply store a function itself as an object directly, and you do need to use
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Get-Item&lt;/code&gt; cmdlet to retrieve a function from the current session.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Declare function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Test-FunctionInfo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Testing...&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Get FunctionInfo object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Function:\Test-FunctionInfo'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Retrieve just the contents of the function (its script block)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FunctionScript&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;${Function:\Test-FunctionInfo}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Invoke the function later&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, although it's &lt;em&gt;technically&lt;/em&gt; possible to create &quot;higher-order&quot; functions in PowerShell,
which themselves return some other function, it's generally not particularly feasible or
well-supported to program in such a fashion in PowerShell.&lt;/p&gt;

&lt;h2 id=&quot;concept-3-variables-are-immutable&quot;&gt;Concept 3: Variables are Immutable&lt;/h2&gt;

&lt;p&gt;For those of us who are not very familiar with functional languages (myself included), this concept
seems very &lt;em&gt;odd&lt;/em&gt;.
Programming? With immutable variables? Say &lt;em&gt;what&lt;/em&gt;?
F# follows this &lt;em&gt;to an extent&lt;/em&gt; — its variables are immutable by default, with an optional
modifier that makes them mutable.
It also requires that mutable variables be updated with a special operator for clarity in the code
in terms of which variables are mutable or not.&lt;/p&gt;

&lt;div class=&quot;language-fsharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Immutable variables&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Attempting to re-assign a value later will be a compilation error&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Mutable variables&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Initial assignment&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Assigning a new value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PowerShell, however, has &lt;em&gt;very&lt;/em&gt; mutable variables by default.
However, if you &lt;em&gt;wanted&lt;/em&gt; to program in a more functional manner, you could conceivably do so using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set-Variable&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;New-Variable&lt;/code&gt; to create read-only variables or constants.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Readonly variables can be removed later with Remove-Variable -Force&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-Variable&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readonly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Option&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ReadOnly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Readonly&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Output: 5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Constant variables can never be removed from the scope they're created in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-Variable&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Option&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Constant&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Output: 12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you wanted to program with this ideal in mind, I would generally recommend using read-only
variables instead of constants.
Constants in PowerShell are &lt;em&gt;really&lt;/em&gt; hard to work with at times, but I suppose if you &lt;strong&gt;really&lt;/strong&gt;
wanted to enforce the functional programming concept of immutable variables you could do so with it.
However, I'd still strongly recommend never setting constant variables in the global scope —
the only way to wipe the slate clean there is to literally restart the whole PowerShell session.&lt;/p&gt;

&lt;p&gt;Because PowerShell is a console and an automation framework, it often won't make that much sense to
use too many immutable variables in general use, but I could definitely see that perhaps in a given
module you may want to attempt to code in this matter for greater reliability of results.
However, it's also important to remember that use of some objects may make it rather difficult to
enforce completely — for example, a constant variable may store a hashtable reference, but as
long as you're using an actual hashtable there isn't really a way to make it read only.&lt;/p&gt;

&lt;p&gt;You could, conceivably, instead opt to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[System.Collections.ObjectModel.ReadOnlyDictionary[T1,T2]]&lt;/code&gt;
rather than a hashtable, and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[System.Collections.ObjectModel.ReadOnlyCollection[T]]&lt;/code&gt; instead of
a standard array, however — so if you would like to attempt to go that route, it may be
possible to do so.
Personally, I think having a constant or read-only variable that points to a hashtable that remains
mutable may still be an interesting concept to play with at times.&lt;/p&gt;

&lt;h2 id=&quot;concept-4-functions-have-referential-transparency&quot;&gt;Concept 4: Functions Have Referential Transparency&lt;/h2&gt;

&lt;p&gt;As the &lt;a href=&quot;https://thesocietea.org/2016/12/core-functional-programming-concepts/&quot;&gt;linked article&lt;/a&gt;
details, &lt;em&gt;referential transparency&lt;/em&gt; is a bit of a tricky thing to define properly.
But given the definition in that article, I think it's pretty safe to say that the vast majority of
PowerShell functions and cmdlets are not referentially transparent by nature.
Certainly you &lt;em&gt;can&lt;/em&gt; opt to make something referentially transparent in PowerShell, but in the
majority of places you want to use PowerShell it's probably not a particularly valuable option.&lt;/p&gt;

&lt;h2 id=&quot;concept-5-basis-in-lambda-calculus&quot;&gt;Concept 5: Basis in Lambda Calculus&lt;/h2&gt;

&lt;p&gt;This really comes down to two things. First, that all functions can be written without a name, and
second, that functions are curried.&lt;/p&gt;

&lt;h3 id=&quot;nameless-functions&quot;&gt;Nameless Functions&lt;/h3&gt;

&lt;p&gt;In PowerShell, separating a function from its name or creating a nameless function is quite simple
and straightforward.
You can simply extract the script block from the function to create what is effectively a nameless
function, which can be executed independently as its own object.
Script blocks can also be created independently of functions and passed as parameters or executed on
their own using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; operator or either the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$sb.Invoke()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$sb.InvokeReturnAsIs()&lt;/code&gt; methods.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Scriptblock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Item&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Function:mkdir&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Select-Object&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-ExpandProperty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ScriptBlock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Scriptblock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\Test'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$NewScriptblock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$NewScriptBlock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'C:\Program Files'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;currying-functions&quot;&gt;Currying Functions&lt;/h3&gt;

&lt;p&gt;Currying is probably something most people working with PowerShell either haven't heard of or don't
really use very often.
PowerShell isn't really &lt;em&gt;designed&lt;/em&gt; for currying functions, which I would say is mostly because it's
designed to function as a shell for administrative and automation purposes.
Currying is what a language like F# does naturally, and it's a bit of an unusual concept to those of
us accustomed to working with less functionally-minded languages.&lt;/p&gt;

&lt;p&gt;In F#, all functions have a single set of parameters that are all mandatory, unlike PowerShell.
If you call an F# function with less parameters than it needs to function, it doesn't return any
errors or warnings.
Instead, it's designed such that doing so actually creates a &lt;em&gt;new version&lt;/em&gt; of that function which
effectively has some preset parameters compared to the original.
It's a bit easier to &lt;em&gt;show&lt;/em&gt; than to &lt;em&gt;tell&lt;/em&gt; with this sort of thing, so let's see how this tends to
work.&lt;/p&gt;

&lt;div class=&quot;language-fsharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Define the &quot;base&quot; function&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sumNumbers&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This function can be called directly, with 3 parameters&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sumNumbers&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// returns: 6&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Define a curried function&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addToThree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sumNumbers&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Call curried version, with two parameters&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;addToThree&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// returns: 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PowerShell typically isn't designed to work like this.
However, given that functions can be pretty easily built on the fly with script blocks, you could
potentially design a framework to curry functions in PowerShell.
In general, though, this would almost certainly become rather complicated with PowerShell's ability
to define complex parameter sets and optional parameters.
But if you were &lt;em&gt;really&lt;/em&gt; determined to make it work, you definitely could do so — and with
PowerShell's splatting ability combined with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PSBoundParameters&lt;/code&gt;, it is actually relatively easy to
do so.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add-Numbers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$y&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# &quot;curried&quot; function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add-ToSquare&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Square&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add-Numbers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PSBoundParameters&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Square&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a result, in general usage function currying is, to an extent, almost &quot;baked in&quot; in some ways
to the function design itself, depending on how you choose to construct your parameters, set default
parameters, and permit optional parameters to be omitted.
Working directly with script blocks and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; operator also brings it a bit closer to the
functional programming language methodology, as well.
However, unlike true functional languages, it doesn't do currying by default with all functions.&lt;/p&gt;

&lt;h2 id=&quot;implicit-return&quot;&gt;Implicit Return&lt;/h2&gt;

&lt;p&gt;F# has something that I would usually call an &quot;implicit return&quot; — that is, there isn't really
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; statement, and anything called on a line on its own will return the value to whatever
assignment is &quot;upstream&quot;, if there is any.
If there is no upstream assignment going on, it simply outputs the variable to the console.
I'm not sure if this is something that's super common in functional languages, but it is something
that PowerShell also mimics by design.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$Values&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Number&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Note there is no assignent happening here, so it is passed upstream to the $Values variable&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# and stored as an array.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Number&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Get-Numbers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$End&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Simply outputs the values when the function is called&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$Start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$End&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Numbers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Prints numbers 1 through 10 to the console&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PowerShell &lt;em&gt;does&lt;/em&gt; still have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; statement, but its primary operation here is purely for
flow control.
You can pass it a value if you like, but it doesn't require a value to operate.
When called, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; in PowerShell simply passes control back to the caller of the function or
script.
This can be a bit confusing for some, who are more accustomed to a language like C#, which doesn't
allow for this kind of implicit return, and assume that unless they specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; no values will
be output.
Because of this, the usual recommendation is to restrict use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; only to places where it is
really needed for flow control (to exit a function early) or in classes, where the stricter parsing
and JIT compilation modes make it a requirement.&lt;/p&gt;

&lt;h1 id=&quot;powershell-is-weird&quot;&gt;PowerShell is Weird&lt;/h1&gt;

&lt;p&gt;PowerShell has a lot of object-oriented tendencies, and that's really the core principle of its
overall design.
But because it's &lt;em&gt;also&lt;/em&gt; a functional administrative &lt;strong&gt;shell&lt;/strong&gt;, it also takes a few pages from the
functional programming book as it needs them.
It's a very interesting combination, and I am rather fond of it myself, though I understand all too
well that this unusual combination of concepts can tend to make it a rather confusing language to
work with.&lt;/p&gt;

&lt;p&gt;I've found that at least for myself, I understood PowerShell pretty readily only because I had prior
experience with &lt;em&gt;both&lt;/em&gt; F# and C#, and as a result I was able to pretty easily categorise and note
the different interplay of concepts which often don't really work together in other languages.&lt;/p&gt;

&lt;p&gt;For anyone who wants to get a little more familiar with a more functionally-minded language, I
highly recommend a bit of dabbling in F#.
When I was first looking for learning materials on it, I discovered Chris Marinos'
&lt;a href=&quot;https://github.com/ChrisMarinos/FSharpKoans&quot;&gt;F# Koans&lt;/a&gt;, which I &lt;em&gt;highly&lt;/em&gt; recommend for anyone
wanting to take a look at F# from a beginner's perspective — they were also the inspiration
for &lt;a href=&quot;https://bit.ly/pskoans&quot;&gt;PSKoans&lt;/a&gt;, after all!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;</content><author><name></name></author><category term="powershell" /><category term="powershell" /><category term="functional" /><category term="language" /><summary type="html">Functional languages differ from typical, more concretely object-oriented languages in a few important ways. One of the simplest to point out and demonstrate is that in most functional languages, every code path returns a value — there's effectively no such thing as a method that exists purely to create some side effect like there often is in object oriented languages.</summary></entry><entry><title type="html">Contributing to Open Source Projects - PowerShell Core</title><link href="https://vexx32.github.io/2019/01/03/Contributing-Open-Source/" rel="alternate" type="text/html" title="Contributing to Open Source Projects - PowerShell Core" /><published>2019-01-03T00:00:00-05:00</published><updated>2019-01-03T00:00:00-05:00</updated><id>https://vexx32.github.io/2019/01/03/Contributing-Open-Source</id><content type="html" xml:base="https://vexx32.github.io/2019/01/03/Contributing-Open-Source/">&lt;p&gt;It's been a little while now since I started contributing to PowerShell Core,
so I thought it's probably an apt time to talk about it a little bit.
I've come to the conclusion that sooner or later, we should probably &lt;em&gt;all&lt;/em&gt; look to see if we can
contribute anything to whichever tools we happen to be using.
After all, there really is no one better suited to guide the development of the tools &lt;em&gt;you're using&lt;/em&gt;
on a daily basis than &lt;strong&gt;you&lt;/strong&gt;.
I'll try to break down why I think we should all look to contribute a little something back to the
tools we use in our day-to-day lives wherever we can.&lt;/p&gt;

&lt;p&gt;Developers often have their own ideas for where the project is headed, and that's fantastic —
having a concrete vision for where they want to take the project is essential, if they ever want to
get it off the ground and in common use.
However, it is also arguably just as important for those of us who actually use the end product to
be able to offer our own perspective, experience, and ideas.
A project maintained alone can only survive so long, after all.&lt;/p&gt;

&lt;p&gt;Without a new perspective every once in a while, many things get ignored or overlooked; it's
essential to be able to hear about the areas where the product falls short as well as the areas it
does well.
Without that, it becomes a never-ending minefield of guessing what will be valuable in the short
term as well as what is worthwhile pursuing in the long-term.&lt;/p&gt;

&lt;h1 id=&quot;selfish-selflessness-perspective-is-important&quot;&gt;Selfish Selflessness: Perspective is Important&lt;/h1&gt;

&lt;p&gt;While it may not always be &lt;em&gt;voiced&lt;/em&gt;, I can't help but feel that all too often I see people take the
attitude of &lt;em&gt;&quot;well, it doesn't necessarily help me or what I'm doing; why should I bother?&quot;&lt;/em&gt;
Certainly, there may not always be a clear reason to contribute to an open source project.
It mightn't help you in your day to day &lt;em&gt;immediately&lt;/em&gt; with that specific tool, or you mightn't have
the necessary knowledge &lt;strong&gt;right now&lt;/strong&gt; to make something happen that you'd like to see.&lt;/p&gt;

&lt;p&gt;Even so, I think it's well worth your while to contribute as much as you're able to spare the time
for as a hobby.
I have at least a few reasons for believing this.&lt;/p&gt;

&lt;h2 id=&quot;reason-1-it-helps-the-overall-development-of-the-project&quot;&gt;Reason 1: It helps the overall development of the project&lt;/h2&gt;

&lt;p&gt;You mightn't be able to contribute immensely to the core functionality of a tool, you mightn't even
be all that familiar with the language used to create the tool.
Even so, you can chip in and help out with a small amount of the &quot;simpler&quot; things, like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Low-priority issues&lt;/li&gt;
  &lt;li&gt;Minor bugs&lt;/li&gt;
  &lt;li&gt;Small quality-of-life improvements&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I emphasize documentation because it's the easiest to neglect, but also one of the most important
things that affects the adoption of products as well as new features.&lt;/p&gt;

&lt;p&gt;Helping out with these &quot;less-important&quot; but frequently overlooked &quot;minor&quot; things can really free up
other contributors and the project maintainers to be able to dedicate their time to the more
flashy and impressive new features or overhauls that &lt;em&gt;always&lt;/em&gt; take more time.
If they're always finding their time chipped away by having to constantly handle the small stuff,
they'll be caught in the uncomfortable place of either having to &lt;em&gt;ignore&lt;/em&gt; these issues entirely to
get that new feature completed (often to the detriment of documentation), or they'll have to forego
the necessary time investment to properly complete or even get any work done at all on the new
feature they've been trying to work on.&lt;/p&gt;

&lt;p&gt;With even a handful of people helping chip away at the smaller issues, the ones that seem on the
surface to be &quot;less important&quot; no longer need take up time for everyone else who is contributing to
the project.
As a result, the project's development can be accelerated quite a bit just by a few people taking a
little time to jot down some documentation or tackle the relatively simpler fixes and minor issues.&lt;/p&gt;

&lt;h2 id=&quot;reason-2-it-helps-you-develop-your-own-skills-or-learn-new-ones&quot;&gt;Reason 2: It helps you develop your own skills, or learn new ones&lt;/h2&gt;

&lt;p&gt;My first contribution to PowerShell Core was very much a trial by fire, as Patrick put it.
I was grumbling in the PowerShell &lt;a href=&quot;https://j.mp/psdiscord&quot;&gt;Discord&lt;/a&gt; server about how it was very
annoying that you can't specify named parameters for .NET methods in PowerShell, I think.&lt;/p&gt;

&lt;p&gt;Enter Patrick, stage left (known widely as &lt;a href=&quot;https://twitter.com/seeminglyscienc&quot;&gt;@seeminglyscienc&lt;/a&gt;
on Twitter, and similarly &lt;a href=&quot;https://github.com/SeeminglyScience&quot;&gt;SeeminglyScience&lt;/a&gt; on Github) who
simply asked me &quot;Why don't &lt;em&gt;you&lt;/em&gt; make it happen?&quot;&lt;/p&gt;

&lt;p&gt;Frankly, I was surprised.
I hadn't even &lt;em&gt;considered&lt;/em&gt; doing it myself — and I suspect I am not the only one out there who
simply hasn't even considered contributing.
That's part of the reason I'm writing this at all, really.&lt;/p&gt;

&lt;p&gt;I knew I was out of my depth, but Patrick was keen to help me figure it out.
He gave me initial pointers, some places to start, and told me to send him a message if I got stuck.
In the interests of transparency, that idea &lt;em&gt;still&lt;/em&gt; hasn't really gotten anywhere.
It's still out of my depth a bit, but I'm confident now that given enough time to work on it and
sufficient guidance, I could absolutely make it happen.
It's a pet project that I've not yet found the time to complete just yet, but it's very much doable.&lt;/p&gt;

&lt;p&gt;Before I got too far with &lt;em&gt;that&lt;/em&gt;, however, someone brought up PowerShell's rather &lt;strong&gt;sparse&lt;/strong&gt; support
for different numeric types.
Sure, you can apply a type cast, but unlike many other languages — including its close cousin
C# — PowerShell really only supported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;long&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimal&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; at the time.
(This has &lt;a href=&quot;https://github.com/PowerShell/PowerShell/pull/7813&quot;&gt;since&lt;/a&gt; &lt;a href=&quot;https://github.com/PowerShell/PowerShell/pull/7901&quot;&gt;changed&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;I started to wonder about this as well, and before long I asked Patrick if he knew where I should
start looking — and of course he did.
I've since found that quite a lot of the folks you'll run across in the PowerShell repository (and
indeed many of those who maintain or contribute to projects written in PowerShell) are &lt;em&gt;extremely&lt;/em&gt;
helpful and willing to point you where you need to go.&lt;/p&gt;

&lt;p&gt;After several iterations and a couple of pull requests I ended up closing because, frankly, my
commit history was an absolute &lt;strong&gt;mess&lt;/strong&gt;, I had a three part project on my hands.
The last pull request in this particular saga is still pending review, but if you're interested in
checking out the improvements I coded into the tokenizer (including the native ability for PS to
parse binary numbers, with a &lt;em&gt;very&lt;/em&gt; gracious nod to &lt;a href=&quot;https://github.com/HumanEquivalentUnit&quot;&gt;HumanEquivalentUnit&lt;/a&gt;
for his impressive work helping me refine and optimize the binary parse method) you can find that
ongoing &lt;a href=&quot;https://github.com/PowerShell/PowerShell/pull/7993&quot;&gt;here&lt;/a&gt; at the time of writing.&lt;/p&gt;

&lt;p&gt;And beyond that, I've since branched out into some extra smaller projects, like improving the type
inference for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$_&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PSItem&lt;/code&gt; in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catch {}&lt;/code&gt; block, once again with some interesting ideas from
Patrick's inventive mind.&lt;/p&gt;

&lt;p&gt;Now, I started out knowing &lt;em&gt;some&lt;/em&gt; C#, but not an awful lot.
I would say I knew just enough to be able to comprehend most code bases I would be reading, but in
terms of actually being able to &lt;em&gt;write&lt;/em&gt; it well, I was pretty rusty at best.
I took one year of a C# course back in college, and then got too bored to continue; I wasn't exactly
the model student for that sort of thing.
However, having a project to puzzle over for a time really helped me get a great many more tools
under my belt, and I'm relatively confident that at the moment I could probably work in any codebase
I want to, provided I have a little bit of extra time to familiarize myself with the code and
general structure.&lt;/p&gt;

&lt;h2 id=&quot;reason-3-it-prepares-you-to-take-on-the-tougher-stuff&quot;&gt;Reason 3: It prepares you to take on the tougher stuff&lt;/h2&gt;

&lt;p&gt;As I mentioned above, I made it rather hard for myself in the beginning when I started contributing
to PS Core; I can't say I would &lt;em&gt;recommend&lt;/em&gt; starting that way, but it certainly has its merits.
Even so, it's probably not for &lt;strong&gt;everyone&lt;/strong&gt;.
We all learn in different ways, after all.&lt;/p&gt;

&lt;p&gt;But no matter where you start, you'll be gaining some amount of familiarity with the project's code,
their general code of conduct, their methodology when it comes to the product's lifecycle and the
rhythm they like to work with.&lt;/p&gt;

&lt;p&gt;Hang around the repository and look at other people's pull requests, talk about issues that are
raised, and keep learning.
Sooner or later, you'll be ready enough to tackle that issue you've been eyeing for the past couple
weeks.
And if you're not quite sure where to start, I can think of no better way than to simply submit an
issue on the problem or enhancement you're looking to create, lay out what you do know, what you
don't, and more often than not someone else will happily help you figure out where to start.&lt;/p&gt;

&lt;p&gt;If you hit a major roadblock, don't be afraid to submit a WIP pull request and ping a few of the
active maintainers or contributors asking for a bit of assistance.
Most of them are only too happy to help, overjoyed that someone else is also willing to help out,
even if they're having difficulties.&lt;/p&gt;

&lt;h1 id=&quot;contribute&quot;&gt;Contribute&lt;/h1&gt;

&lt;p&gt;With that all said, I really only can urge everyone to contribute wherever they can.
It's all too easy to say &quot;Well, someone &lt;em&gt;else&lt;/em&gt; will make it happen eventually.&quot;
And, sure, maybe they will.
But maybe they &lt;strong&gt;won't&lt;/strong&gt;, because they think &lt;em&gt;just like you&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Change happens when a &lt;em&gt;community&lt;/em&gt; makes it happen, not when one lone person decides it's time.
Time and time again we see in this world that some corporate &quot;leader&quot; or CEO tries to make something
change, but doesn't really tell anyone else how or why it &lt;em&gt;should&lt;/em&gt; change.
Inevitably, it backfires — the community is a rubber band that pulls things back to how they
were in some form or another.&lt;/p&gt;

&lt;p&gt;If you want your favourite tool, framework, or language to get better, it's very much up to you.
Many will grow without you, if they must, but in just about every case, another pair of helping
hands and a fresh set of eyes with just a &lt;em&gt;slightly&lt;/em&gt; different perspective can really amplify the
growth and accelerate progress immensely.&lt;/p&gt;

&lt;p&gt;What deserves your time?&lt;/p&gt;

&lt;p&gt;What deserves your perspective?&lt;/p&gt;

&lt;p&gt;How can you make an impact?&lt;/p&gt;</content><author><name></name></author><category term="powershell" /><category term="contributing" /><category term="PS Core" /><category term="powershell" /><category term="csharp" /><category term="github" /><category term="open source" /><summary type="html">It's been a little while now since I started contributing to PowerShell Core, so I thought it's probably an apt time to talk about it a little bit. I've come to the conclusion that sooner or later, we should probably all look to see if we can contribute anything to whichever tools we happen to be using. After all, there really is no one better suited to guide the development of the tools you're using on a daily basis than you. I'll try to break down why I think we should all look to contribute a little something back to the tools we use in our day-to-day lives wherever we can.</summary></entry><entry><title type="html">All About PSKoans</title><link href="https://vexx32.github.io/2018/12/27/All-About-PSKoans/" rel="alternate" type="text/html" title="All About PSKoans" /><published>2018-12-27T00:00:00-05:00</published><updated>2018-12-27T00:00:00-05:00</updated><id>https://vexx32.github.io/2018/12/27/All-About-PSKoans</id><content type="html" xml:base="https://vexx32.github.io/2018/12/27/All-About-PSKoans/">&lt;p&gt;It's been a handful of months since I started working on the PSKoans module, so I thought I'd take
the time to set down the story behind the PSKoans module.
It borrows from some koans modules from other languages, and the concept of koans as a programming
tool seems to originate from a Ruby project — although at least a handful of other languages
now have koan libraries available for learners.&lt;/p&gt;

&lt;p&gt;The concept of &lt;em&gt;kōans&lt;/em&gt; was first introduced to me when I first decided to learn how to code in F#.
Initially, I struggled quite a bit.
For those of you who mightn't be familiar with it, it's a bit of an unusual language that aims to
bring functional language features into a .NET family language.
This places it in a bit of a strange in-between, where many of the libraries are heavily
object-oriented, and yet the language itself is quite clearly built for more functional constructs.&lt;/p&gt;

&lt;p&gt;Whilst searching for learning resources, I stumbled across
&lt;a href=&quot;https://github.com/ChrisMarinos/FSharpKoans&quot;&gt;Chris Marinos' F# Koans&lt;/a&gt;, which (like other koans
projects) aim to teach you F# by presenting you with a series of failing assertions, and guiding you
towards fixing them, teaching you the logic behind how it works.
These in turn are inspired by &lt;a href=&quot;https://github.com/edgecase/ruby_koans&quot;&gt;EdgeCase's Ruby Koans&lt;/a&gt;, and
the readme there has further links and information as the origins of the concept itself.&lt;/p&gt;

&lt;h1 id=&quot;first-some-definitions&quot;&gt;First, Some Definitions&lt;/h1&gt;

&lt;p&gt;You could say the simplest definition of a &lt;em&gt;kōan&lt;/em&gt; is &quot;a logical contradiction.&quot; The term is &lt;strong&gt;old&lt;/strong&gt;,
dating back to Zen Buddhist monks, who would be instructed to meditate upon logical contradictions
until they could arrive at a purely &lt;em&gt;intuitive&lt;/em&gt; understanding of a concept being studied, rather
than simply reasoning logically.
It is often written simply as &lt;em&gt;koan&lt;/em&gt;, mainly because the accented O character can be a bit tricky to
type on English keyboards.&lt;/p&gt;

&lt;p&gt;For programming purposes, a koan usually is framed as an assertion which is initially written in a
'failing' state.
A contradiction.
Something simple like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 + 1 | Should -Be 3&lt;/code&gt; (at least, if you write it in Pester syntax) should
give you the general idea.
In actuality, many koans projects opt to define a custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blank&lt;/code&gt; function to represent a space to be
filled in; in PSKoans I have a function named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Get-Blank&lt;/code&gt; which uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__&lt;/code&gt; as its alias, and a
similar idea is used in Chris Marinos' F# Koans.&lt;/p&gt;

&lt;p&gt;This is used to create an assertion that will always fail the first time around, and often some
interaction framework is used as an in-between to help guide the pupil to where to look in the error
message and how to find the issue and resolve it For example:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Describe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Addition'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'is basic arithmetic'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Executing this in PowerShell (with PSKoans installed, or a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return $null&lt;/code&gt; function aliasing
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__&lt;/code&gt; command call) will result in the following output:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gi&quot;&gt;+ Describing Addition
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;-   [-] is basic arithmetic 3.9s
-     Expected 6, but got $null.
-     3:         __ | Should -Be ( 5 + 1 )
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pretty straightforward; tells you what's wrong, and where it needs to be fixed.&lt;/p&gt;

&lt;h1 id=&quot;closing-the-gap&quot;&gt;Closing the Gap&lt;/h1&gt;

&lt;p&gt;Up until recently, a &lt;em&gt;majority&lt;/em&gt; of PowerShell learning materials fit into the following categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Books&lt;/li&gt;
  &lt;li&gt;Talks&lt;/li&gt;
  &lt;li&gt;Blog Posts&lt;/li&gt;
  &lt;li&gt;Documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all &lt;em&gt;wonderful&lt;/em&gt; ways to learn and expand on what you know.
However, they lack a certain something that I would have loved to have when I was learning the ropes
myself — that extra bit of interactivity.
For me, learning to code from a &lt;em&gt;book&lt;/em&gt; has always been a doomed prospect.
There's something incredibly disconnecting about the code being on a printed (or even digital) book
page; if you ever want to try something out, you have to write everything out all at once, and if
you're not familiar with the language, chances are you'll mess it up and not even begin to know
where you went wrong.
Books are great for teaching concepts, but for me they miss by a large margin when trying to convey
or really impress the practicality of the language, or even the depth of its usefulness.&lt;/p&gt;

&lt;p&gt;Talks have a similar issue, I fear; they're fantastic for opening up your breadth of knowledge and
showing you some really cool stuff you mightn't see or hear about otherwise, but they fall quite
flat when you don't have the basics down and can't really follow what's going on quite yet.&lt;/p&gt;

&lt;p&gt;And blog posts and documentation can often be far too dry to really spark those learning moments.
Not that they're &lt;em&gt;bad&lt;/em&gt;, of course.
They have their place, as everything else I listed does — and I'm sure I missed a few methods,
as well — but there's a gap where it really truly pays to have some form of interactive
experience, and I &lt;strong&gt;hope&lt;/strong&gt; that that's where PSKoans can come in and really shine.
My wife likens it to a game — we set the challenges, and you need to solve them one by one or
in bulk if you prefer, and we can give you feedback of how you're doing, where you're going wrong,
and (down the development road, anyway) potentially even eventually some suggestions of how to
proceed in areas you might get stuck.&lt;/p&gt;

&lt;h1 id=&quot;taking-the-plunge&quot;&gt;Taking the Plunge&lt;/h1&gt;

&lt;p&gt;I'm sure many of my readers are probably tending towards the more advanced, but it's been my own
experience that we tend to have little holes in our knowledge even of the more basic things.
In fact, as I create the koans for a particular topic I often learn new things about that very topic
&lt;em&gt;while I'm writing them!&lt;/em&gt;
So, if you've not yet found the time to knock out a few koans and see why I keep suggesting new
folks try it, I can only encourage you to give it a shot — you may well learn something from
the experience.&lt;/p&gt;

&lt;p&gt;If nothing else, perhaps you'll gain enough familiarity to simply be able to provide a gentle
recommendation for those learning PowerShell.
I've been chatting to a few people about their possible application in a more controlled group
classroom or training-type setting as well, and &lt;a href=&quot;https://thomasrayner.ca&quot;&gt;Thomas Rayner&lt;/a&gt; has already
begun teaching some of his coworkers using PSKoans as one of the primary tools.
His initial results are encouraging, but as with any stress test I tend to miss the occasional
oddity until someone stumbles across it.
It's very hard to properly review your own writings, after all, even when they are in PowerShell
— but I try my best!&lt;/p&gt;

&lt;h2 id=&quot;installing-the-module&quot;&gt;Installing the Module&lt;/h2&gt;

&lt;p&gt;PSKoans is available from the PowerShell gallery, or the &lt;a href=&quot;https://bit.ly/pskoans&quot;&gt;Github page&lt;/a&gt;, so
you can install it anywhere you have a PowerShell 5.1 or PowerShell Core engine available.
It's designed to be fairly easy to work with, but it does require a recent version of Pester to be
installed, so make sure you have that down and then it's simply an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Install-Module PSKoans&lt;/code&gt; away!
If you have any issues or concerns, feel free to leave an issue on the Github and I'll get back to
you shortly — or if it's urgent, you can reach me on the
&lt;a href=&quot;https://j.mp/psdiscord&quot;&gt;PowerShell Discord server&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="PowerShell" /><category term="PSKoans" /><category term="Tools" /><category term="Beginner" /><category term="koans" /><category term="learning" /><category term="powershell" /><summary type="html">It's been a handful of months since I started working on the PSKoans module, so I thought I'd take the time to set down the story behind the PSKoans module. It borrows from some koans modules from other languages, and the concept of koans as a programming tool seems to originate from a Ruby project — although at least a handful of other languages now have koan libraries available for learners.</summary></entry></feed>