PSDrives and PSProviders - PowerShell management - PowerShell in Depth, Second Edition (2015)

PowerShell in Depth, Second Edition (2015)

Part 2. PowerShell management

Chapter 15. PSDrives and PSProviders

This chapter covers

· Understanding PSProviders

· Working with PSDrives

· Using transactional processing

When you add a module or a PSSnapin to PowerShell, you usually take this step because of the commands contained within those extensions. But extensions can also add something called a PSProvider to the shell, and those providers can be useful in ways many administrators haven’t realized are possible.

15.1. Why use PSProviders?

PSProviders, or providers for short, don’t immediately seem like a good idea for administration, but they are. To better understand what providers are, and what advantages they offer, you have to understand the other way of managing things in PowerShell: using commands.

Think about what developers at Microsoft have to do when they’re designing a set of commands. Take Active Directory as an example: First, they have to think of the nouns they’ll create. In other words, what kinds of things exist in Active Directory? These can include users, computers, contacts, printers, organizational units, and so forth. Once they have a list of the available nouns, they think of what they can do with those things, and that’s their list of verbs: create new ones, delete them, modify them, move them, and so on. Combine the two lists and you have the list of commands that you’ll need to create: New-ADUser, Set-ADUser, Remove-ADUser, and on and on.

That technique works fine when the list of things—that is, the nouns—can all be known in advance. Technically, in Active Directory you can’t ever know all the nouns in advance, because Active Directory can have its schema extended. You might, for example, add a class that represents a door, so that Active Directory can contain security information about your office building. There’s no way Microsoft could know about that in advance, and so you wouldn’t have commands for it, meaning you couldn’t manage it directly. It may be possible to manage through a generic command (*-ADObject). In reality, companies don’t like to extend their Active Directory schema that much, so the nouns Microsoft knows about—users, computers, and so forth—are likely the only ones you’ll ever have.

But take another example, like Internet Information Services (IIS). IIS isn’t only designed to be extensible; it almost insists on it! Some IIS machines have ASP.NET, whereas others have PHP. Some might have the URL Rewrite feature installed, whereas others might have that along with some advanced caching module. You never know in advance what might be installed.

That’s where a provider comes in handy. For anything that can be represented as a hierarchy, a provider can dynamically discover what’s available and give you a way of discovering it and manipulating it. A provider doesn’t need to know in advance what the nouns and verbs are. Unfortunately, that makes providers a bit trickier to use. Without knowing in advance what the nouns and verbs are, you’re stuck with a fairly generic set of commands that can manipulate almost anything a provider might see. Those commands have help files, of course, but the help is also generic, so it’s difficult to find practical examples that apply to a specific technology. The same sets of commands are used to manage IIS, SQL Server, WSMAN, and many other technologies.

That difficulty is one reason the IIS team didn’t commit 100% to a provider. They do know certain nouns in advance, because IIS will always contain things like websites, application pools, and so forth. Those are the things you’re most likely going to manipulate in PowerShell, so the IIS team created regular commands for them. The provider for IIS exists to handle everything else.

15.2. What are PSProviders?

A PSProvider is essentially an adapter that connects PowerShell to some external technology and that represents that external technology as a hierarchical data store. It makes external systems look like disk drives.

You can see a list of all currently loaded providers by running Get-PSProvider. Keep in mind that when you load a module or snap-in, it can also load additional providers, so it’s a good idea to periodically run Get-PSProvider and see what’s available to you.

Note

The Certificate and WSMan providers may not show when you use Get-PSProvider.

A good provider developer will always provide a help file for the provider, which is the one place they can offer nongeneric examples of how to use the provider. Most people don’t even realize that provider help exists, but if you run Help FileSystem, you’ll see an example of what provider help looks like. You use the normal Help command, along with the name of a provider (FileSystem, Registry, WSman, and so on) to learn how to use a provider.

In and of themselves, providers aren’t useful, because you can’t use them directly. Instead, they’re used to create PSDrives.

Note

Be aware that providers are designed for PowerShell. How they interact with the rest of the operating system varies. For example, changes you make using the Registry provider will be reflected in the operating system. But changes you make using the Environment provider affect only your current PowerShell session. If you change the value of an environment variable using the provider, it has no effect outside of PowerShell.

15.3. What are PSDrives?

A PSDrive is a provider in action. Keep in mind that a provider is an adapter that connects PowerShell to some external system; a PSDrive is an adapter being used to connect to a specific system.

PSDrives don’t have drive letters; instead, they have drive names. That’s because 26 letters wouldn’t be enough to handle all the drives PowerShell might have connected at any one time, and because names are a bit easier to remember than single letters.

By default, PowerShell maps a number of PSDrives, using some of its built-in adapters, every time it starts. When a module or snap-in includes a provider, it’ll usually map a PSDrive or two when the module or snap-in loads. To see a list of all currently available PSDrives, run Get-PSDrive:

PS C:\> Get-PSDrive

Name Used (GB) Free (GB) Provider Root

---- --------- --------- -------- ----

Alias Alias

C 64.47 167.39 FileSystem C:\

Cert Certificate \

Env Environment

Function Function

HKCU Registry HKEY_CURRENT_USER

HKLM Registry HKEY_LOCAL_MACHINE

Variable Variable

WSMan WSMan

The command will show you the drives, where they’re mapped to, which provider is handling the connection, and other information applicable to the individual drive. Your current location within the set of drives will also be shown.

Note

Your currently attached disk drives will still retain their letters and be visible as PowerShell PSDrives.

To create a new PSDrive, you run the New-PSDrive command. What you’ll normally want to do is change to an already-connected PSDrive that uses the same provider and then run the command. That’s because each provider can provide its own specific version of New-PSDrive. For example, the ActiveDirectory module included with Windows Server 2008 R2 and later provides a special version of New-PSDrive. If you need to connect a PSDrive to an Active Directory domain, you must do so while in the default AD: drive that’s created when you load theActiveDirectory module. Not all providers include a special version of New-PSDrive, but by changing to an existing drive that uses the provider, you’ll be assured of using any special version that might be in there. That specialized version, if one exists, will also include help that’s specific for how it works, so you’ll want to view the help from within an existing drive as well, for example:

PS C:\> Import-Module ActiveDirectory

PS C:\> Set-Location AD:

PS C:\> Help New-PSDrive

Note

You’ll usually see folks use the cd alias of Set-Location rather than using the full cmdlet name. You should also check the Push-Location and Pop-Location cmdlets if you aren’t familiar with their actions. These cmdlets have aliases of pushd and popd, respectively, and come in handy when you’re navigating around the shell, especially when changing between PSDrives from different providers.

15.4. Working with PSDrives

PowerShell includes about a dozen generic commands that are designed to work with the contents of a PSDrive. Many of these have aliases that correspond to old-school DOS or Cmd.exe commands, because the filesystem drives are some of the most commonly used PSDrives. The commands, and their most common aliases, are as follows:

· Clear-Item (cli)

· Copy-Item (copy, cpi, or cp)

· Get-ChildItem (dir, ls, or gci)

· Get-Item (gi)

· Invoke-Item (ii)

· Move-Item (move, mv, or mi)

· New-Item (ni)

· Remove-Item (erase, del, rd, ri, or rm)

· Rename-Item (rni or ren)

· Set-Item (si)

· Clear-ItemProperty (clp)

· Copy-ItemProperty (cpp)

· Get-ItemProperty (gp)

· Move-ItemProperty (mp)

· New-ItemProperty

· Rename-ItemProperty (rnp)

· Set-ItemProperty (sp)

As you can see from the command names, a PSDrive can contain two different generic kinds of object: an item and an item property. There are also the Set-Location command, which changes your location to a different PSDrive or within a PSDrive, and the Get-Location command, which displays the current location. Read Get-Help about_Core_commands and Get-Help about_providers for further information.

Note

The FileSystem provider is the one you tend to work with the most, and it’s also the one around which the provider and PSDrive terminology are based. We’ll focus on the filesystem for our main examples but also include examples using other providers so that you can see how the terminology and techniques carry over.

15.4.1. Filter, Include, and Exclude

One point that causes a lot of confusion is the use of the –Filter, -Include, and –Exclude parameters of the *Item cmdlets. Table 15.1 defines the parameters for Get-ChildItem.

Table 15.1. Definitions of the Exclude, Filter, and Include parameters

Parameter

Definition

-Exclude

Omits the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted.

-Filter

