2021: A PowerShell Year in Review

2021 was quite the year for PowerShell. We saw a lot of first and improvements in the platform. Not just from Microsoft but the community as a whole. I also personally hit a few milestones.

First and foremost, happy 15th birthday to PowerShell.

This year was also a huge year for me. My book Practical Automation with PowerShell was released for early access. You can purchase the eBook now and read chapters 1-8 right away, with chapters 9-11 coming very soon. The full book will be available this spring in eBook or hardcopy. This book aims to help you take your PowerShell skills to the next level and create full enterprise-ready automations.

Unfortunately, my blog posting has slowed a bit due to writing an entire book, but I did hit the 100th edition milestone for PowerShell Weekly. And I’m planning some redesigns for it later this year.

This year also marked my Podcast debut on IT Reality Podcast. I was also honored to present Automate Your Entire Server Patching Process for PowerShell Southampton and Automate the Admin for the New York PowerShell Meetup.

I’m looking forward to continuing my journey with PowerShell and technology in general. But I know most of you aren’t here to read about me, so here is my recap of some of the highlights from this year.

PowerShell Team

The PowerShell team at Microsoft has a busy year. me other firsts for PowerShell this year.

  • PowerShell 7 saw 12 different production releases, including 7.2.0 in November, followed quickly by 7.2.1 in December. There were also 11 preview and RC releases.
  • SecretManagement and SecretStore modules are made generally available, giving PowerShell a secure, repeatable, customizable way to store and retrieve passwords and secrets inside your scripts/automations.
  • PowerShell 7.2 updates are made available via Microsoft Update
  • Azure AD modules were migrated to Graph
  • PowerShell Crescendo 0.7.0-Preview.4 is released. Getting us one step closer to having a production-ready framework to develop PowerShell cmdlets for native OS commands. On any platform.
  • PowerShellGet 3.0 Preview 12 Release includes more parameters, additional pipeline support, more wildcard support and a number of other features detailed in the link provided.

The Community

Some remarkable and noteworthy community contributions from this year.

  • @kieranwalsh made a little PowerShell script to scan all locally installed modules and update them.
  • @Christopher83 with a great tip about using CTRL+SPACE to get a list of cmdlets.
  • @Jaap_Brasser developed a fantastic module to help configure Windows 11.
  • @SimonWahlin released the MyTesla module to automate your Tesla. Because why not!
  • @Ba4bes wrote a post showing you to create an API to find an Azure resource abbreviation. And how to turn it into an Azure Function App. All with PowerShell.
  • @TylerLeonhardt released Inline Values support for PowerShell. Allowing you to level up your PowerShell debugging by seeing values of variables right inline in the VS Code editor.
  • u/Kathy_Cooper1012 shared a script to audit Office 365 user’s activity with PowerShell.
  • u/rumorsofdemise shows how to test connectivity to ports from a server.
  • u/MadBoyEvo with the only command you will ever need to understand and fix your Group Policies (GPO).

PowerShell and Security

I don’t know about the rest of you, but it felt like every time we finished resolving some major vulnerability, another would pop up. Thank full the community and PowerShell were there to help us through some of the tough times.

  • @0gtweet with a script to remotely stop all spoolers where only default printers exist. #PrintNightmare
  • @sstranger created Get-Log4shellVuln.ps1 to scan all local drives for the presence of log4j jar files and analyzed the contents of the jar file to determine if it is vulnerable to log4shell (CVE-2021-44228) vulnerability
  • @darkQuassar  released a new package called AzureHunter, a Cloud Forensics Powershell module to run threat hunting playbooks on Azure UnifiedAuditLog data.

Top 10 PowerShell Weekly Links

These links were the most visited from PowerShell Weekly Newsletter

  1. Jeff Hicks: Better Event Logs with PowerShell
  2. u/DustinDortch: Why is  += so frowned upon?
  3. Kelvin Tegelaar: Tech in 5 minutes: Azure Functions
  4. Grzegorz Tworek: StopAndDisableDefaultSpoolers.ps1
  5. Adam Driscoll: Search Everything with PowerShell
  6. Idera: Finding System Paths
  7. Exchange Team: EXO V2 PowerShell module is now Generally Available on Linux & macOS
  8. Ioan Popovici: Clean-ADInactiveDevice
  9. Adam Driscoll: This is a PowerShell syntax\technique I was unaware of until today.
  10. Damien Van Robaeys: OneDrive and PowerShell: Get size and size on disk.

Modules

These modules were either released this year or received notable updates.

  • Pester v5.3.1 Pester provides a framework for running BDD style Tests to execute and validate PowerShell commands inside of PowerShell. Version 5.3.x included a bunch of new functionality, including a new Code Coverage mode, configure output for failed tests, automatic CI detection, and much more.
  • PSSlack v1.0.6 PowerShell module for the Slack API. Version 1.0.6 was released with multiple improvements and updates.
  • Foil v0.1.0 A PowerShell Crescendo wrapper for Chocolatey – https://github.com/ethanbergstrom/Foil
  • PnP.PowerShell v1.9.0 Microsoft 365 Patterns and Practices PowerShell Cmdlets
  • Posh-SSH v3.0.0 Provides SSH and SCP functionality for executing commands against remote hosts.

I know this post doesn’t even come close to capturing even a small amount of community contributions. So please feel free to comment or contact me with the ones you think should be included.

2023: A PowerShell Year in Review

2023 was quite the year for me and PowerShell, so I thought I would put together a brief summary of the year as I saw it. Plus provide you with some fun and interesting statics from the PowerShell Weekly newsletter.

This year was also a huge year for me. My book Practical Automation with PowerShell was released in April. This book aims to help you take your PowerShell skills to the next level and create full enterprise-ready automations. It was a real labor of lover to share my experiences in automation with the world. And I hope everyone who has read it has found it useful.

I’m looking forward to 2024 where I plan on making some major updates to some of my community module, publish more blog content, and in general continue my journey with PowerShell and technology in general. But I know most of you aren’t here to read about me, so here is my recap of some of the highlights from this year.

PowerShell Platform

PowerShell 7.4 was made generally available in November and is now built on .NET 8.
• The new package manager, PSResourceGet was released and is now included in PowerShell 7.4.
Microsoft Graph modules have now officially replaced the Azure AD modules.
• There were also new releases for PSReadLine and Crescendo.

Community

The PowerShell Podcast is still going strong with weekly releases and are almost up to 100 episodes.
The Pacific PowerShell User Group was started, and many local user groups are still going strong. Most notably the New York PowerShell Meetup and Research Triangle PowerShell User Group. (If you know of other PowerShell user groups please let me know and I’ll add them here.)
• This year was also my time presenting at the PowerShell + DevOps Global Summit. It was great getting to meet so many member of the community in person. Be sure to check out the PowerShell + DevOps Global Summit 2023 playlist on YouTube for my presentation and all of the others. And don’t forget to purchase your tickets to the 2024 summit.

PowerShell Weekly by the Numbers

For those who aren’t aware PowerShell Weekly is a weekly collection of PowerShell news, blogs, scripts, and other related media from world the web, that I found useful and wanted to share. With this being the end of the year, I thought I would share some interesting insights and numbers from 2023. Start with the number:

689
The total number of links this year

301
The number of unique contributors

140
The number of unique sites

Top Links
Completion Predictor v0.1.1 Release by The PowerShell Team (231 – clicks)
How to Create a Powershell Form Generator by Fabio De Oliveira (193 – clicks)
PowerShell Extension for Visual Studio Code Spring 2023 Update by The PowerShell Team (153 – clicks)
Building your own Terminal Status Bar in PowerShell by mdgrs (145 – clicks)
Automatically convert a PowerShell command to use splatting by Mike F. Robbins (116 – clicks)
PowerShell KeePass and saving time. by Emil Larsson (115 – clicks)
Increase maturity of PowerShell script with Mermaid diagram by Wiktor Mrowczynski (115 – clicks)
Best Practices Make Perfect by Jeff Hicks (110 – clicks)
POSH by James Brundage (110 – clicks)
How to optimize and speed up your PowerShell scripts by Bas Wijdenes (103 – clicks)

I hope everyone has a wonderful holiday season and I will see you all again in 2024.

Compare Images

The following function can be used to compare two pictures based on size and a pixel-by-pixel comparison.

Function Compare-Images {
    param(
        $ReferenceFile,
        $DifferenceFile
    )
    $ReferenceImage = [System.Drawing.Bitmap]::FromFile($ReferenceFile)
    $DifferenceImage = [System.Drawing.Bitmap]::FromFile($DifferenceFile)

    if ($ReferenceImage.Size -ne $DifferenceImage.Size) {
        Write-Host "Images are of different sizes"
        $false
    }
    else {
        # Set the difference to 0
        [float]$Difference = 0;
        # Parse through each pixel
        for ($y = 0; $y -lt $ReferenceImage.Height; $y++) {
            for ($x = 0; $x -lt $ReferenceImage.Width; $x++) {
                $ReferencePixel = $ReferenceImage.GetPixel($x, $y);
                $DifferencePixel = $DifferenceImage.GetPixel($x, $y);
                # Caculate the difference in the Red, Green, and Blue colors
                $Difference += [System.Math]::Abs($ReferencePixel.R - $DifferencePixel.R);
                $Difference += [System.Math]::Abs($ReferencePixel.G - $DifferencePixel.G);
                $Difference += [System.Math]::Abs($ReferencePixel.B - $DifferencePixel.B);
            }
        }
        # Caculate the precentage of difference between the photos
        $Difference = $(100 * ($Difference / 255) / ($ReferenceImage.Width * $ReferenceImage.Height * 3))
        if ($Difference -gt 0) {
            Write-Host "Difference: $Difference %" 
            $false
        }
        else {
            $true
        }
    }
}
PS C:\>Compare-Images "C:\Pictures\Pic01a.png" "C:\Pictures\Pic01b.png"
Difference: 0.01859266 %
False

The this post of part of the series Automation Authoring. Refer the main article for more details on use cases and additional content in the series.

Find All agent-based Hybrid Runbook Workers

