提供程序和驱动器
PowerShell系列好久没更新了,主要原因是懒有些主题涉及的内容太多了,一时间不知道怎么整理成文章发出来。近期刚好因为一点小问题又折腾了一下PowerShell,就顺便整理出这么一篇文章,介绍一下PowerShell中很重要的提供程序和驱动器。
提供程序(Provider)
Provider这个词在很多中文资料中被翻译为“提供程序”,刚开始学习PowerShell时看到这个词的我是这样子的:
要理解这个概念,其实只要读一读它的英文名就可以了。Provider,提供者,提供什么呢?在PowerShell中,Provider提供的是数据。它提供的数据可以是文件,也可以是环境变量,也可以是注册表信息。说到这里你可能还是有点懵(内心:这玩意儿到底嘎哈用的?),不过没关系,你只要记住它是提供数据的就行了,请继续往下读。
驱动器(Drive)
那驱动器又是什么?说到驱动器,大多数人首先会想到的应该是各种“CDEF盘”,不过PowerShell中的驱动器可没有那么简单。如果说提供程序提供了数据,那么驱动器就是提供了索引数据的方式,也可以说驱动器通过一个特定的提供程序连接到存储数据的介质。
举个例子:FileSystem是PowerShell一个内置的提供程序,它提供了文件系统相关的数据,而C盘就是属于FileSystem的一个驱动器,通过C:\path\to\file
的形式我们可以索引到提供程序提供的数据(文件或文件夹)。
PowerShell中的驱动器跟提供程序是多对一的关系,就像一个提供文件数据的提供程序可以对应多个文件系统驱动器(CDEF盘)一样。
项(Item)
仔细看看文件系统、注册表、环境变量等数据源的构成,我们能发现其实这些系统之间有很多相似之处:
- 它们都是树型结构
- 每一项数据都能对应一个路径,像文件路径和注册表项路径(这个特性是基于其树形结构的)
- 每一项数据都是由名字、内容和属性构成的
所以PowerShell又引入了另一个概念——项(Item)。PowerShell将提供程序提供的数据抽象为一个个的项(文件是项,文件夹是项,注册表项是项,环境变量也是项),将数据统一以项的形式表现。
PowerShell通过这种形式,将数据以一致的形式公开,这样我们可以以相同的方式对这些不同类型的数据进行管理了!试想一下,你可以用与修改文件内容相同的方式修改环境变量,是不是很有意思呢?
内置提供程序和驱动器
PowerShell内置了以下的提供程序和驱动器:
Provider | Drive | Data store |
---|---|---|
Alias | Alias: | cmdlet别名 |
Certificate | Cert: | 数字签名证书 |
Environment | Env: | 环境变量 |
FileSystem | * | 文件和文件夹 |
Function | Function: | PowerShell函数 |
Registry | HKLM:, HKCU: | 注册表,其中的两个驱动器HKLM:对应注册表的HKEY_LOCAL_MACHINE,HKCU:对应HKEY_CURRENT_USER |
Variable | Variable: | PowerShell中的变量 |
WSMan | WSMan: | WS-Management配置信息 |
使用这些内置的驱动器,就可以访问并管理提供程序提供的数据了:
PS > Set-Content Env:\Test test
PS > Get-Content Env:\Test
test
PS > Get-Content Variable:\PID
27631
注意路径中驱动器名字要加冒号(:),Windows上的路径分隔符是使用反斜杠(\)的。
相关cmdlet
获取Provider
Get-PSProvider [[-PSProvider] <String[]>] [<CommonParameters>]
使用Get-PSProvider
命令用于获取提供程序对象(System.Management.Automation.ProviderInfo)。参数-PSProvider
可以指定要获取的提供程序的名字,可以使用通配符,不指定时获取所有提供程序对象。
PS > Get-PSProvider e*, f*
Name Capabilities Drives
---- ------------ ------
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C}
Function ShouldProcess {Function}
使用Get-Member
可以获取到提供程序对象的属性和方法:
PS > Get-PSProvider | Get-Member
TypeName:System.Management.Automation.ProviderInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Capabilities Property System.Management.Automation.Provider.ProviderCapabilities Capabilit...
Description Property string Description {get;set;}
Drives Property System.Collections.ObjectModel.Collection[System.Management.Automati...
HelpFile Property string HelpFile {get;}
Home Property string Home {get;set;}
ImplementingType Property type ImplementingType {get;}
Module Property psmoduleinfo Module {get;}
ModuleName Property string ModuleName {get;}
Name Property string Name {get;}
PSSnapIn Property System.Management.Automation.PSSnapInInfo PSSnapIn {get;}
- Capabilities:提供程序支持的功能
- Credentials 表示允许使用可变更的凭据连接数据存储
- Filter 表示对项的操作支持-Filter参数
- ShouldProcess 表示对项的操作支持-WhatIf和-Confirm参数
- Transactions 表示支持事务
- Description:描述信息
- Drives:提供程序包含的驱动器对象
- HelpFile:帮助文件的路径
- Home:在相应驱动器中“~”号所对应的路径
- ImplementingType:具体实现的类
- PSSnapIn:提供该提供程序的组件
获取Drive
Get-PSDrive [-LiteralName|[-Name] <String[]>] [-PSProvider <String[]>] [-Scope <String>] [-UseTransaction] [<CommonParameters>]
使用Get-PSDrive
命令用于获取驱动器对象(System.Management.Automation.PSDriveInfo)。其参数列表如下:
-LiteralName
用于指定驱动器的名字,使用这个参数指定驱动器会忽略通配符-Name
也是用于指定驱动器名字的,不过使用这个参数时可以使用通配符,不指定驱动器名字时列出所有的驱动器-PSProvider
指定从哪些提供程序中获取驱动器,可以使用通配符-Scope
指定获取驱动器的范围,可选值有Global、Local(默认)、Script和相对当前范围的数字(0是当前范围,1是父级)-UseTransaction
将命令放入事务,这个参数只有在进行事务时才有作用
同样,我们使用Get-Member
看看驱动器对象中保存了哪些信息:
PS > Get-PSDrive | Get-Member
TypeName:System.Management.Automation.PSDriveInfo
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Management.Automation.PSDriveInfo d...
Equals Method bool Equals(System.Object obj), bool Equals(System.Manag...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Credential Property pscredential Credential {get;}
CurrentLocation Property string CurrentLocation {get;set;}
Description Property string Description {get;set;}
DisplayRoot Property string DisplayRoot {get;}
MaximumSize Property System.Nullable[long] MaximumSize {get;}
Name Property string Name {get;}
Provider Property System.Management.Automation.ProviderInfo Provider {get;}
Root Property string Root {get;}
Free ScriptProperty System.Object Free {get=## Ensure that this is a FileSys...
Used ScriptProperty System.Object Used {get=## Ensure that this is a FileSys...
- Credential:指定身份凭据,否则无法查看使用别的用户创建的驱动器
- CurrentLocation:记录当前位置,当从别的驱动器回到该驱动器时会跳转至这个位置
- Description:提供描述信息
- DisplayRoot:这个参数在内置驱动器中都为空,所以暂时不清楚作用,如果你知道它的作用,烦请联系博主
- MaximumSize:这个参数在内置驱动器中都为空,所以暂时不清楚作用,如果你知道它的作用,烦请联系博主
- Name:驱动器名字
- Provider:该驱动器属于哪个提供程序
- Root:根路径
- Free:可用空间(仅FileSystem)
- Used:已用空间(仅FileSystem)
新建Drive
New-PSDrive [-Name] <String> [-PSProvider] <String> [-Root] <String> [-Confirm] [-Credential <PSCredential>] [-Description <String>] [-Persist] [-Scope <String>] [-UseTransaction] [-WhatIf] [<CommonParameters>]
创建驱动器,关联到某个网络或者本地位置。这个命令创建的驱动器分为临时驱动器或者网络映射驱动器,网络映射驱动器可以保存到本地主机。
-Name
指定新驱动器的名字,对于网络映射驱动器,需要键入一个盘符,其它的可以使用任意名字-PSProvider
指定提供程序,临时驱动器可以关联任何提供程序,网络映射驱动器必须是FileSystem-Root
指定新驱动器的根路径,临时驱动器可以是任何路径,网络映射驱动器只能关联远程主机的文件路径(使用UNC路径)-Confirm
在运行cmdlet的时候显示确认操作的信息-Credential
指定一个有该命令执行权限的用户,默认是当前用户,输入一个用户名或者由Get-Credential
生成的PSCredential对象,-Root
参数是一个UNC路径时可以使用这个参数-Description
指定驱动器的描述信息-Persist
表示这个命令会创建一个网络映射驱动器,当没有使用点语法运行脚本时,驱动器不会保存到运行环境以外-Scope
指定驱动器的生效范围,可选值有Global、Local(默认)、Script和相对当前范围的数字(0是当前范围,1是父级)-UseTransaction
将命令放入事务,这个参数只有在进行事务时才有作用-WhatIf
显示调试信息,加入这个参数时不会实际创建驱动器
PS > New-PSDrive -Name me -PSProvider FileSystem -Root C:\Users\ganzi
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
me 0.00 62.58 FileSystem C:\Users\ganzi
移除Drive
Remove-PSDrive -LiteralName|[-Name] <String[]> [-Confirm] [-Force] [-PSProvider <String[]>] [-Scope <String>] [-UseTransaction] [-WhatIf] [<CommonParameters>]
该命令用于移除New-PSDrive
命令创建的临时驱动器,并且断开映射到网络驱动器的连接,该命令无法删除物理驱动器。
-LiteralName
用于指定驱动器的名字,使用这个参数指定驱动器会忽略通配符-Name
也是用于指定驱动器名字的,不过使用这个参数时可以使用通配符-Confirm
在运行cmdlet的时候显示确认操作的信息-Force
强制删除-PSProvider
指定从哪些提供程序中删除驱动器,可以使用通配符-Scope
指定驱动器删除的范围-UseTransaction
将命令放入事务,这个参数只有在进行事务时才有作用-WhatIf
显示调试信息,加入这个参数时不会实际删除驱动器
这个命令也可以通过管道输入PSDriveInfo对象:
PS > Remove-PSDrive -Name smp
PS > Get-PSDrive X, S | Remove-PSDrive
Tips
- 如果你需要其中某个提供程序的详细信息,只需要运行
Get-Help $ProviderName -Full
- 提供程序由管理单元(snap-in)提供,虽然无法删除提供程序,但是可以使用
Remove-PSSnapin
移除管理单元从而达到移除提供程序的效果 - 提供程序可以将参数动态添加到内置的cmdlet中,这些参数仅在cmdlet和提供程序数据一起使用时才可用,比如在Cert驱动器中使用
Get-Item
和Get-ChildItem
命令时可以使用-CodeSigningCert
参数 - 当一个新的驱动器接入电脑,PowerShell会自动向FileSystem提供程序添加一个驱动器对象而不需要重启,当驱动器断开连接后,PowerShell也会自动移除这个对象
关于注册表提供程序只有两个根节点,没有HKEY_CLASSES_ROOT等节点的问题,PSTips上有解释:
事实上HKEY_CLASSES_ROOT根节点不是一个独立的根节点,而是指向HKEY_LOCAL_MACHINE\SOFTWARE\Classes。
可以使用脚本将特殊文件夹加入虚拟驱动器:PowerShell 添加个性化驱动器
总结
PowerShell通过提供程序-驱动器-项的组合,对数据进行抽象,使得我们可以使用相同的方式管理来源不同,但是却有相似之处的数据。不得不说这种设计比同类其它产品先进许多,充分发挥了PowerShell面向对象的优势,不过这也使得学习成本变高不少。
下一篇计划讲讲关于PowerShell中项的操作,如果不出意外的话,我们一周后见!
参考资料
- PowerShell官方文档
- 《Windows PowerShell实战指南》
- PSTips
感谢以上内容的提供者!