Specifies a filter in the provider’s format or language. The value of this parameter qualifies the Path parameter. The syntax of the filter, including the use of wildcards, depends on the provider. Filters are more efficient than other parameters, because the provider applies them when retrieving the objects, rather than having Windows PowerShell filter the objects after they’re retrieved.

-Include

Gets only the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted.

So, what does this mean in practice and how should you use these parameters? The first clue is in the definition of –Filter. Filters are the most efficient way to restrict the data because they’re applied as data is retrieved rather than PowerShell filtering the result set. As Don always says, “Filter early.” The –Filter parameter works like this:

PS C:\> Get-ChildItem -Path 'C:\MyData\PSHinDepth2E' -Filter *.txt

Directory: C:\MyData\PSHinDepth2E

Mode LastWriteTime Length Name

---- ------------- ------ ----

-a--- 16/12/2013 18:22 5371 pswa - Copy.ps1.txt

The filter modifies the –Path parameter. In effect it becomes:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*.txt'

Unfortunately, you can supply only a single filter. You can’t do this, for instance:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E' -Filter *.txt, *.docx

If you only want to work with a subset of the items, then –Filter is the recommended way because of its efficiency. At times you may need to use the –Include and –Exclude parameters.

The –Exclude parameter is the simplest in concept. It excludes any item that matches the value of the parameter. In the following example you get everything but files that have a .txt extension.

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E' -Exclude *.txt

Following that example, you may think to do this:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E' -Include *.txt

But you won’t get anything returned. This is a point about which we see many questions in the forums. If you want to use –Include, you need to do it like this:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*' -Include *.txt

The value supplied to –Path has to end in a wildcard so that everything in the folder is returned. PowerShell then filters the data using the value given in the –Include parameter. Not only is this more complicated to remember, it’s also slower, which is why we recommend using –Filter.

You can combine the parameters so these options will work:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*' -Include *.doc -Exclude A*

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*' -Filter *.doc -Exclude A*

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*' -Filter *.doc -Include X*

But don’t try:

Get-ChildItem -Path 'C:\MyData\PSHinDepth2E\*' -Filter *.doc -Include *.txt

15.4.2. Working with PSDrive items

In the filesystem, an “item” is either a folder or a file, because those are the only two things the filesystem can contain. When you’re using other providers, objects are presented as a hierarchy of files and folders, as if they were also a filesystem. But under the hood, that isn’t always the case.

Here’s a simple sequence of commands that creates a text file, renames it, creates a folder, and moves the file to that folder:

PS C:\> dir > directory.txt

PS C:\> ren directory.txt dir.txt

PS C:\> md files

Directory: C:\

Mode LastWriteTime Length Name

---- ------------- ------ ----

d---- 11/27/2013 11:00 AM files

PS C:\> move dir.txt files

If you’re paying close attention, you’ll see the use of md, which wasn’t included on the list of aliases we provided earlier. That’s because it isn’t an alias to a command—it’s an alias to a built-in function named Mkdir:

PS C:\> get-alias md

CommandType Name ModuleName

----------- ---- ----------

Alias md -> mkdir

PS C:\> get-content function:\mkdir

Tip

Try running Get-Content function:\mkdir. The output is long, but you’ll see that it’s a function that runs New-Item under the hood.

You don’t have to use Md or Mkdir to create new folders. Instead, you could run the New-Item command, which is what Mkdir is running under the hood:

PS C:\> New-Item -Type Directory -Name Test

Directory: C:\

Mode LastWriteTime Length Name

---- ------------- ------ ----

d---- 11/27/2013 11:05 AM Test

The Mkdir function takes care of adding the –Type Directory parameter so that you don’t have to type it.

If you have experience using older command-line shells, whether from MS-DOS or a Unix or Linux system, then working with items will be familiar to you. It’s true that the parameters of commands like Get-ChildItem (which you probably know as dir or ls) differ from the older commands that you’ve used in the past, but PowerShell’s help system can show you the new syntax any time you need a reminder.

Two things that can trip you up about the item-related commands are the –Path and –LiteralPath parameters that they all support. The –Path parameter is what’s used by default when you don’t specify a parameter name:

PS C:\> dir windows

That command is using the –Path parameter. That parameter accepts wildcards, meaning the ? character stands in for any single character, and the * character stands in for any one or more characters:

PS C:\> dir win*

That’s all well and good, and it’s what you’d normally expect to happen in the filesystem. In the Windows filesystem, neither ? nor * is legal in a file or folder name. They’re reserved, by the filesystem, as wildcard characters. You’d never have a file named D?n, but specifying that with one of the item commands would match Dan, Don, Dun, and so forth.

A problem arises when you remember that there are providers other than the FileSystem one, and in other data stores both ? and * are legal characters. For example, it’s completely legal to have a Registry key named “Modified?” or “Ex*tra.” But if you tried to use the normal –Pathparameter with those, you’d get “Modified?” along with “ModifiedA” and “ModifiedB,” because the –Path parameter always treats ? and * as wildcards. Therefore, you should use the –LiteralPath parameter, which treats ? and * as literal characters rather than as wildcards. You’ll need to use the –LiteralPath parameter any time a path contains ? or *, which might be the case in some of the nonfilesystem providers.

If you have access to a Windows Server 2008 R2 or later computer, and if it has IIS installed, try this:

PS C:\> import-module web*

PS C:\> cd iis:

PS IIS:\> dir

Name

----

AppPools

Sites

SslBindings

Here you load the WebAdministration module, which adds an IIS PSProvider and automatically uses that provider to map an IIS: PSDrive. You then change to that drive and list its top-level contents. As you can see, the IIS server has three top-level items: AppPools, Sites, and SslBindings.

A word about PSDrive names

This can be a bit tricky, so we want to call your attention to it. As we’ve mentioned, all PSDrives have a name, which is what you use to refer to them. Your computer probably has a C: drive, an HKCU drive, an HKLM drive, and so forth. The drive names do not include a colon at the end.

When you work with these drives, you’ll often see a colon after the name. For example, running cd hkcu doesn’t work, because PowerShell tries to treat the hkcu as the name of an item. Putting a colon after a drive name is a cue to the shell that this is a drive name. Running cd hkcu:will change you to the HKCU drive.

Normally, you’ll only use the colon when you’re including the drive name as part of a path, such as when you’re specifying a –Path or –LiteralPath parameter. If a command needs only the name of a drive—such as when you’re using New-PSDrive to connect a new drive—then you don’t use the colon.

From here, you can use cd to move around the drive and use dir to see its contents:

PS IIS:\> cd .\AppPools

PS IIS:\AppPools> dir

Name State Applications

---- ----- ------------

1af7c46fb0ee418db1735836 Started /Topology...

832e13c26dbd40e4a4a420a1 Started /b7a2fc705e6945ef90251b9dc2e59b0d...

Classic .NET AppPool Started

DefaultAppPool Started Default Web Site

SecurityTokenServiceAppl Started /SecurityTokenServiceApplicationPool...

SharePoint - 80 Started SharePoint - 80

SharePoint Central Admin Started SharePoint Central Administration v4...

SharePoint Web Services Stopped SharePoint Web Services Root

You’ll notice that the “directory listings” for different drives all look a bit different, depending on the provider in use. A directory listing for the C: drive, for example, won’t include “State” and “Applications” columns, because those make no sense in the filesystem. In the IIS provider, those columns do make sense. This is the most confusing part about working with providers and PSDrives. You have to remember that every data store you connect to works a bit differently. Although PowerShell does its best to make them all look like files and folders, under the hood they aren’t, and some differences are inevitable.

How useful are the providers in the real world?

One common question revolves around the usefulness of providers compared to using cmdlets. In certain cases, such as the Registry or certificate store, specific cmdlets aren’t available, so you have to use the provider or a scripting technique.

Richard decided to experiment with the AD provider to determine just how many common administrative tasks could be performed using the provider. The experiments grew into a comparison of scripting techniques, the Microsoft cmdlets, the Quest cmdlets, and the AD provider. Surprisingly, it was possible to perform practically all common AD administrative tasks through the provider (though some involved jumping through a few hoops).

The interested reader is directed to the Active Directory posts on Richard’s blog at http://blogs.msmvps.com/richardsiddaway/.

15.4.3. Working with item properties

In the filesystem, “items” are files and folders. These items all have properties, such as a file’s “Read Only” attribute. The item property commands, such as Get-ItemProperty and Set-ItemProperty, enable you to work with those properties:

PS C:\> Get-ItemProperty test.ps1 | Format-List *

PSPath : Microsoft.PowerShell.Core\FileSystem::C:\test.ps1

PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\

PSChildName : test.ps1

PSDrive : C

PSProvider : Microsoft.PowerShell.Core\FileSystem

VersionInfo : File: C:\test.ps1

InternalName:

OriginalFilename:

FileVersion:

FileDescription:

Product:

ProductVersion:

Debug: False

Patched: False

PreRelease: False

PrivateBuild: False

SpecialBuild: False

Language:

BaseName : test

Mode : -a---

Name : test.ps1

Length : 2518

DirectoryName : C:\

Directory : C:\

IsReadOnly : False

Exists : True

FullName : C:\test.ps1

Extension : .ps1

CreationTime : 11/1/2013 7:57:42 AM

CreationTimeUtc : 11/1/2013 2:57:42 PM

LastAccessTime : 11/1/2013 7:57:42 AM

LastAccessTimeUtc : 11/1/2013 2:57:42 PM

LastWriteTime : 11/26/2013 8:04:47 PM

LastWriteTimeUtc : 11/27/2013 4:04:47 AM

Attributes : Archive, NotContentIndexed

Obviously, the properties displayed will be different across different providers: Items in the Registry, for example, will have different properties than items in the filesystem. In fact, the Registry is a good example of where item properties get interesting. Take a look at figure 15.1, which shows Windows’ graphical Registry Editor. We’ve opened it to HKEY_CURRENT_USER\Software\Microsoft\Notepad.

Figure 15.1. Examining a Registry key using the graphical Registry Editor

Now let’s change to that same location using PowerShell:

PS C:\> cd hkcu:\software\microsoft\notepad

PS HKCU:\software\microsoft\notepad> dir

Wait, what? The directory listing is empty? Why wouldn’t the directory listing include those four Registry values—iWindowPosDX, iWindowPosDY, and so forth?

In PowerShell’s Registry provider, registry hives such as HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER are connected as PSDrives. Registry keys, such as Software, Microsoft, and Notepad, are presented as items. If you run Dir HKCU:\Software, you’ll get a listing of Registry keys under the Software key, because the dir alias points to Get-ChildItem, and because Registry keys are items.

But Registry values are presented as item properties, so they don’t show up when you run Dir. Instead, you have to switch to using the item property commands, such as Get-ItemProperty, or its alias, gp. Here’s what you need to do:

PS HKCU:\software\microsoft\notepad> cd ..

PS HKCU:\software\microsoft> gp notepad

iWindowPosX : 246

iWindowPosY : 64

iWindowPosDX : 1199

iWindowPosDY : 630

fWrap : 0

StatusBar : 0

lfEscapement : 0

lfOrientation : 0

lfWeight : 400

lfItalic : 0

lfUnderline : 0

lfStrikeOut : 0

lfCharSet : 0

lfOutPrecision : 3

lfClipPrecision : 2

lfQuality : 1

lfPitchAndFamily : 49

lfFaceName : Consolas

iPointSize : 160

szHeader :

szTrailer :

iMarginTop : 1000

iMarginBottom : 1000

iMarginLeft : 750

iMarginRight : 750

PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER

\Software\Microsoft\notepad

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER

\Software\Microsoft

PSChildName : notepad

PSDrive : HKCU

PSProvider : Microsoft.PowerShell.Core\Registry

First, you change up a level in the hierarchy so that the shell is focused on HKCU: \Software\Microsoft. Then, you ask the shell to display the item properties of the Notepad key. Essentially, the Notepad key looks like a file, and the settings (or values) underneath it look like properties of the file.

From this same point, you can start to make changes:

PS HKCU:\software\microsoft> Set-ItemProperty -Path Notepad -Name iWindowPosX

-Value 120

PS HKCU:\software\microsoft> gp notepad –name iWindow*

iWindowPosX : 120

iWindowPosY : 64

iWindowPosDX : 1199

iWindowPosDY : 630

PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSChildName : notepad

PSDrive : HKCU

PSProvider : Microsoft.PowerShell.Core\Registry