In case you are not away the Microsoft Monitoring Agent (MMA) will be retired on 31 August 2024. Prior to this date you will need to migrate all your agent-based hybrid workers to the extension-based worker. Microsoft has provided plenty of guidance on migrating the existing agent-based hybrid workers to extension-based hybrid workers. However, it may be difficult to keep track of all the hybrid workers in your environment and which ones have been migrated.

I put together the following script that will gather all the hybrid workers in your environment and let you know which ones are still agent-based. Just connect to Azure using the Connect-AzAccount and run this script below.

# Run Connect-AzAccount before running this script
Function Get-SubscriptionHybridRunbookWorkers{
    [CmdletBinding()]
    param(
        $SubscriptionId
    )
    # Set context to the subscription
    if($(Get-AzContext).Subscription.SubscriptionId -ne $SubscriptionId){
        Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop | Out-Null
    }
    Write-Verbose "Connected to $($(Get-AzContext).Subscription.Name)"

    # Get all of the automation accounts
    $AllAutomationAccounts = Get-AzAutomationAccount

    foreach($acct in $AllAutomationAccounts){
        Write-Verbose " - Account: $($acct.AutomationAccountName)"
        $autoAcct = @{
            AutomationAccountName = $acct.AutomationAccountName 
            ResourceGroupName = $acct.ResourceGroupName
        }
        # Get all the Hybrid Runbook Worker Groups
        $HybridRunbookWorkerGroups = Get-AzAutomationHybridRunbookWorkerGroup @autoAcct
        foreach($hrwg in $HybridRunbookWorkerGroups){
            # Output all the individual Hybrid Runbook Workers
            Get-AzAutomationHybridRunbookWorker @autoAcct -HybridRunbookWorkerGroupName $hrwg.Name | Select-Object WorkerType, WorkerName, 
                @{l='HybridRunbookWorkerGroupName';e={$hrwg.Name}}, @{l='GroupType';e={$hrwg.GroupType}}, @{l='SubscriptionId';e={$SubscriptionId}},
                @{l='AutomationAccountName';e={$acct.AutomationAccountName}}, @{l='ResourceGroupName';e={$acct.ResourceGroupName}}
        }
    }
}

# Get all enabled Azure subscriptions
$AllSubscriptions = Get-AzSubscription | Where-Object{ $_.State -eq 'Enabled' } | Select-Object Name, Id -Unique

$AllHybridRunbookWorkers = foreach($sub in $AllSubscriptions){
    Get-SubscriptionHybridRunbookWorkers -SubscriptionId $sub.Id
}

# Output all v1 hybrid workers aka the agent-based ones that need to be migrated
$AllHybridRunbookWorkers | Where-Object{ $_.WorkerType -eq 'HybridV1' }

Once the script is complete, it will output any hybrid workers that still have the worker type of HybridV1. This indicates that it is an agent-based worker and will need to be migrated.

WorkerType                   : HybridV1
WorkerName                   : MyOnPremSrv.contoso.com
HybridRunbookWorkerGroupName : HybridGroup01
GroupType                    : User
SubscriptionId               : d02f6dda-71fd-45b6-a0c0-4a9510dcb33e
AutomationAccountName        : MyAutomationAccount
ResourceGroupName            : TheResourceGroup

Any hybrid workers with the Group Type of User are members of a hybrid worker group. You can follow Microsoft’s guidance for migrating the existing agent-based hybrid workers to extension-based hybrid workers.

The Group Type of System indicates the machine is registered with the Automation Update Management. For these follow Microsoft’s guidance to move virtual machines from Automation Update Management to Azure Update Manager.

PowerShell Weekly Redesign!

I am pleased to announce that PowerShell Weekly has been redesigned and moved to its own sub-site psweekly.dowst.dev. All past posts and links are available there as well.

What’s New

  • New look and feel
  • Thumbnails for every link
  • Improved searching of the 2,000+ links
    • Search by keyword, date, author, category
  • Custom RSS Feed specifically the links
Practical Automation with PowerShell

After months and months of work, I’m proud to announce my new book is now available for purchase.

Practical Automation with PowerShell

Practical Automation with PowerShell reveals how you can use PowerShell to build automation solutions for a huge number of common admin and DevOps tasks. It takes you beyond scripting basics and shows you how to handle the unforeseen complexities that can keep automations from becoming reusable and resilient. You’ll discover tools and platforms that let you share your automations with your team and even roll them out to non-technical users through easy-to-understand frontends.

All code examples and scripts in the book are available on the GitHub repo for the book.
Practical-Automation-with-PowerShell

The book is in the Manning Early Access Program (MEAP). In MEAP, you read a book chapter-by-chapter while it’s being written and get the final eBook as soon as it’s finished. Which offers several benefits over the traditional “wait to read” model.

  • • Get started now. You can read early versions of the chapters before the book is finished.
  • • Regular updates. We’ll let you know when updates are available, and you can get the new content from your Manning user account.
  • • Get finished books faster. MEAP customers are the first to get final eBooks and pBooks.
  • • Contribute to the writing process. Your feedback in the liveBook Discussion Forum makes the book better.

Be sure to check back here, GitHub, and Manning