Lesson Note
PowerShell 7: Adding Commands — Class Notes
Full class notes for MoL ch. 7: management shells, snap-ins vs modules, module discovery/import, profile scripts, and the PowerShell Gallery.
- Published
- Reading time
- 14 min read
On this page
How these notes were made: the material supplied for this lesson was the chapter’s own heading list — “How one shell can do everything”, “About product-specific management shells”, “Extensions: finding/adding snap-ins”, “Extensions: finding/adding modules”, “Command conflicts and removal”, “On non-Windows OS”, “Playing with a new module”, “Profile scripts”, “Getting modules from the internet”, “Common points of confusion” — with an explicit instruction to draft the content from general knowledge rather than a transcript. These notes follow that structure, but the explanations are written from general knowledge of PowerShell’s module system, not reproduced or paraphrased from Don Jones and Jeffery Hicks’s actual book text, which was not supplied. Worth checking against your own copy of the chapter for their specific wording and examples.
Class notes · Learn Windows PowerShell in a Month of Lunches (3rd ed.), Don Jones and Jeffery Hicks · Chapter 7
Quick reference: the short version of this lesson lives in the Learn PowerShell resource sheets. This follows Chapter 6 (The Pipeline) and shifts focus: rather than what PowerShell can already do, this chapter is about extending what it can do with additional commands.
Learning objectives
By the end of these notes you should be able to:
- Explain how one shell provides commands for many different products.
- Explain what a “management shell” actually is.
- Distinguish snap-ins from modules, and find and load each.
- Resolve command-name conflicts between extensions.
- Explain module behaviour differences on non-Windows platforms.
- Use a profile script to preload extensions automatically.
- Find and install modules from the internet.
1. How one shell can do everything
PowerShell’s core engine does not, by itself, know how to manage Exchange mailboxes, Azure resources, or SQL Server databases. Instead, PowerShell is built to be extended: vendors and the community ship cmdlets for their own products as add-ons, which you load into an ordinary PowerShell session as needed. The result is that the same shell — the same syntax, the same pipeline, the same help system — works for practically any product that has published a PowerShell extension, rather than needing a completely different tool for every product.
2. Product-specific “management shells”
Many products ship with what looks like their own dedicated shell — for
example, an “Exchange Management Shell” shortcut, or a “SQL Server PowerShell”
icon. These are not separate shells with their own engine. They are
ordinary powershell.exe (or pwsh) sessions, launched with a shortcut that
automatically loads that product’s extension before you see a prompt.
Exam tip: if you understand this, a “management shell” stops looking like a mysterious separate tool and becomes simply “PowerShell, with one particular extension already loaded” — you could achieve the same result yourself in an ordinary PowerShell window by loading that extension manually.
3. Extensions: finding and adding snap-ins
Snap-ins are the older of the two extension mechanisms, from early
PowerShell versions. A snap-in is a compiled .dll registered with Windows,
providing a set of cmdlets.
Get-PSSnapin -Registered # list snap-ins installed and available to load
Add-PSSnapin <SnapinName> # load a registered snap-in into the session
Get-PSSnapin # list snap-ins currently loadedNote (beyond this lesson): snap-ins are effectively legacy. They only work in Windows PowerShell (not in cross-platform PowerShell 7/PowerShell Core), and Microsoft’s own guidance since PowerShell 2.0 has been to prefer modules for new extensions. You mainly still encounter snap-ins with older products that have not been updated (some legacy Exchange tooling being a well-known example).
4. Extensions: finding and adding modules
Modules are the modern extension mechanism, and almost everything you add to PowerShell today will be a module rather than a snap-in.
Get-Module -ListAvailable # list modules installed on this system
Import-Module <ModuleName> # load a module into the current session
Get-Module # list modules currently loadedOnce a module is imported, the commands it provides behave exactly like built-in cmdlets — same discoverability, same help, same pipeline behaviour.
In the real world: since PowerShell 3.0, you often do not even need to run
Import-Moduleexplicitly. If a command from an installed module is typed at the prompt, PowerShell auto-discovers and auto-loads the module that provides it the first time it is used in a session.
5. Command conflicts and removal
Two different extensions can sometimes provide a command with the same name. When that happens, the most recently imported module’s version of the command generally takes precedence.
To avoid a clash deliberately, Import-Module accepts a -Prefix
parameter, which adds a prefix to every noun in that module’s commands (so
Get-User from one module could become Get-ContosoUser when imported with
-Prefix Contoso), letting both versions coexist without a naming collision.
To remove a loaded module (and the conflict it may be causing) from the current session:
Remove-Module <ModuleName>5.1 Worked example — resolving a naming conflict
Two different vendor modules, ModuleA and ModuleB, both provide a
Get-Report cmdlet, and you need both loaded at once.
Import-Module ModuleA
Import-Module ModuleB -Prefix B
Get-Report # runs ModuleA's version
Get-BReport # runs ModuleB's version, thanks to the prefixBoth commands are now available side by side, disambiguated by the prefix rather than one silently overriding the other.
6. Extensions on non-Windows OS
PowerShell 7 (built on .NET, and often called PowerShell Core) runs on Linux and macOS as well as Windows. Not every module behaves identically across platforms:
- Modules that rely on Windows-only APIs (certain hardware, registry, or WMI-dependent features, for instance) may be unavailable or limited on Linux/macOS.
- Most general-purpose modules — especially ones aimed at cross-platform scenarios like cloud management (Azure, AWS) — work consistently everywhere.
- Snap-ins do not work at all outside Windows PowerShell — this is one of the concrete reasons modules have fully superseded them.
7. Playing with a new module
A typical first encounter with an unfamiliar module follows a predictable pattern:
Get-Module -ListAvailable NewModuleName # confirm it's actually installed
Import-Module NewModuleName # load it
Get-Command -Module NewModuleName # see what commands it adds
Get-Help <SomeNewCommand> -Examples # learn one command at a timeThis mirrors the general PowerShell discovery habit from earlier chapters — find what’s there, then read the help — just applied to a module’s commands specifically rather than the whole shell.
8. Profile scripts: preloading extensions when the shell starts
Typing Import-Module for the same set of modules every single session gets
tedious. A profile script runs automatically every time PowerShell
starts, and is the natural place to put commands you always want available —
including Import-Module lines for extensions you use constantly.
$PROFILE # shows the path to your personal profile script
Test-Path $PROFILE # check whether it currently existsIf it does not exist yet, you create it (and its containing folder, if needed) and add lines such as:
Import-Module MyFavouriteModuleNote (beyond this lesson):
$PROFILEactually represents one of several possible profile scripts — PowerShell checks scripts scoped to the current user vs all users, and the current host application (the console) vs all hosts.$PROFILEon its own points at the “current user, current host” profile, the one used most often for personal customisation.
9. Getting modules from the internet
Beyond what ships with Windows or a product installer, a huge additional library of community and vendor modules is published to the PowerShell Gallery, and PowerShell’s built-in package-management commands can search it and install directly from it:
Find-Module -Name SomeModule # search the Gallery
Install-Module -Name SomeModule # download and install it
Install-Module -Name SomeModule -Scope CurrentUser # install for you only, no admin neededOnce installed this way, the module behaves exactly like any other installed
module — Get-Module -ListAvailable, Import-Module, and so on all work the
same regardless of where the module originally came from.
10. Common points of confusion
A few recurring stumbling blocks when working with extensions:
- Installed vs imported. A module can be installed on the system
(present on disk, listed by
Get-Module -ListAvailable) without being imported into your current session (actually usable right now, listed by plainGet-Module). Auto-loading blurs this in practice, but the distinction still matters when troubleshooting “why can’t I use this command.” - Module vs snap-in confusion. Because both extend PowerShell with new
cmdlets, it is easy to assume they behave identically — but snap-ins use a
different loading mechanism (
Add-PSSnapin, notImport-Module) and do not work at all in PowerShell 7. - Scope of installation.
Install-Modulewithout-Scope CurrentUsertypically installs for all users and requires administrator rights — a common source of unexpected “access denied” errors for someone expecting a simple, user-level install. - “Management shell” mystique. As covered in Section 2, a product’s dedicated shell shortcut is not special magic — it is ordinary PowerShell with one extension preloaded, which is worth remembering when a “shell” feels mysteriously limited or oddly configured compared to your usual session.
11. Security perspective
Extending PowerShell with third-party code is, functionally, running someone else’s software with your privileges — worth treating with the same care as any other software installation:
- Modules run with your permissions, and can do anything a script can do. A module is code, not a passive data file; importing it can execute initialization logic immediately. Install modules only from sources you trust — the official PowerShell Gallery listing for a well-known publisher, not an unofficial mirror or a link from an untrusted source.
- The PowerShell Gallery is a public, open publishing platform, similar in spirit to other language package registries — which means it carries the same general supply-chain risk: a malicious or compromised package can be published under a plausible-sounding name. Check publisher identity and package reputation (download counts, review the module’s actual source where available) before installing anything into an environment that matters.
-Scope CurrentUsernarrows blast radius, not just admin friction. Installing for the current user only, rather than all users, means a compromised or malicious module affects one account’s profile rather than every user of the machine — a meaningful containment benefit on a shared or multi-user system, on top of avoiding the need for elevated rights.- Profile scripts are a very effective persistence location. Because a
profile script runs automatically every time PowerShell starts, it is
an attractive place for malicious code to hide if an attacker can write to
it — a rogue
Import-Moduleor arbitrary command added to$PROFILEexecutes silently on every future session. Review profile script contents periodically, and protect write access to profile files the same way you would protect any other auto-run location. - Execution policy is a related, separate control worth knowing exists. PowerShell’s execution policy setting restricts which scripts can run at all — it is not covered in this chapter’s own headings, but it interacts directly with everything here: an overly permissive execution policy removes one of the practical speed bumps against an unwanted script (module or otherwise) running unintentionally.
Summary
- PowerShell is extensible: the same shell gains new product-specific commands by loading extensions, rather than needing a separate tool per product.
- A “management shell” is just ordinary PowerShell with one extension preloaded by its launch shortcut — not a distinct engine.
- Snap-ins (
Add-PSSnapin,Get-PSSnapin -Registered) are the legacy mechanism, Windows-only and largely superseded; modules (Import-Module,Get-Module -ListAvailable) are the modern standard and often auto-load on first use since PowerShell 3.0. - Conflicts between same-named commands favour the most recently
imported module;
-PrefixonImport-Moduleavoids the clash deliberately;Remove-Moduleunloads one. - On non-Windows platforms, most modules work fine, but Windows-only-API modules and all snap-ins do not.
$PROFILEpoints to your personal startup script — put routineImport-Modulelines there to preload extensions automatically.- The PowerShell Gallery hosts installable modules (
Find-Module,Install-Module, optionally-Scope CurrentUser). - Common confusions: installed vs imported, module vs snap-in, install scope, and the “management shell” mystique.
Glossary
| Term | Meaning |
|---|---|
| Extension | An add-on providing new PowerShell commands. |
| Management shell | PowerShell pre-loaded with one product’s extension. |
| Snap-in | Legacy, Windows-only extension mechanism. |
| Module | The modern extension mechanism; cross-platform. |
| Import-Module | Loads a module into the current session. |
| Add-PSSnapin | Loads a registered snap-in into the session. |
| Auto-loading | PowerShell loading a module automatically on first use. |
| -Prefix | Import-Module parameter avoiding command-name clashes. |
| Remove-Module | Unloads a module from the current session. |
| $PROFILE | The path to the current user/host’s profile script. |
| Profile script | A script run automatically at PowerShell startup. |
| PowerShell Gallery | The public online repository for modules. |
| Find-Module | Searches the PowerShell Gallery. |
| Install-Module | Downloads and installs a module from the Gallery. |
| Scope (install) | Whether a module installs for the current user or all users. |
| Execution policy | Setting controlling which scripts may run (beyond this lesson). |
Review questions
- How does PowerShell provide commands for so many different products from one shell?
- What is a “management shell” actually, underneath its shortcut?
- Name the command to list registered snap-ins, and the command to load one.
- What is the modern replacement for snap-ins, and what command imports one?
- What happens automatically, since PowerShell 3.0, when you type a command from an installed-but-not-yet-imported module?
- If two modules provide a command with the same name, which one’s version runs?
- How does the -Prefix parameter on Import-Module solve a naming conflict?
- Which extension type does not work at all outside Windows PowerShell?
- What does $PROFILE point to, and why would you edit it?
- Name the two commands used to search for, and then install, a module from the PowerShell Gallery.
- What does -Scope CurrentUser change about an Install-Module command?
- Describe two of the “common points of confusion” from this lesson.
- Scenario: you need two vendor modules loaded that both define a Get-Status command. How do you use both without one overwriting the other?
- Scenario: a PowerShell session behaves oddly every time it starts, running an unexpected command nobody remembers adding. Where would you look first?
Answer key
- Vendors and the community publish extensions (modules/snap-ins) adding product-specific cmdlets, loaded into an otherwise ordinary shell. Extensibility, not separate tools.
- Ordinary PowerShell with one particular extension already loaded by the shortcut that launches it. No separate engine.
Get-PSSnapin -Registeredlists them;Add-PSSnapin <name>loads one. The legacy pair of commands.- Modules;
Import-Module <name>loads one. The modern mechanism. - PowerShell auto-discovers and auto-loads the module that provides that command, without needing an explicit Import-Module. Auto-loading since v3.
- The most recently imported module’s version takes precedence. Import order matters.
- It prefixes every noun in that module’s commands, so both versions get distinct names and can coexist. Disambiguation by naming.
- Snap-ins — they don’t work outside Windows PowerShell (not in PowerShell 7/Core). Windows-only legacy mechanism.
- The path to your personal (current user, current host) profile script; you edit it to preload extensions or settings automatically at startup. Startup customisation point.
Find-Moduleto search;Install-Moduleto download and install. The Gallery workflow.- It installs the module for the current user only, avoiding the need for administrator rights (versus installing for all users by default). Per-user, no elevation needed.
- Installed vs imported (present on disk vs actually loaded), and module vs snap-in confusion (different loading commands, different platform support) — any two valid points named in the lesson. Recurring stumbling blocks.
- Import one normally and the other with
-Prefix, e.g.Import-Module ModuleB -Prefix B, givingGet-StatusandGet-BStatus. Prefix avoids the clash. - The profile script (
$PROFILE) — it runs automatically on every startup and is a common place for an unexpected auto-run command to hide. A classic startup-persistence location.