《Windows Powershell 实战指南》第5章笔记

52次阅读

共计 5653 个字符,预计需要花费 15 分钟才能阅读完成。

第 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 不能隐式赋予,使用时必须写上参数名称。

正文完
 0