什么是提供程序
一个PowerShell的提供程序,或者说PSProvider,其本质上是一个适配器。它可以接受某些数据存储,并使得这些介质看起来像是磁盘驱动器一样。
大部分的其他软件程序包都存在提供程序,比如Internet Information Service(IIS)、SQL Server,甚至是活动目录。
可以通过Get-PSProvider
命令,查看当前Shell中已经存在的提供程序。
PS C:\> Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C, D, Z}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
# 使用环境提供程序,显示操作系统变量%TEMP%。
PS D:\(tmp> Get-Item env:temp
Name Value
---- -----
TEMP C:\Users\GUORUI~1\AppData\Local\Temp
我们可以通过模块或者管理单元将一些提供程序添加到PowerShell中,这也是PowerShell仅支持的两种扩展方式。有些时候,如果启用了某些PowerShell功能,可能也会新增一个PSProvider。
比如,当开启了远程管理时,会新增一个PSProvider。
# 开启远程管理
PS C:\Windows\system32> Enable-PSRemoting
WinRM 已更新为接收请求。
成功更改 WinRM 服务类型。
已启动 WinRM 服务。
PS C:\Windows\system32> Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C, D}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
WSMan Credentials {WSMan}
我们可以看出每个提供程序都有各自不同的功能。下面是常见的一些功能描述。
**ShouldProcess**
:这部分提供程序支持-WhatIf
和-Confirm
参数,保证我们在正式执行这部分脚本之前可以对它们进行测试。**Filter**
:在Cmdlet中操作提供程序的数据时,支持-Filter
参数。**Credentials**
:该提供程序允许使用可变更的凭据连接数据存储。这也就是-Credentials
参数的作用。**Transactions**
:该提供程序支持事务。
Name Used (GB) Free (GB) Provider Root
Alias Alias C 112.37 7.63 FileSystem C:\ Cert Certificate \ D 299.66 34.08 FileSystem D:\ Env Environment Function Function HKCU Registry HKEY_CURRENT_USER HKLM Registry HKEY_LOCAL_MACHINE Variable Variable WSMan WSMan Z 355.07 44.93 FileSystem \10.1.2.83\d
在上面返回的列表中,可以看到有3个驱动器使用了FileSystem提供程序,两个使用了Registry提供程序,等等。
PSProvider会适配对应的数据存储,通过PSDrive机制使得数据存储可被访问,然后可以使用一系列Cmdlets去查阅或者操作每个PSDrive呈现出来的数据。大多数情况下,操作PSDrive的cmdlet名词部分都会包含“Item”。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/635565/1653472582474-999951ba-92a1-489f-9a49-62cfb687679a.png#clientId=u1ef435a4-c76d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=586&id=u0eb45ab3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=645&originWidth=1675&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1219531&status=done&style=none&taskId=u5ccf893d-bb86-436b-8d2a-b77dd442840&title=&width=1522.7272397230486)
<a name="n19E6"></a>
## FileSystem的结构
Windows文件系统(以及macOS与Linux的文件系统)主要由3种对象组成:磁盘驱动器、文件夹和文件。磁盘驱动器是最上层的对象,包含文件夹和文件。文件夹是一种容器对象,它可以包含文件以及其他文件夹。<br />PowerShell中的术语和文件系统中的略有不同。PowerShell并不会使用“文件”以及“文件夹”的说法。
- PSDrive可能不是指向某个文件系统,比如PSDrive可以映射到注册表。
- PowerShell采用更通俗的说法:“项”(Item)。一个文件或者一个文件夹都叫作项。
每个项基本上都会存在对应的属性。比如,一个文件项可能有最后写入的时间、是否只读等属性。一些项,比如文件夹,可能包含子项(子项包含在文件夹项中)。
- Clear、Copy、Get、Move、New、Remove、Rename以及Set等动词可以应用于这些项(比如文件或者文件夹)以及它们对应的属性(比如该项最后写入的时间或者该项是否只读)。
- Item名词对应的是单独对象,比如文件或者文件夹。
- ItemProperty代表一个项对应的属性。比如只读、项创建时间、长度等。
- ChildItem名词对应一个项(比如文件或者子文件夹)包含于另外一个项(文件夹)中。
某些Cmdlet在某些特定场合下不一定能正常工作。
- 比如,**FileSystem提供程序不支持事务**,所以文件系统驱动器下的Cmdlet中的命令都不支持-UseTransaction参数。
- 再比如,**注册表不支持Filter功能**,所以注册表驱动器下的Cmdlet也都不支持-Filter参数。
某些PSProvider并不具有对应的项属性。比如,Environment这个PSProvider主要用来构造PowerShell中可用的ENV:类型驱动器(如Env:\PSModulePath)。该驱动器主要的作用是访问Windows中的环境变量,但是如下所示,它并没有对应的项属性。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/635565/1653473021206-1cd19e56-ed47-4d85-ae8f-984e259d8638.png#clientId=u1ef435a4-c76d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=244&id=ue62a1c69&margin=%5Bobject%20Object%5D&name=image.png&originHeight=268&originWidth=1556&originalType=binary&ratio=1&rotation=0&showTitle=false&size=400223&status=done&style=none&taskId=u5a9b284a-2cfe-4833-9756-f15de241fd3&title=&width=1414.5454238860082)<br />通过以上可知,即便Cmdlet知道如何实现某些功能,也并不意味着该提供程序真正支持对应的操作。
<a name="oRf4r"></a>
## 使用文件系统
在使用提供程序时,需要熟悉的另外一个Cmdlet是Set-Location(别名cd)。该参数的功能是将Shell中当前路径,变更为不同路径。比如变更到另一个文件夹下:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/635565/1653473254916-55e56594-ad57-4822-a7af-ef8d3d02d828.png#clientId=u1ef435a4-c76d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=67&id=uc0037528&margin=%5Bobject%20Object%5D&name=image.png&originHeight=83&originWidth=425&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7081&status=done&style=none&taskId=u724b527d-ac61-4d12-a760-ccaee2e803f&title=&width=341.3636169433594)
<a name="yEpHq"></a>
### New-Item
New-Item这个Cmdlet在很多地方都是通用的,它可以用来新建文件夹、文件、注册表项以及其他项,所以你必须告知你希望创建的类型是什么。
```powershell
# 创建一个目录
New-Item -Path "d:\" -Name "logfiles" -ItemType "directory"
# 在当前目录创建一个文件
New-Item -Path . -Name "testfile1.txt" -ItemType "file" -Value "This is a text string."
# 创建多个文件
New-Item -ItemType "file" -Path "c:\ps-test\test.txt", "c:\ps-test\Logs\test.log"
PowerShell中也包含MKDir命令。很多人都认为该命令是New-Item的别名,但使用MKDir并不需要输入类型。
内部实现上,Mkdir是一个函数,而并不是一个别名。但是实际上,它仍然调用了New-Item,只不过隐式赋予了-Type Directory这个参数。
通配符与路径
大部分项的Cmdlet都包含了-Path属性。默认情况下,该属性支持通配符输入。
Get-ChildItem
比如,我们查看Get-ChildItem
(别名Dir
)的完整帮助文档:
通配符:
- “*”:代表0个或者多个字符;
- “? ”:仅代表单个字符。
拓展:Get-ChildItem的-Filter、-Include和-Exclude参数之间有什么不同?
- 如果查询一个容器,Include与Exclude必须使用 –Recurse参数。
Filter使用了PS提供程序的过滤功能,并不是所有的提供程序都支持该参数。
- 例如,你可以在文件系统中使用
DIR –filter
,但无法在注册表中使用。 在注册表中,可以使用
DIR –include
命令实现过滤输出结果。 ```powershell PS C:\Users\guoruilong> Get-ChildItem -Path HKLM:\HARDWARE -Include EHive: HKEY_LOCAL_MACHINE\HARDWARE
- 例如,你可以在文件系统中使用
Name Property
DESCRIPTION DEVICEMAP UEFI RESOURCEMAP
<a name="KydWn"></a>
### 参数LiteralPath
在文件或者文件夹的名称中,不允许带有“*”或者“? ”字符。但在注册表中,你可以看到一些项的名称中包含“? ”字符。这将导致一个问题:当在一个路径中使用了“*”或者“? ”,PowerShell会如何对待,是作为一个通配符还是一个特定的字符?<br />针对此问题,PowerShell给出的解决办法是新增一个参数`-LiteralPath`。该参数并不支持通配符。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/635565/1653475189180-85e97a33-a753-487d-8af7-0091d26a5c51.png#clientId=u80b6ebdc-480f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=249&id=u6324a1c2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=303&originWidth=692&originalType=binary&ratio=1&rotation=0&showTitle=false&size=57410&status=done&style=none&taskId=ue5c16820-77d8-419d-8d42-6ce74be64cd&title=&width=569.0880737304688)<br />如果需要查询名字中带有*或者?,就要使用-LiteralPath参数,而不要使用-Path。需要注意的是,-LiteralPath这个参数不可隐式赋予,否则,将默认使用-Path参数。
<a name="dUnZi"></a>
## 使用其他提供程序 - 注册表
如果想对其他提供程序有个大致的认识,以及了解其他项的Cmdlet如何工作,最好的办法就是去尝试一下非文件系统格式的PSDrive。在PowerShell内置的提供程序中,注册表应该算是比较好的一个示例。
```powershell
PS C:\> Set-Location -Path HKCU: # 切换到HKEY_CURRENT_USER
PS HKCU:\> Set-Location -Path SOFTWARE
PS HKCU:\SOFTWARE> Get-ChildItem
PS HKCU:\> cd .\SOFTWARE\Microsoft\Windows\
PS HKCU:\SOFTWARE\Microsoft\Windows\> dir
Hive: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows
Name Property
---- --------
AssignedAccessConfiguration
CurrentVersion
DWM Composition : 1
ColorizationColor : 3288365271
ColorizationColorBalance : 89
ColorizationAfterglow : 3288365271
ColorizationAfterglowBalance : 10
ColorizationBlurBalance : 1
EnableWindowColorization : 0
ColorizationGlassAttribute : 1
AccentColor : 4292311040
ColorPrevalence : 0
EnableAeroPeek : 1
AlwaysHibernateThumbnails : 0
在该列表中可以看到EnableWindowColorization
的键值,现在将它修改为1。
# 可以使用-Name参数,代替-PSProperty参数。
PS HKCU:\SOFTWARE\Microsoft\Windows\> Set-ItemProperty -Path dwm -PSProperty EnableWindowColorization 1
PS HKCU:\SOFTWARE\Microsoft\Windows\> dir
Hive: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows
Name Property
---- --------
AssignedAccessConfiguration
CurrentVersion
DWM Composition : 1
ColorizationColor : 3288365271
ColorizationColorBalance : 89
ColorizationAfterglow : 3288365271
ColorizationAfterglowBalance : 10
ColorizationBlurBalance : 1
EnableWindowColorization : 1
ColorizationGlassAttribute : 1
AccentColor : 4292311040
ColorPrevalence : 0
EnableAeroPeek : 1
AlwaysHibernateThumbnails : 0
采用这种方法,可以处理其他提供程序类似的问题。