《Windows Powershell 实战指南》第5章笔记
第5章 提供程序
1. 什么是提供程序
1.1 概念
提供程序(PSProvider):本质上是一个适配器。它可以像访问磁盘驱动器一样访问某些数据存储介质。
驱动程序(PSDrive):驱动程序可通过一个特定的提供程序去连接到某些存储数据的介质。
获取本机上的提供程序:
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, E, F} Function ShouldProcess {Function} Variable ShouldProcess {Variable}
通过Get-PSProvider的执行结果,观察提供程序和驱动程序两者的关系。如果用磁盘和分区来类比的话,提供程序就是一块磁盘,驱动程序就是这块磁盘上划分的几个分区。要想访问磁盘上的数据必须先进入某个分区,我们无法绕过分区直接打开或修改磁盘上的数据。
所以Registry、Alias、Environment等提供程序就是存储数据的底层介质,HKLM,、HKCU、Alias、Env等驱动程序就是上层的分区。而我们要想访问这些介质中的数据,必须先打开HKLM,、HKCU、Alias等驱动程序,就像打开C盘、D盘一样,下一步才能选择其中的文件和数据。
1.2 功能描述
从 Get-PSProvider的执行结果可以看出每个提供程序都有各自不同的功能。这一点很重要,因为这决定了我们如何使用这些提供程序。下面是常见的一些功能描述:
- ShouldProcess——表明该提供程序支持
-whatif
和-confirm
参数,保证我们正式执行这部分脚本之前可以对他们进行测试。 - Filter——表明在Cmdlet中操作提供程序的数据时,支持
-Filter
参数。 - Credentials——表明该提供程序允许使用可变更的凭据去连接数据存储。这也是
-Credentials
参数的作用。 - Transactions——表明该提供程序支持事务操作,也就是允许你在该提供程序中将过个变更作为一个原子操作进行提交或者全部回滚。
2. 文件系统的结构
2.1 文件系统
Windows文件系统主要由三种对象组成:磁盘驱动器、文件夹和文件。磁盘驱动器是最上层的对象,包含文件夹和文件。文件夹是一种容器对象,它可以包含文件以及其他文件夹。文件不是容器对象,它可以算作最小单位的对象。
2.2 Item的来源和操作命令
Powershell中的术语和文件系统中的略有不同。因为PSDrive 可能并不是指向某个文件系统——比如PSDrive可以映射到注册表,所以powershell并不会使用“文件”和“文件夹”的说法。相反,powershell采用更通俗的说法“项”(Item)。一个文件或者文件夹都叫项,尽管本质他们是不同的。所以powershell中操作对象的命令都包含“Item”字符。使用下列命令搜索包含“Item”的Cmdlet:
PS C:\> Get-Command -Noun *Item* CommandType Name Version Source ----------- ---- ------- ------ Function Get-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Function Get-TestDriveItem 3.4.0 Pester Function New-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Function Remove-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Function Rename-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Function Reset-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Function Set-DAEntryPointTableItem 1.0.0.0 DirectAccessClientComponents Cmdlet Add-ClusterVMMonitoredItem 2.0.0.0 FailoverClusters Cmdlet Clear-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Clear-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Copy-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Copy-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Get-ChildItem 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Get-ClusterVMMonitoredItem 2.0.0.0 FailoverClusters Cmdlet Get-ControlPanelItem 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Get-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Get-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Get-ItemPropertyValue 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Invoke-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Move-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Move-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet New-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet New-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Remove-ClusterVMMonitoredItem 2.0.0.0 FailoverClusters Cmdlet Remove-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Remove-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Rename-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Rename-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Set-Item 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Set-ItemProperty 3.1.0.0 Microsoft.PowerShell.Management Cmdlet Show-ControlPanelItem 3.1.0.0 Microsoft.PowerShell.Management
对上面的命令名称构成的一些解释:
- 比如Clear,Copy,Get,Move,New,Remove,Rename 和 Set 等动词可以应用于这些项(包括文件夹和文件)以及它们的属性(比如最后修改时间、只读等)。
- 名词部分只包括一个“Item”,可以应用于文件或文件夹的操作。
- 名词部分是“ItemProperty”,代表一个项对应的属性,比如只读、创建时间、大小等。
- 名词部分是“ChildItem”代表一个项(文件或文件夹)包含在另一个项中(文件夹)。
2.3 使用命令
上面的Cmdlet都是通用的,因为它们需要处理各种不同的数据源。但是需要注意的是,某些Cmdlet在特定场合下不一定能正常工作。就是说所有的提供程序都支持这些 Cmdlet 的使用,但是不支持部分参数的使用。从提供程序的功能描述部分(1.2节)中可以找到原因。
例如:文件系统不支持事务,所以在文件系统驱动器下使用命令时都不支持-UseTransaction
参数;注册表不支持 Filter 功能,所以在注册表驱动器中使用命令时,也不能使用-Filter
参数。
另外某些 PSProvider 并不具有对应的项属性。比如 Environment 提供程序主要的作用是访问Windows 中的环境变量,但它并没有任何项属性:
PS C:\> Get-ItemProperty -Path Env:\PSModulePath Get-ItemProperty : 无法使用接口。此提供程序不支持 IPropertyCmdletProvider 接口。 所在位置 行:1 字符: 1 + Get-ItemProperty -Path Env:\PSModulePath + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotImplemented: (:) [Get-ItemProperty], PSNotSupportedException + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.GetItemPropertyCommand
3. 使用文件系统
在使用提供程序时,首先需要熟悉的命令为 Set-Location。它的功能是将Shell中当前路径变更为不同的路径。使用 Set-Location命令进入不同的驱动程序,必须在驱动程序末尾加上:\
(这里使用斜杠效果也是一样的:/
),例如:
PS C:\> Set-Location d:\ PS D:\> Set-Location env:\ PS Env:\> Set-Location Function:\ PS Function:\> Set-Location HKCU:\ PS HKCU:\>
创建一个新的项的命令是 New-Item,由于该命令在所有提供程序中都能使用,所以使用时必须指定新项的类型,例如文件夹、文件或者注册表。例如:
PS C:\> New-Item -Name 123 -ItemType Directory 目录: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2019/4/2 22:28 123
4. 使用通配符以及绝对路径
大部分的 Cmdlet 都包含-Path
参数,默认情况下该参数支持通配符。例如我们查看 Get-ChildItem 的帮助文档中关于-Path
参数的部分:
PS C:\> help Get-ChildItem -Parameter path -Path <String[]> Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). 是否必需? False 位置? 0 默认值 Current directory 是否接受管道输入? True (ByPropertyName, ByValue) 是否接受通配符? True
*
通配符代码0个或多个字符,?
通配符仅代表单个字符。由于它们是通配符,所以在文件夹或文件的名称中不允许使用这两个字符。但是在其他类型的数据存储中,Item 的名称中是可以包含*
和?
的。例如注册表中的项名称就可以使用*
和?
,这就导致一个问题。当一个路径参数中使用了*
和?
powershell该如何识别,是作为通配符还是名称中的一个字符。针对该问题,powershell给出的解决办法是增加一个参数-LiteralPath
。
PS C:\> help Get-ChildItem -Parameter liter* -LiteralPath <String[]> Specifies, as a string arrya, a path to one or more locations. Unlike the Path parameter, the value of the LiteralPath parameter is used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences. 是否必需? True 位置? named 默认值 None 是否接受管道输入? True (ByPropertyName) 是否接受通配符? False
如果要查询的名称中带有*
和?
,就要使用-LiteralPath
参数,而不能使用-Path
。注意-LiteralPath
不能隐式赋予,使用时必须写上参数名称。