You change the iWindowPosX Registry setting to 120 and then redisplay the settings under Notepad to confirm your change. Presumably, the next time you open Notepad, its window will be in a slightly different position because of this change.

When you consider this technique for modifying the Registry, commands like New-ItemProperty should start making sense to you. It doesn’t make sense to add new properties to an actual file on the filesystem; the filesystem recognizes only the properties that it was designed to work with. In the Registry, though, item properties are the way Registry values are presented, and it absolutely makes sense that you’re able to create new ones, as well as delete old ones, copy them, and so on.

15.5. Transactional operations

One cool feature of some, but not all, providers is support for transactional operations. Running Get-PSProvider will reveal the providers that support this feature:

PS C:\> Get-PSProvider

Name Capabilities Drives

---- ------------ ------

Alias ShouldProcess {Alias}

Environment ShouldProcess {Env}

FileSystem Filter, ShouldProcess, Credentials {C, D, E, G...}

Function ShouldProcess {Function}

Registry ShouldProcess, Transactions {HKLM, HKCU}

Variable ShouldProcess {Variable}

Certificate ShouldProcess {Cert}

WSMan Credentials {WSMan}

You can see “Transactions” hiding at the end of the Registry provider’s Capabilities column. A transaction consists of a set of operations that you’ve queued up but that haven’t yet been implemented. As you add operations to the queue, PowerShell keeps track of them for you. When you’ve finished, you can either commit the entire batch or cancel the entire batch. The idea is to let you perform an entire set of tasks and ensure that either none of them completes or that all of them complete successfully. If an error crops up halfway through, you can cancel everything and start over.

Almost all of the item and item property commands include a –UseTransaction switch, which tells them to add something to the queue of an active transaction. To do that, you first have to start a transaction. Let’s walk through an example. We’ll start by evaluating the item properties of the HKCU:\Software\Microsoft\Notepad Registry key:

PS HKCU:\software\microsoft> get-itemproperty notepad

iWindowPosX : 120

iWindowPosY : 64

iWindowPosDX : 1199

iWindowPosDY : 630

fWrap : 0

...

Next, start a transaction, and then make two changes to the Registry. Notice that each change is using the –UseTransaction parameter:

PS HKCU:\software\microsoft> Start-Transaction

Suggestion [1,Transactions]: Once a transaction is started, only commands t

hat get called with the -UseTransaction flag become part of that transactio

n.

PS HKCU:\software\microsoft> Set-ItemProperty -Path Notepad

-Name iWindowPosX -Value 500 -UseTransaction

PS HKCU:\software\microsoft> Set-ItemProperty -Path Notepad

-Name iWindowPosY -Value 50 –UseTransaction

Now, take a look at the Registry values again to see if your changes took effect:

PS HKCU:\software\microsoft> get-itemproperty Notepad -Name iWindowPos*

iWindowPosX : 120

iWindowPosY : 64

iWindowPosDX : 1199

iWindowPosDY : 630

PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSChildName : notepad

PSDrive : HKCU

PSProvider : Microsoft.PowerShell.Core\Registry

The two changes seem to have been ignored. That’s because they haven’t happened, yet—they’re queued up in the transaction. If you want to see what the Registry would look like after the transaction, you have to tell Get-ItemProperty to take the transaction’s queue into account:

PS HKCU:\software\microsoft> get-itemproperty Notepad -Name iWindowPos*

-useTransaction

iWindowPosDX : 1199

iWindowPosDY : 630

iWindowPosX : 500

iWindowPosY : 50

PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSChildName : notepad

PSDrive : HKCU

PSProvider : Microsoft.PowerShell.Core\Registry

Ah, now you can see your changes. But they’re still not real: The transaction is pending. You can run Cancel-Transaction to abandon your changes and shut down the transaction or run Complete-Transaction to go ahead and apply the pending changes:

PS HKCU:\software\microsoft> Complete-Transaction

PS HKCU:\software\microsoft> get-itemproperty Notepad -Name iWindowPos*

iWindowPosX : 500

iWindowPosY : 50

iWindowPosDX : 1199

iWindowPosDY : 630

PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Sof...

PSChildName : notepad

PSDrive : HKCU

PSProvider : Microsoft.PowerShell.Core\Registry

With the transaction committed, Get-ItemProperty is able to show the finalized changes.

Note

Not every provider supports the use of transactions. Be sure to check a provider’s capabilities before you assume that it’ll support transactions. In PowerShell v3 and v4, of the base providers only the Registry provider supports transactions.

15.6. Every drive is different

Keep in mind that every drive in PowerShell can behave a bit differently, because every provider—and every underlying technology—works a bit differently. The basic commands that you’ll use for manipulating items and item properties can even change slightly—each provider is capable of providing its own specialized versions of these commands. A bit of experimentation—and the fact that each PSProvider should offer its own help file—can usually get you on the right path.

The provider in SQL Server 2008 (and R2) is a little unusual. PowerShell support in these versions of SQL Server is provided by a closed-shell version of PowerShell (SQLPS.exe) that includes the SQL Server provider and cmdlets but has some aspects of PowerShell removed. This means that you can’t add any other PowerShell functionality into it. But you can add the SQL Server components into a normal PowerShell session, which provides access to the full range of functionality. You can access SQLPS.exe by right-clicking an object such as a database in SQL Server Management Studio or by starting the executable (which isn’t on the Start menu by default).

Assuming you’ve started a PowerShell session with the SQL Server components loaded, you can use Get-PSDrive to discover that the SQL Server provider installs a SQLSERVER: drive, which you can access as any other drive:

PS C:\> cd sqlserver:

PS C:\> dir

Name Root Description

---- ---- -----------

SQL SQLSERVER:\SQL SQL Server Database Engine

SQLPolicy SQLSERVER:\SQLPolicy SQL Server Policy Management

SQLRegistration SQLSERVER:\SQLRegistration SQL Server Registrations

DataCollection SQLSERVER:\DataCollection SQL Server Data Collection

PowerShell and SQL Server deserve a book in their own right, so for now you’ll get a quick look at using the provider concentrating on the database engine. One important point is that the functionality to create databases or associated objects wasn’t implemented. You need to use PowerShell and Server Management Objects (SMO) to accomplish those tasks. You need to traverse a number of levels to get to the interesting bits:

cd sql\W08R2SQL08\default

The location you’re changing to breaks down as SQL (for the database engine as shown earlier) followed by the server name followed by the instance name. If you think this may allow you to access the provider on remote machines, you’re correct.

Within the instance are the objects you’d expect such as databases, logins, endpoints, and so forth. If you look at the databases

PS C:\> cd databases

PS C:\> Get-ChildItem | Get-Member

you’ll see that you’re dealing with an SMO object:

TypeName: Microsoft.SqlServer.Management.Smo.Database

The methods and properties of the objects can be accessed as with any other provider. One of the properties of a database is that it can be set to AutoClose—that is, it shuts down when the last user logs off. This setting is often used by inexperienced DBAs. It may sound like a good idea, but it means that your database won’t be available for the overnight backup! The setting can be easily tested (assuming you’re still in the databases container—if not, give the full path):

dir | select Name, AutoClose

Any databases that are incorrectly set can be quickly corrected. You might think to use this:

Set-ItemProperty -Path Test1 -Name Autoclose -Value $true

But unfortunately that functionality wasn’t enabled in this provider and you’ll get an error message. You can work in the provider—you need a little more effort:

Get-ChildItem |

where {$_.AutoClose} |

foreach {

$_.AutoClose = $false

$_.Alter()

}

This code sets the property to the desired value and then calls the Alter() method to save the change.

The SQL Server provider isn’t straightforward, but its ability to combine PowerShell and SMO in simple commands makes it hugely powerful. The ability to work through the provider with remote systems gives a large boost to productivity.

15.7. Summary

At first glance, providers can seem like an awkward, complicated way to perform management tasks. Because you’re using a generic set of cmdlets to manipulate items and item properties, and because items and item properties refer to different things in different providers, it can be difficult to get help and examples specific to the task you’re trying to accomplish. Sometimes, you might wish that there were commands for everything, instead of these crazy providers.

But providers offer what’s probably the best solution to a difficult problem: dynamic systems. Without knowing in advance what a system will look like, Microsoft and other developers can’t provide a concrete set of commands. A provider’s ability to adapt to dynamic situations, along with the provider’s model of using generic commands, is the most flexible way to address the situation. With a bit of practice, you’ll find that working with providers becomes as straightforward as working with regular commands.