Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Windows Server Automation with PowerShell Cookbook

You're reading from   Windows Server Automation with PowerShell Cookbook Powerful ways to automate and manage Windows administrative tasks

Arrow left icon
Product type Paperback
Published in Jul 2021
Publisher Packt
ISBN-13 9781800568457
Length 674 pages
Edition 4th Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Thomas Lee Thomas Lee
Author Profile Icon Thomas Lee
Thomas Lee
Arrow right icon
View More author details
Toc

Table of Contents (18) Chapters Close

Preface 1. Installing and Configuring PowerShell 7 2. Introducing PowerShell 7 FREE CHAPTER 3. Exploring Compatibility with Windows PowerShell 4. Using PowerShell 7 in the Enterprise 5. Exploring .NET 6. Managing Active Directory 7. Managing Networking in the Enterprise 8. Implementing Enterprise Security 9. Managing Storage 10. Managing Shared Data 11. Managing Printing 12. Managing Hyper-V 13. Managing Azure 14. Troubleshooting with PowerShell 15. Managing with Windows Management Instrumentation 16. Other Books You May Enjoy
17. Index

Improvements in ForEach and ForEach-Object

Windows PowerShell users are well versed in the use of both the ForEach statement and the ForEach-Object cmdlet. You can use both of these methods in your scripts to process collections, such as all the users in a specific Active Directory group, or the audio files in a file share. In PowerShell 7, both of these iteration methods are considerably faster.

Using either ForEach mechanism is a quick and easy way of processing a collection. One downside some IT pros may have noticed is that the overhead of ForEach processing in Windows PowerShell grows with the size of the collection. With small collection sizes, you are not likely to notice any difference. As the collection size grows, so does the overhead.

Getting ready

You run this recipe on SRV1 after you have installed PowerShell 7 and have created a console profile file. Run this recipe in an elevated console.

How to do it...

  1. Creating a remoting connection to the localhost using Windows PowerShell
    New-PSSession -UseWindowsPowerShell -Name 'WPS'
    
  2. Getting a remoting session
    $Session = Get-PSSession -Name 'WPS'
    
  3. Checking the version of PowerShell in the remoting session
    Invoke-Command -Session $Session  -ScriptBlock {$PSVersionTable}
    
  4. Defining a long-running script block using ForEach-Object
    $SB1 = {
      $Array  = (1..10000000)
      (Measure-Command {
        $Array | ForEach-Object {$_}}).TotalSeconds
    }
    
  5. Running the script block locally:
    [gc]::Collect()
    $TimeInP7 = Invoke-Command -ScriptBlock $SB1 
    "Foreach-Object in PowerShell 7.1: [{0:n4}] seconds" -f $TimeInP7
    
  6. Running the script block in PowerShell 5.1
    [gc]::Collect()
    $TimeInWP  = Invoke-Command -ScriptBlock $SB1 -Session $Session
    "ForEach-Object in Windows PowerShell 5.1: [{0:n4}] seconds" -f $TimeInWP
    
  7. Defining another long-running script block using ForEach
    $SB2 = {
        $Array  = (1..10000000)
        (Measure-Command {
          ForEach ($Member in $Array) {$Member}}).TotalSeconds
    }
    
  8. Running it locally in PowerShell 7
    [gc]::Collect()
    $TimeInP72 = Invoke-Command -ScriptBlock $SB2 
    "Foreach in PowerShell 7.1: [{0:n4}] seconds" -f $TimeInP72
    
  9. Running it in Windows PowerShell 5.1
    [gc]::Collect()
    $TimeInWP2  = Invoke-Command -ScriptBlock $SB2 -Session $Session
    "Foreach in Windows PowerShell 5.1: [{0:n4}] seconds" -f $TimeInWP2
    

How it works…

In step 1, you use New-PSSession to create a remoting session using a Windows PowerShell endpoint. This step produces output like this:

Figure 2.24: Creating a remoting connection to the localhost

In step 2, you get the session object representing the session you created in the previous step. This creates no output.

In step 3, you obtain the version of PowerShell that the remoting session is using to process commands, namely, Windows PowerShell 5.1. The output of this step looks like this:

Figure 2.25: Checking the PowerShell version in the remoting session

In step 4, you create a script block, $SB1, which uses the ForEach-Object cmdlet to iterate over a large collection. This step creates no output.

You invoke the $SB1 script block in the local session, in step 5. This step runs the script block in PowerShell 7. The output from this step looks like this:

Figure 2.26: Running the script block locally

With step 6, you run the $SB1 script block in Windows PowerShell 5.1, which produces output like this:

Figure 2.27: Running the script block in PowerShell 5.1

You next create a script block that makes use of the ForEach syntax item, in step 7, producing no output. You then run this second script block in PowerShell 7, in step 8, which produces output like this:

Figure 2.28: Running the script block locally in PowerShell 7

In the final step, step 9, you run $SB1 in the remoting session created earlier (in other words, in Windows PowerShell 5.1), which produces output like this:

Figure 2.29: Running the script block in PowerShell 5.1

There's more...

In step 1, you create, implicitly, a remoting session to the localhost using a process transport that is much faster than the traditional remoting session using WinRM.

In steps 5, 6, 8, and 9, you force .NET to perform a garbage collection. These are steps you can use to minimize the performance hits of running a script block in a remote session (in Windows PowerShell) and to reduce any impact of garbage collections while you are performing the tests in this recipe.

As you can see from the outputs, running ForEach-Object is much faster in PowerShell 7, as is running ForEach in PowerShell 7. Processing large collections of objects is a lot faster in PowerShell 7.

The improvements to loop processing that you can see in the recipe, combined with the use of ForEach-Object -Parallel you saw in Exploring parallel processing with ForEach-Object, provide an excellent reason to switch to PowerShell 7 for most operations.

The performance of iterating through large collections is complex. You can read an excellent article on this subject at https://powershell.one/tricks/performance/pipeline. This article also addresses the performance of using the pipeline versus using ForEach to iterate across collections in a lot more detail.

You have been reading a chapter from
Windows Server Automation with PowerShell Cookbook - Fourth Edition
Published in: Jul 2021
Publisher: Packt
ISBN-13: 9781800568457
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime