Summary: Learn different ways to work with Windows PowerShell drives, including using WMI to find the root.
Hey, Scripting Guy! I have been trying to grasp this idea of Windows PowerShell drives. I am not certain how they are useful, or how I can find information about them. Can you help?
—BP
Hello BP,
Microsoft Scripting Guy Ed Wilson here. Of course, I can help. I wrote about PSDrives three weeks ago, so you may want to refer to that article for additional information about PSDrives.
The first thing to understand about PSDrives is that PSDrives are used as a way to abstract the complexity of accessing different types of information. As I mentioned yesterday, Windows PowerShell providers are used to perform the abstraction; PSDrives provide the way to interact with that data. The cool thing about Windows PowerShell providers is they do not need to be written by the Windows PowerShell team; using the software development kit (SDK), anyone can write their own Windows PowerShell provider and expose data sources to the Windows PowerShell user. For example, someone could write a Windows PowerShell provider for an XML document. You could then use Set-Location to the XML document drive, use Get-ChildItem, and return information from that document. The methodology mimics the same methodology used with the file system.
In my article about PSDrives from three weeks ago, I illustrate creating a new PSDrive that is centered on a particular folder. This makes it easier for me to work with all of my Hey, Scripting Guy! Blog posts.
Oh! By the way, I am rapidly approaching a major milestone on the Hey, Scripting Guy! Blog. To date, the Hey Scripting Guy! Blog has 1,049 posts written about VBScript; I only wrote a few of those articles. Most of those were written by the previous Scripting Guys. One of the first things I did when becoming the Microsoft Scripting Guy was shift the blog’s emphasis to Windows PowerShell. The Hey, Scripting Guy! Blog now has 1,004 posts about Windows PowerShell. I did not write all of those articles, because we have had 184 blog articles written by guest bloggers, including posts written by Honorary Scripting Guys. So after I write another 230 blog posts about Windows PowerShell, the blog will officially be weighted in favor of Windows PowerShell.
I am not limited to creating new PSDrives from the filesystem provider. I can create new drives that expose data from the other providers as well. For example, if I am interested in working with the registry, I might want a new PSDrive. The first thing to do is to see which registry drives are available. One way to find this information is to use the Get-PSDrive cmdlet, as shown here:
PS C:\> Get-PSDrive -PSProvider registry
Name Used (GB) Free (GB) Provider Root
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
The previous command reveals two registry drives: HKCU and HCLM. To create a new PSDrive, I use the New-PSDrive Windows PowerShell cmdlet. When using the New-PSDrive cmdlet, I need to specify the provider, the registry provider for this example, a name, and the root location for the drive. The command and associated output are shown here:
PS C:\> New-PSDrive -PSProvider registry -Name HKCR -Root HKEY_CLASSES_ROOT
Name Used (GB) Free (GB) Provider Rouot
HKCR Registry HKEY_CLASSES_ROOT
To use the drive, I can use it like any other drive. If I do not put a colon at the end of the drive name, an error is displayed. This is illustrated here:
PS C:\> Get-ChildItem HKCR
Get-ChildItem : Cannot find path 'C:\HKCR' because it does not exist.
At line:1 char:14
+ Get-ChildItem <<<< HKCR
+ CategoryInfo : ObjectNotFound: (C:\HKCR:String) [Get-ChildItem], ItemNotFoundExcept
ion
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
When I add the colon at the end of the drive name, the command works as shown here:
PS C:\> Get-ChildItem HKCR:
Hive: HKEY_CLASSES_ROOT
SKC VC Name Property
3 16 * {ContentViewModeLayoutPatternForBrowse, ContentViewModeFo...
1 2 .386 {(default), PerceivedType}
2 3 .3g2 {(default), PerceivedType, Content Type}
2 3 .3gp {(default), PerceivedType, Content Type}
<<OUTPUT TRUNCATED>>
I do not have to create a PSDrive at a root location. I can specify a different location. For example, I might want a PSDrive that exposes the HKEY_LOCAL_MACHINE\SOFTWARE hive. To do this, I use the New-PSDrive cmdlet, specify the registry provider, give it a name, and identify the root of the drive. The resultant command is shown here:
PS C:\> New-PSDrive -PSProvider registry -Name sw -Root HKLM:\SOFTWARE
Name Used (GB) Free (GB) Provider Root
Sw Registry HKEY_LOCAL_MACHINE\SOFTWARE
I can then change my working location to the new software drive, and use the Get-ChildItem cmdlet to explore the drive. These two commands are shown here:
PS C:\> Set-Location sw:
PS sw:\> Get-ChildItem
Hive: HKEY_LOCAL_MACHINE\SOFTWARE
SKC VC Name Property
0 1 7-Zip {Path}
1 0 Analog Devices {}
1 0 ATI Technologies {}
756 1 Classes {(default)}
8 0 Clients {}
1 1 CXT {IsDriverLoaded}
1 0 Hewlett-Packard {}
3 0 IBM {}
1 0 IM Providers {}
2 0 InstalledOptions {}
1 0 Intel {}
3 1 LENOVO {(default)}
198 0 Microsoft {}
3 0 MozillaPlugins {}
1 0 MSIT TPM Crypto Provider {}
1 0 nsoftware {}
4 1 NVIDIA Corporation {nvDelFiles}
2 0 ODBC {}
4 0 Policies {}
5 0 PowerPivot {}
0 16 RegisteredApplications {Windows Address Book, Paint, Windows Search,
1 0 Sonic {}
4 0 Synaptics {}
1 1 tdbg_trace {(default)}
35 1 Wow6432Node {(default)}
1 0 Xerox {}
Some companies, such as Microsoft, make extensive use of certificates. A PSDrive that is useful is to create one that exposes the my certificate store for the current user. In the following command, I use the certificate provider to create a new certificate drive named mycerts.
PS C:\> New-PSDrive -Name mycerts -PSProvider certificate -Root cert:\CurrentUser\My
Name Used (GB) Free (GB) Provider Root
Mycerts Certificate \CurrentUser\My
After I have the mycerts: drive, I can easily query the drive to find certificates that are going to expire in the next month:
PS C:\> Get-ChildItem mycerts: | where { $_.notafter -le "11/1/2011" } | select thumbprint, notafter
Thumbprint NotAfter
4D43DC0CDFE1FDF31857FFA03120ACF4DB5C3CE6 10/1/2011 2:01:33 PM
I do not have to use a specific location when creating a new PSDrive. For example, I can use an environmental variable if I want to. In the following example, I create a new PSDrive called tmp that points to the temp folder in my profile. To get at this location, I use the $env:temp variable:
PS C:\> New-PSDrive -Name tmp -PSProvider filesystem -Root $env:temp
Name Used (GB) Free (GB) Provider Root
Tmp 47.49 FileSystem C:\Users\edwils\AppData\Local\Temp
Well, if I can use an environmental variable when creating a new PSDrive, can I use a WMI query? In the following command, I use a WMI query to find the drive on my machine that has the greatest amount of free space. I then create a new PSDrive called data: that is located on that drive. This is a really cool way to have immediate access to the drive on your machine that has the greatest amount of free space. Here is the command:
PS C:\> New-PSDrive -Name data -PSProvider filesystem -Root (gwmi win32_logicaldisk | sort freespace
-Descending | select deviceID -First 1).deviceID
Name Used (GB) Free (GB) Provider Root CurrentLocation
Data 100.02 47.49 FileSystem C:\
After the drive is created, I can easily set my working location to that drive:
PS C:\> Set-Location data:
PS data:\>
By the way, the WMI query I used to find the drive with the most free space is shown here (it is useful in and of itself):
(gwmi win32_logicaldisk | sort freespace -Descending | select deviceID -First 1).deviceID
Well, BP, that is all there is to playing around with new PSDrives. Join me tomorrow when I will have a guest blog article written by Boe Prox. It is cool, and you will not want to miss it.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy