PowerShell Uses – Things to Start Doing, Things to Stop Doing

by | Jan 9, 2024 | Blog, Tech Blog

Patch Tuesday Webinar

Join Patch My PC's Jordan Benzing and Bryan Dam every Thursday succeeding Patch Tuesday for the Patch Tuesday Support Group Webinar.

Patch Tuesday Releases

Tech Blogs

Critical Patches

What is Windows PowerShell

Windows PowerShell is a task automation framework and a command-line shell developed by Microsoft.

Windows PowerShell is built on top of the .NET Framework and supports cmdlets (pronounced “command-lets”), which are small, focused scripts or tools that perform a specific task. These cmdlets can be combined and reused to create more complex PowerShell scripts and automation workflows.

Key Features

Command-line Shell

PowerShell command-line shell

PowerShell’s command-line shell is a versatile interface enabling administrators to perform administrative tasks like interacting with cloud services like Azure and on-premise services like Active Directory, modifying server configuration and automating daily tasks. PowerShell’s command-line has a very strong feature set, including object-oriented output, tab completion, scripting, command history as well as accepting and returning .NET objects.

Scripting language

PowerShell script Get-RunningProcesses.ps1 shown in Visual Studio Code

PowerShell is widely used by administrators to automate the management of Windows systems. However, it can also be used to automate the deployment of new devices, as well as test, and deploy code. PowerShell scripts can do something as simple restarting a service, or creating an active directory group, or it could be extended through the use of functions, classes and modules to automate the deployment and maintenance of infrastructure.

Integration with .NET Framework

PowerShell querying .NET classes

PowerShell’s integration with .NET framework allows administrators to easily incorporate .NET functionality into their scripts. Providing them direct access to .NET classes, making it very easy to utilize a wide range of libraries and capabilities, like creating and manipulating .NET objects, invoking .NET methods, loading external .NET assemblies and creating graphical user interfaces through .NET’s Windows Presentation Foundation(WPF) or Windows Forms (WinForms), allowing expansion beyond traditional command-line tasks.

Remote Management

Using PowerShell to remotely connect to another Windows device.

PowerShell’s remote management functionality allows administrators to execute PowerShell commands and scripts on remote devices using technologies like Windows Management Instrumentation (WMI) and PowerShell Remoting, allowing them to gather information, monitor and make configuration changes and provide centralized administration of their environment.

Cmdlets

Cmdlets

PowerShell cmdlets, or commandlets, are specialized commands created for system administration and automation tasks. These tend to follow a naming convention of verb-noun (e.g. Get-Process, or New-Item). Cmdlets perform very specific operations, and their output is generally structured as objects allowing them to be easily combined using pipelines to chain multiple commands together.

Script Execution Policies

Script Execution Policies

PowerShell script execution policies are a security feature designed to allow the control of the conditions under which a script can be run, helping to prevent unintended execution of potentially harmful or malicious scripts. By default PowerShell enforces a fairly restrictive policy, however, users can adjust these policies based on their security requirements.

PowerShell’s origin story

Back in 2002, Before Windows PowerShell was “PowerShell” it was known as “Monad”. This name came from Jeffrey Snover’s realization that Windows needed a good command-line interface and scripting language, similar to Linux, so he coined the Monad Manifesto

Development started in 2003, and v1 was released in 2006. During development it remained “Monad” but upon release the name “PowerShell” was used.

Over the years since then, PowerShell has had many releases, each adding more and more functionality

  • Monad (2003): The development of PowerShell began in 2003 under the codename “Monad.”

  • PowerShell 1.0 (2006): v1.0 was included as part of Windows Management Framework, This was when the concept of cmdlets was first introduced.

  • PowerShell 2.0 (2009): v2.0 was released as part of Windows 7 and Windows Server 2008r2. This release first introduced the Integrated Scripting Environment (ISE), a GUI for creating and running scripts.

  • PowerShell 3.0 (2012): v3.0 was released as part of Windows 8 and Windows Server 2012. Features such as workflow capabilities, improved remoting, and new cmdlets for managing features like networking and storage were included.

  • PowerShell 4.0 (2013): Released with Windows 8.1 and Windows Server 2012 R2. With this version we saw enhancements to Desired State Configuration (DSC) for declarative configuration management. New cmdlets for web services and networking were also introduced.

  • PowerShell 5.0 (2014): v5.0 was initially released with Windows 10 and Windows Server 2016. The PowerShellGet module was included in v5.0, which allowed for the managing PowerShell modules. Script debugging capabilities were improved, and classes were introduced.

  • PowerShell Core (2016): Microsoft expanded PowerShell’s reach beyond Windows to Linux and macOS with PowerShell Core. PowerShell Core is an open-source, cross-platform version of PowerShell that can run on various operating systems.

  • PowerShell 7 (2020): PowerShell 7 is the latest major version. Building on the foundation of PowerShell Core, PowerShell 7 brings some additional features like improved performance, and compatibility with Windows PowerShell 5.1.

Common uses of Windows PowerShell

This list is far from extensive, and common PowerShell uses will be very subjective but these are some of the common uses I found on the PowerShell subreddit and through some internal discussion.

We won’t really go into any of these in huge detail

Management and automation of Azure services (e.g. Entra, Virtual machines or networking)

Managing Azure services is possible through the use of Azure PowerShell. Azure PowerShell is a CLI built on top of the Windows PowerShell framework. It provides a specific set of cmdlets designed for interacting with Azure services and resources including provisioning and managing VMs, configuring network, deploying applications and managing Entra ID.

On-premise infrastructure management (e.g. Active Directory, Group policy, DNS)

Through the use of PowerShell commands that are included in additional modules, Administrators can manage on-premise infrastructure such as Active Directory, Group Policy objects, DNS records and Certificate Services.

Configuration Management and IAS (e.g. PowerShell DSC)

PowerShell Desired state configuration (DSC) is a framework that allows for a consistent and repeatable definition of system configurations. Integrated into PowerShell, DSC gives administrators the ability to specify the desired state of a device using simple scripts known as DSC configurations rather than manually carrying out the step-by-step procedures to achieve the same state.

Application packaging and deployment in ConfigMgr

Administrators can leverage Windows PowerShell to streamilne the creation of ConfigMgr applications by capturing installation configurations and configuring deployment parameters. Additionally, PowerShell allows administrators to automate the deployment of their applications by managing distribution of content, creating deployments and monitoring deployment statuses.

I would try to explain PSADT to you in my own words, but it’s own tag line does it perfectly!

Additionally, utilizing PowerShell to work with your application packages lets you work with technologies like PowerShell App Deployment Toolkit (PSADT).

PSAppDeployToolkit is a versatile solution that streamlines and standardizes the process of software deployment, making it easier than ever to manage your IT environment. It has a comprehensive set of features, such as dynamic logging, user interaction capabilities, and customizable functionality.

If you are interested in reading more about PSADT, check out their website PSAppDeployToolkit.

Searching the Windows event log

Being able to use PowerShell to interact with the Windows event log allows administrators a versatile and efficient way of monitoring and managing system events. PowerShell cmdlets such as Get-EventLog and Get-WinEvent allow for the retrieval of useful event data, filtering on specific criteria and analysis of logs for troubleshooting and auditing.

Managing WSUS

Utilizing PowerShell commands to interact with Windows Server Update Services (WSUS) allows for the managing of Windows updates within an organization in a more streamlined and automated manner.

Note: To interact with WSUS via PowerShell, you will need to install the WSUS tools, which can be done relatively easily.

  • Windows 10 & 11 – Add-WindowsCapability -Online -Name Rsat.WSUS.Tools~~~~0.0.1.0

  • Windows Server – Install-WindowsFeature UpdateServices-API

Cmdlets such as Get-WsusUpdate, Approve-WsusUpdate and Invoke-WsusServerCleanup can be used to query, approve and optimize the update process. Administrators can also automate the process of routine tasks, like synchronizing update metadata and the approval of patches using a PowerShell script.

With that being said, the WSUS cmdlets can be very inefficient and not fun to work with, however, you can also interact with the WSUS API using PowerShell, which is a much better experience.

Microsoft.UpdateServices.Administration Namespace | Microsoft Learn

Installing Windows updates

Admins are able to use Windows PowerShell to automate the download and installation of Windows updates using custom PowerShell scripting. Rather than explain it here, I would recommend checking out this blog post by Adam Cook where he goes into great detail on the subject of using PowerShell to install Windows updates.

Remote device management

Being able to remotely manage your devices is critical, especially if your devices are located in different parts of the country, or even the world. Using PowerShell commands like Invoke-Command and Enter-PSSession to establish remote connections and execute commands on devices helps Administrators query devices, troubleshoot problems and in some situations remediate them as well. Additionally, modules such as PSRemoting allow for the configuration and management of remote sessions, enabling admins to carry out tasks such as software installations, configuration changes and troubleshooting across multiple devices.

Best Practices

There are absolutely more best practices for PowerShell than I can fit in this blog post, but here are 5 that I think are the best ones to mention!

Comment your code!

Writing PowerShell scripts with clear comments are a must have when writing a script that someone else may eventually use in the future.

This ensures that anyone reading it has a better chance of understanding what the script does, and allows then to potentially contribute to the script.

Most importantly, it helps you! For example, If you come back to that script in 6 months time and you forget what you created a specific PowerShell function for.

Comments do not need to be full paragraphs, more often than not a single concise line can sum something up just as well.

Example

In this example we can see 3 comments, “Import the ConfigurationManager.psd1 module”, “Connect to the site’s drive if it is not already present” and “Set the current location to be the side code”

function Set-ConfigMgrSiteDrive {
	[OutputType([System.Void])]
	param (
		[Parameter(Mandatory)]
		[String]
		$SiteCode,
		[Parameter(Mandatory)]
		[String]
		$ProviderMachineName
	)
	try {
		# Import the ConfigurationManager.psd1 module 
		if ($null -eq (Get-Module ConfigurationManager)) {
			Import-Module "$($ENV:SMS_ADMIN_UI_PATH)..ConfigurationManager.psd1"
		}

		# Connect to the site's drive if it is not already present
		if ($null -eq (Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue)) {
			New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName
		}

		# Set the current location to be the site code.
		Push-Location
		Set-Location "$($SiteCode):"
	}
	catch {
		throw $_.Exception.Message
	}
	
}

Use comment-based help in your script headers

Adding a header to your PowerShell scripts lets you add additional useful information like

  • A synopsis and description of your script
  • Notes
  • Examples
  • Links to documentation

A header within your script allows someone who is unfamiliar with your script to understand more about how to use it, what it does and where to go for more help.

The Microsoft documentation on comment-based help can be found here, for more information! – about Comment Based Help – PowerShell | Microsoft Learn

Example

In this example, We can see that a synopsis, description, parameters, examples and notes are all defined.

Example taken from here – https://github.com/PatchMyPCTeam/CustomerTroubleshooting/blob/Release/PowerShell/Export-PMPCInstalledSoftware.ps1

<#
.SYNOPSIS
    Get installed software from the local computer's registry and export to .csv
.DESCRIPTION
    Get installed software from the local computer's registry and export to .csv
.PARAMETER ExportCsvPath
    Specifies the desired path to the CSV to export. This defaults to the current directory with a file name of 'PMPC-Uninstall-Hive-Export.csv'
.EXAMPLE
    Export-PMPCInstalledSoftware -ExportCsvPath 'C:tempPMPC-Export.csv'

    Exports all the uninstall hives to a CSV file named 'C:tempPMPC-Export.csv'
.EXAMPLE
    Export-PMPCInstalledSoftware

    Exports all the uninstall hives to a CSV file named 'PMPC-Uninstall-Hive-Export.csv' in the directory where the function was ran
.NOTES
    ################# DISCLAIMER #################
    Patch My PC provides scripts, macro, and other code examples for illustration only, without warranty 
    either expressed or implied, including but not limited to the implied warranties of merchantability 
    and/or fitness for a particular purpose. This script is provided 'AS IS' and Patch My PC does not 
    guarantee that the following script, macro, or code can or should be used in any situation or that 
    operation of the code will be error-free.
#>

If we query this script using Get-Help we see the following output, which shows the name, synopsis, syntax and related links, but note that there are no examples listed even though we defined them.

Get-Help

What we do see is some additional remarks at the end telling us we we can use Get-Help -Full, -Detailed, or -Examples.

Get-Help Examples

Use clear and concisely named variables

While it may seem quicker and easier to use shorthand variables like $i to make your script shorter, or smaller, when you haven’t updated that script in 6 months or a colleague tries to edit it, $i causes more confusion than anything.

When creating variables, you ideally want to name them after what they are being used for, or what they represent. For example $DeviceNames clearly suggests that it is used to store names of devices.

Additionally, when creating variables the best practice is to stick to alphanumeric characters and the underscore (_) character. Including things like whitespace or other special characters makes variables more difficult to use.

Some additional information taken from the Microsoft Documentation

  • Alphanumeric variable names can contain these characters:
    • Unicode characters from these categories: Lu, Ll, Lt, Lm, Lo, or Nd.
    • Underscore (_) character.
    • Question mark (?) character.
  • The following list contains the Unicode category descriptions. For more information, see UnicodeCategory.
    • Lu – UppercaseLetter
    • Ll – LowercaseLetter
    • Lt – TitlecaseLetter
    • Lm – ModifierLetter
    • Lo – OtherLetter
    • Nd – DecimalDigitNumber

Tabs, not spaces!

Like the other best practices we’ve discussed so far, consistent code indentation really helps with your PowerShell scripts readability. To help keep things as consistent as possible, It’s always recommend to use tab to indent your line, rather than repeatedly pressing the space bar.

  • Note: While this is generally recommended, different PowerShell text editors can interpret indentations like tabs differently. If you create your PowerShell scripts in VSCode then move to NotePad++, it’s worth double checking that your indentation is still correct.
Example

Pick a capitalization convention and stick to it!

While PowerShell is not case sensitive, it is recommended to follow a capitalization convention to ensure your code is easy to read.

  • Microsoft’s documentation on capitalization conventions lists 2 appropriate ways to capitalize identifiers in your scripts.
    • PascalCasing
      • PascalCasing is used for all identifiers, with the exception of parameter names. Capitalize the first character of each word (including all acronyms over two letters in length).
        • e.g. ValidatePattern
        • e.g PSChildName
      • An exception is made for two-letter acronyms, where both letters are capitalized.
        • e.g. IOStream
    • camelCasing
      • camelCasing is used only for parameter names. Capitalize the first character of each word, except the first.
        • e.g. $employeeName
        • e.g. $temperature
      • Unlike PascalCasing, two-letter acronyms that begin a camel-cased identifier are lowercase
        • e.g. ioStream
  • Do use PascalCasing for all public member, type, and namespace names consisting of multiple words
  • Do use camelCasing for parameter names.
    • PowerShell keywords, just to confuse matters more!
      • PowerShell keywords are written in lowercase
        • e.g. begin, foreach, for, exit, if, return.
  • Do not capitalize each word in close-form compound wordsClose-form compound words
    • NOTE: Languages that can run on the CLR are not required to support case-sensitivity, although some do. Even if your language supports it, other languages that might access your framework do not. Any APIs that are externally accessible, therefore, cannot rely on case alone to distinguish between two names in the same context.
  • Do not assume that all languages are case sensitive.
  • At the end of the day PowerShell is not case-sensitive, but be nice to whoever may read your script in the future 🙂

Things to stop doing

Overcomplicating things

While I’m almost definitely guilty of this, more does not always mean better. Keeping it simple is absolutely recommended where possible. Keep your scripts as streamlined and simple as possible, where possible, try to avoid making your script jump around, but instead keep it linear so that it is readable from top to bottom.

PowerShell functions are a fantastic example of where scripts can get unnecessarily complicated.

You can achieve the same result with a simple script, or with a PowerShell function, both of which have their place. Functions are great when writing reusable code, but for single-use or quick snippets, keep it simple!

Example

Simple addition using PowerShell
Simple addition using a PowerShell function

Stop disabling PowerShell in your environment

Instead, configure it correctly.

Now this is a rabbit hole that I’m not going to go too deep into, however, while Windows PowerShell is a very powerful tool, and can absolutely be used malicious, it is equally as powerful at analyzing issues, incident response, automating security tasks as well as basic day to day administrative tasks across your estate.

An excerpt from the NSA, CISA, NZ NCSC and NCSC-UK on keeping PowerShell.

Cybersecurity authorities from the United States, New Zealand, and the United Kingdom recommend proper configuration and monitoring of PowerShell, as opposed to removing or disabling PowerShell entirely. This will provide benefits from the security capabilities PowerShell can enable while reducing the likelihood of malicious actors using it undetected after gaining access into victim networks.

Some straight forward recommendations on securing PowerShell

  • Enable and configure Script Execution
    • Configuring the Windows PowerShell execution policy within your estate, including both client endpoints and servers, to, for example, AllSigned ensures the following
      • Scripts can run
      • Requires that all scripts and configuration files are signed by a trusted publisher, including scripts written on the local device.
      • Prompts before running scripts from publishers that have yet to be classified as trusted or untrusted
    • The remaining risk with AllSigned is that a signed script may still be malicious.
  • Constrained language mode
    • ConstrainedLanguage mode protects your systems by limited the available cmtlets and .NET types that can be used in a Windows PowerShell session.
  • Application Control
  • Just Enough Administration
    • JEA, another technology from Microsoft, is a security tool that enables delegated administration for anything managed by PowerShell.
    • JEA lets you do the following
      • Reduce the number of administrators on your machines
      • Limit what users can do
      • Better understand what your users are doing
  • Secure PowerShell remoting using WinRM

The list of ways you can secure PowerShell goes on, and while you may find it easier to just block PowerShell entirely, the pros of using PowerShell in your environment far out-weight the cons, in my opinion.

Worrying about your code

Everyone writes code differently, which can be seen in the examples given throughout this blog post. As long as you choose a standard for your script, and stick to it, that’s fine – If it works, it works! Yes, I’m sure everyone’s scripts could be better written in some places, consolidated in others and more efficient, but at the end of the day everyone is different. Follow the general best practices, comment your code and stick to your standard and use tabs instead of spaces, you’ll do just fine.

Things you wish you knew about sooner

GitHub Copilot

If I can stress anything enough in this post, it’s that you should look into copilot from GitHub – GitHub Copilot · Your AI pair programmer.

Copilot, from GitHub, can be used within code editors like Visual Studio Code (VSCode) to provide autocomplete-style suggestions. It will provide you with suggestions based off existing code that you have started to type, or from plain text comments detailing what you are trying to achieve. It can review both the open file, as well as other files in your project, to show these suggestions directly in your editor.

Here is an example of using copilot with plaintext input to generate code within VSCode

GitHub copilot text prompt demonstration
GitHub copilot inline demonstration

While the suggestions provided by copilot may not always be perfect, they are usually always a great starting point for what ever you are trying to do.

The PowerShell community

The PowerShell community is extremely active, supportive and available across multiple platforms. If you’re stuck with something, you’ll always find someone is willing to help!

Places that I recommend checking out

  • Twitter, specifically the PowerShell team! The PowerShell Team (@PowerShell_Team) / X (twitter.com), This is the engineering team within Microsoft that are behind PowerShell.
  • Twitter again, but this time make sure you use the #powershell hashtag.
  • The PowerShell Subreddit, reddit.com/r/PowerShell/. Here you will find questions, and answers, from other members of the PowerShell community, and you may even find that someone has already created what you are trying to achieve!
  • The PowerShell Discord, https://discord.gg/powershell. There are channels here dedicated to all things PowerShell.
  • The WinAdmins Discord, https://discord.gg/winadmins. While not specifically dedicated to PowerShell, it has a vast array of members who are very PowerShell savvy.
  • The PowerShell gallery, PowerShell Gallery | Home. You will find a vast array of pre-existing modules hosted here, which are free for you to use within your scripts!
  • Last, and most definitely not least, PSConf EU is an absolute must, PSConfEU – PowerShell Conference Europe. Each year, people from all around the world head to PSConfEU to share their knowledge with Windows PowerShell. Whether your relatively new or have been using PowerShell from day 1, you’re guaranteed to learn something new!

PowerShell in a month of lunches

Some light reading never hurt anyone, especially not when it’s related to PowerShell! PowerShell in a month of lunches is really what got me into PowerShell when I first started as an IT administrator. I can’t recommend it enough if you’re looking to start from scratch, or even brush up on your existing knowledge.

PowerShell is cross platform!

While commonly known as “Windows PowerShell”, PowerShell itself is available on Windows, Linux and macOS! Obviously there are some differences between Windows PowerShell and Linux/macOS, but you can take a lot of what you know and use it to manage and interact with non-Windows devices.

PowerShell differences on non-Windows platforms – PowerShell | Microsoft Learn

Conclusion

You can use Windows PowerShell to do pretty much anything these days, from automating the deployment of virtual servers in platforms like Hyper-V and VMWare, the building of physical servers, or client endpoint devices, automating the configuration of Windows and Linux devices, automate the onboarding or offboarding of new users in Active Directory or Entra ID, interact with APIs, the list is endless.

I feel I could quite easily talk about PowerShell all day, but I’ll finish with this.

PowerShell is awesome.

Tech Blog

Intune Win32 Apps Guide to Availability and Deadlines Feature Image

Intune Win32 apps: A Strategic Guide to Availability and Deadlines

Discover the ins and outs of Intune Management Extension in our latest blog post. We’re exploring its behavior with scheduled win32 app...

Windows Defender Exploit Guard breaks Google Chrome

Often, blog titles are sensationalised and designed to draw the readers attention. In September 2023, we did actually observe the behavior described...
Discovery Apps - Intune Software Inventory - Feature Image

Discovered Apps – The Intune Software Inventory

Is there an Intune Software Inventory? How does Intune detect apps installed in my tenant? Find out everything you need to know about Discovered...

Intune Scope Tags and Role-Based Access Control Explained

In today's interconnected era, it has become increasingly common for large organizations to have multiple IT departments and workers spread across...

Intune Discovered Apps – Missing Inventory Data

At the tail end of June 2023 and into the first week of July 2023, many admins started to report that application inventory data was missing in...
Intune Discovery Apps - Detecting your applications and gaining back control Feature Image

Intune Discovered Apps – Detecting your applications and gaining back control

Learn more about the power of Intune Discovered Apps for application inventory management. Detect and manage your software inventory...

Intune Microsoft Store Integration App Migration Failures (0x87D1041C)

In July 2021, Microsoft announced that both Microsoft Store for Business and Education would be deprecated on March 31, 2023. While Microsoft has...
Automatic Deployment Rules and ConfigMgr

Automatic Deployment Rules (ADR) and ConfigMgr and why you should use them

What is an ADR Getting Started with ADR Creating and Defining an ADR What are Deployment Packages?In this blog we will review Automatic Deployment...

How to use PowerShell to install Windows updates & ensure long-term compliance

In this post I will walk you through how to install Windows updates and report on patch compliance using Windows PowerShell. We will be using:...

Mastering ConfigMgr Client Actions

In this blog post, we’ll take a deep dive into the various SCCM client actions, including when to use them, what they do, and which log files...

Intune Win32 apps: A Strategic Guide to Availability and Deadlines

Discover the ins and outs of Intune Management Extension in our latest blog post. We’re exploring its behavior with scheduled win32 app...

Windows Defender Exploit Guard breaks Google Chrome

Often, blog titles are sensationalised and designed to draw the readers attention. In September 2023, we did actually observe the behavior described...

Discovered Apps – The Intune Software Inventory

Is there an Intune Software Inventory? How does Intune detect apps installed in my tenant? Find out everything you need to know about Discovered...

Intune Scope Tags and Role-Based Access Control Explained

In today's interconnected era, it has become increasingly common for large organizations to have multiple IT departments and workers spread across...

Intune Discovered Apps – Missing Inventory Data

At the tail end of June 2023 and into the first week of July 2023, many admins started to report that application inventory data was missing in...

Intune Discovered Apps – Detecting your applications and gaining back control

Learn more about the power of Intune Discovered Apps for application inventory management. Detect and manage your software inventory...

Intune Microsoft Store Integration App Migration Failures (0x87D1041C)

In July 2021, Microsoft announced that both Microsoft Store for Business and Education would be deprecated on March 31, 2023. While Microsoft has...

Automatic Deployment Rules (ADR) and ConfigMgr and why you should use them

What is an ADR Getting Started with ADR Creating and Defining an ADR What are Deployment Packages?In this blog we will review Automatic Deployment...

How to use PowerShell to install Windows updates & ensure long-term compliance

In this post I will walk you through how to install Windows updates and report on patch compliance using Windows PowerShell. We will be using:...

Mastering ConfigMgr Client Actions

In this blog post, we’ll take a deep dive into the various SCCM client actions, including when to use them, what they do, and which log files...