I think it's time to talk in depth about some of the most important features of PowerShell: Providers and modules. (Snap-ins have also been important, but they are being gradually phased out.) These are really the core of the universe when it comes to all of the commands available for use within PowerShell, so I want to teach you what they are, how they work and how to use them in your daily activities. Let's dive in!
Introducing providers
When you hear the term "providers," I bet the non-developers among us (and I include myself in this group) start to tune out. That sounds like something you do along with creating a class and instantiating a for-loop with strings that pass through a model view controller.
But that's not the case here. Let me unpack this for you a little bit, at least in the context of PowerShell.
PowerShell providers are essentially like drivers for the operating system, where you install some code to help your copy of Windows talk to the graphics hardware, the storage and disk subsystems, and the chipset on your motherboard. The drivers contain the "translation layer," which is not an official term, so that Windows knows how to drive the hardware and make it work for your use.
PowerShell providers are drivers for PowerShell to navigate things besides the file system. Providers allow PowerShell to traverse the Registry, the File System, Windows Management Instrumentation (WMI) functionality, and more. Third parties can create providers: For example, there is a SQL Server provider that Microsoft installs that lets you do PowerShell operations on databases.
How providers work
Providers take some collection of something -- whatever resource they are trying to enable for PowerShell management -- and make it look like a file system or disk drive to PowerShell. Providers are used by all sorts of software packages that support PowerShell for administration, like Internet Information Services (Microsoft's web server) and Active Directory.
This is one of PowerShell's key extensibility features, because any resource or data to be managed always shows up like a drive. In addition, new commands can be added that interact with the same data storage, whether that's a database or a list of administrative settings for a website or a mailbox store or anything else, really. It's kind of cool.
How do you know what providers you already have? PowerShell does indeed ship with some. You can use the Get-PSProvider
command to find out which ones.
Provider capabilities and drives
The names of the providers are fairly obvious. PowerShell can make all these items look like disk drives: Aliases, the environment (which includes environmental variables like PATH and more), the FileSystem, functions, the Registry, and any defined variables. So I can reach in and touch data or records in any one of these "places" just by cd:\ing around and adding path-like statements to get to where I want to be. When you use a provider, you are technically creating a PSDrive, and that PSDrive is the representation of the storage or resource you are connecting to as the file system on a disk.
The other columns in the list are capabilities and drives.
Capabilities are a list of ways to use, and things you can (and can't) do with each provider. For the purposes of this article, we won't worry about them.
Drives, on the other hand, are the logical access point for providers. They're like drive mappings in Windows that you would use to make, say, Drive M: represent a share and its contents on another computer. For instance, if we were working with the Registry provider, the "drive letter" used to spelunk around and do things would be HKLM and HKCU. So we might want to change "directory" to HKLM and do a directory listing to see what was available to manage, in which case we would use the Set-Location
cmdlet to change the shell's current container to the container you want.
Here's what that looks like when I issue Set-Location hklm:
at the prompt; take a look at the screenshot below.
You can see that dir listed out the main areas of the Registry, including HKEY_LOCAL_MACHINE\Hardware, HKEY_LOCAL_MACHINE\Software and so on. You work the tree by using it like a file system.
I'm hoping this is starting to make sense to you.
Items
You generally use the item
set of cmdlets to interact with PSDrive providers. If you continue to consider working with providers like working with a file system, then instead of files and folders, think items. They're called items whether you're calling registry items or SQL Server databases. Items is a nice generic term that can be used interchangeably.
How do you figure out what the item cmdlets are? Why, you'd use Get-Command
, of course!
The ones we care about are the cmdlets. Looks like we can clear the value of items, copy them, get information about them, start them, move them, create new items, remove and rename items, set them, and more.
Most of the item
set of cmdlets have a -path
parameter that accepts wildcards like *, but this brings up an important point. Precisely because providers support so many different types of storage and resources, there may be cases in which the wildcard is actually a valid, legal, specific input for a given provider. But if you use the wildcard with PowerShell, the system will get confused.
So, for providers that allow the standard wildcard characters as legal characters in names, you can use the -literalpath
instead of just -path
to tell PowerShell to treat the asterisk as an asterisk and not as a wildcard.
Let's dig in a little further to items. Items have properties, which are basically characteristics about the item. If I have a file, then I have the date that file was created (a property), the date it was modified (a property), whether or not it is read-only or writeable (a property), and so on. If I have a Registry key, I have its location (a property), its type (a property) and so on. Items can also have child items, or items within that item. Again using the file system example, folders can have folders within them and within a folder can be files.
When you want to create a new item, in many cases you have to tell PowerShell what kind of item to create. As I show in the following figure, the Show-Command
entry for New-Item
demonstrates that -ItemType
is a parameter I can specify.
PowerShell sometimes tries to guess what kind of item you should create based on the provider you are currently working with, but it doesn't always guess correctly. So if I'm in C:\Windows\System32 and I want to create a new directory called jhtest with PowerShell, I would use New-Item -Path jhtest -ItemType directory
so PowerShell knew that I want a directory and not a file. If you don't specify, then PowerShell will give you a little prompt that looks like:
```
Type:
```
And you will need to specify the type of new item that you want to create.
Differences in providers matter
It is important to remember that in PowerShell, not every provider has the same capabilities. Some work when others don't, depending on the scenario. Some providers let you access different things than others; some do it in different ways; and some don't work at all.
That's why you always have to think about what capabilities each provider has when building commands using a PSDrive provider, and you must always remember that when you are working with a provider with which you are unfamiliar, be sure to run Get-PSProvider
to understand its capabilities. Even if a command seems like it would work, the context of the provider in which you are running that command matters a great deal.
A provider example: The Registry
The best way to learn is with a hands-on example, and I can think of no better than changing the registry exclusively through the use of PowerShell. Our task is to turn off Wi-Fi Sense in Windows 10. Although the Anniversary Update of Windows 10 killed this feature, for the most part, for anyone who hasn't upgraded to the Anniversary Update, you can still follow along.
(What is Windows 10 Wi-Fi Sense? It is Windows 10 automatically sharing wireless network passwords with your friends. In the Anniversary Update, Wi-Fi Sense is used only to connect you to open Wi-Fi hotspots that it knows through crowdsourcing -- in other words, if you're near a publicly open Wi-Fi hotspot, you'll be automatically logged in.)
Surely, since Wi-Fi Sense is a configuration setting within the Windows operating system, the actual place for that setting and its status is stored is in the Registry. I Googled around for a couple of minutes and was able to find that, at least in the RTM build of Windows 10 (build number 10240 to be exact), the Registry setting for this feature was at:
```
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WcmSvc\wifinetworkmanager\config\
```
The actual setting is actually controlled by a DWORD value called, affectionately, AutoConnectAllowedOEM -- and to turn it off, we need to set its value to 0.
Now that the task has been laid out before us, it's time to get to work. From a PowerShell console, let's get into the PSDrive for the Registry.
```
Set-Location -path HKLM:
```
You can do a quick dir to make sure you're in the right spot. You can also notice that the PowerShell prompt changes to HKLM to reflect your current location. It's all good right now. Let's actually just go ahead and get further into the registry, all the way down to the location I identified above that I got from my Google research:
```
Set-location –path hklm:\ SOFTWARE\Microsoft\WcmSvc\wifinetworkmanager\config\
```
Let's do another quick dir to see what there is to see. From the report, do you see the value AutoConnectAllowedOEM that we need to create?
I don't, so that means we actually need to create the value. For this, we would use...
...yes, the New-Item
cmdlet. Here are a few ways we could go about this:
New-Item
alone at the command prompt with nothing else would prompt PowerShell to prompt us (that's a lot of prompting, folks!) for all of the required parameters.- We could use
Get-Help New-Item
to read about what we could do with this command. - We could also use
Show-Command new-item
in order to guide us graphically.
.
Use whichever of those combinations feels right to you. Either way, you should end up alongside me with the following command put together:
```
New-Item -path AutoConnectAllowedOEM -type DWORD -value 0
```
In the case of this specific New-Item
command, -Path is the name of the key that we want to create, since the path refers to the way to get to the object. We're creating a new DWORD object in the registry, so -type would be DWORD, and of course we know from our research that the -value of this new key would need to be 0.
Voila! You have successfully managed the Registry using nothing but PowerShell. But just think for a minute: Literally every configuration setting within the Windows operating system is managed through the Registry, so that means you just gained the skill to interact with and change Registry settings exclusively through scripting. More power to you!