代码改变世界

Windows PowerShell 2.0开发语言之提供程序

2010-11-28 01:46  @天行健中国元素  阅读(2036)  评论(0编辑  收藏  举报

在PowerShell中不存在文件和目录的概念,涉及文件和目录的操作总是转换为项(item)处理,即Get-Item、Get-ChildItem和Get-ItemProperty。在PowerShell中的dir命令以Get-ChildItem的别名出现,通过项操作对象的原因是PowerShell作用的任何类型的对象均以项的形式存在。而不像类Unix系统中将所有的对象都抽象成文件,即使这个对象很明显不是文件的情况。

项是包含内容的属性对象,这些对象又可以包含其他项。这个定义可以很容易扩展到文件和目录,即它们是具有各自内容和属性的项。项的概念可以应用于多个系统对象,提供程序(provider)用来创建、找回、修改和移除项。它是官方提供的重要的Shell扩展机制之一,Shell与一些内置的提供程序一起发布给用户,其中提供了提供程序的接口。

1 列举提供程序

键入Get-PSProvider命令列出所有提供程序的清单:

PS C:\> Get-PSProvider

Name                 Capabilities                                      Drives
----                 ------------                                      ------
WSMan                Credentials                                       {}
Alias                ShouldProcess                                     {Alias}
Environment          ShouldProcess                                     {Env}
FileSystem           Filter, ShouldProcess                             {C, D, A, E}
Function             ShouldProcess                                     {Function}
Registry             ShouldProcess, Transactions                       {HKLM, HKCU}
Variable             ShouldProcess                                     {Variable}
Certificate          ShouldProcess                                     {cert}

每个提供程序被挂接了类似文件系统(FileSystem)的驱动器,其中只有文件系统提供程序指向实际的文件。提供程序会由包含它们的管理单元自动注册。下例获取所有提供程序管理单元的名称和.NET类型:

PS C:\> Get-PSProvider | select Name,PSSnapIn,ImplementingType | fl

Name             : WSMan
PSSnapIn         : Microsoft.WSMan.Management
ImplementingType : Microsoft.WSMan.Management.WSManConfigProvider

Name             : Alias
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.AliasProvider

Name             : Environment
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.EnvironmentProvider

Name             : FileSystem
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.FileSystemProvider

Name             : Function
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.FunctionProvider

Name             : Registry
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.RegistryProvider

Name             : Variable
PSSnapIn         : Microsoft.PowerShell.Core
ImplementingType : Microsoft.PowerShell.Commands.VariableProvider

Name             : Certificate
PSSnapIn         : Microsoft.PowerShell.Security
ImplementingType : Microsoft.PowerShell.Commands.CertificateProvider

除了Certificate提供程序以外,其他所有提供程序都保存在Microsoft.PowerShell.Core管理单元中。

在理想状况下,可以以操作注册键值的方式操作文件。然而基本的存储类型存在局限,这就意味着并不是所有的提供程序都能做到这一点。因此PowerShell引入了提供程序能力的概念,即允许提供程序定义其支持的操作。提供程序支持的能力如下。

(1)Credentials:用户通过命令行访问信任体系的能力。

(2)ExpandWildCards:执行时能够展开包含通配符路径的能力。

(3)Include:包括基于通配符串的项的能力。

(4)Exclude:与Include类似,但排除通配符指向的项的能力。

(5)Filter:根据提供程序指定的字符串增加过滤器项的能力。

(6)None:显式指定提供程序没有附加的能力,恢复继承自基于特定类的提供程序的能力。

(7)ShouldProcess:在调用ShouldProcess方法修改数据前保存,从而允许用户使用-WhatIf和-Confirm参数,在数据修改之前预览或手动确认的能力。

2 驱动器

获取项通过驱动器实现,与Windows驱动器类似,PowerShell中的驱动器表示方法是标识符后加冒号,如C:或D:;不同的是存在长标识符,如Env、cert:,以及HKCU:。可以使用Get-PSDrive命令获取当前在系统中注册的驱动器:

PS C:\> Get-PSDrive

Name       Provider      Root
----       --------      ----
A          FileSystem    A:\
Alias      Alias
C          FileSystem    C:\
cert       Certificate   \
D          FileSystem    D:\
E          FileSystem    E:\
Env        Environment
Function   Function
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
Variable   Variable

每个驱动器都有一个根位置,并跟踪当前位置是否被修改。可以创建新的驱动器,并指向特定的路径,这样可以用很短的路径访问文件系统。下例创建docs:驱动器,并将其指向文档目录:

PS C:\> New-PSDrive -name docs -PSProvider FileSystem `
>> -Root C:\Users\Administrator\Documents
>>

Name       Provider      Root
----       --------      ----
docs       FileSystem    C:\Users\Administrator\Documents

然后即可用创建的驱动器定位目标位置:

PS C:\> cd docs:
PS docs:\> dir
    Directory: C:\Users\Administrator\Documents

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         2009/2/22     16:06            MyVirtualMachines
d----         2009/2/22     16:06            Visual Studio 2005
d----         2009/2/22     16:07            WindowsPowerShell
-a---         2009/2/22     16:04          0 –Root
PS docs:\> c:
PS C:\> docs:
The term 'docs:' is not recognized as a cmdlet, 
function, operable program, or script file. Verify the term and try aga
in.
At line:1 char:6
+ docs: <<<<
    + CategoryInfo          : ObjectNotFound:
 (docs::String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

创建的驱动器和系统本身内置的驱动器不同,后者使用“内置驱动器名:回车”的方式定位;前者使用“cd 自创建驱动器名:回车”的方式访问。即内置驱动器名以在系统中注册过的别名形式存在,创建的驱动器需要从当前变量中查询。

另外驱动器并不是完全透明的,即使命令行当前在驱动器docs:中,目录路径仍然指向原始位置C:\Users\Administrator\Documents。PowerShell支持网络共享,用户可以映射网络共享为本地驱动器,操作时只需要将完整的网络共享路径作为驱动器的根位置即可。下例将网络共享\\FileServer\Public映射为本地的net:驱动器:

PS C:\> New-PSDrive -name net -PSProvider FileSystem `
>> -Root \\FileServer\Public
>>

Name       Provider      Root
----       --------      ----
docs       FileSystem    \\FileServer\Public
PS C:\> cd net:
PS docs:\> dir

    Directory: \\FileServer\Public s

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         2009/2/22     16:06            CodeBackup
d----         2009/2/22     16:06            InstallFile
d----         2009/2/22     16:07            PowerShell
-a---         2009/2/22     16:04          0 –Root

可以使用Remove-PSDrive移除映射的驱动器,但是其所在路径不能被占用;否则出错。使用Remove-PSDrive时,其后的参数是要移除的驱动器名(不带冒号),如:

PS docs:\> Remove-PSDrive docs
Remove-PSDrive : Cannot remove drive 'docs' because it is in use.
At line:1 char:15
+ Remove-PSDrive <<<<  docs
    + CategoryInfo          : InvalidOperation: (:) [Remove-PSDrive], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,
Microsoft.PowerShell.Commands.
RemovePSDriveCommand
PS docs:\> Remove-PSDrive docs:
Remove-PSDrive : Cannot find drive. 
A drive with name 'docs:' does not exist.
At line:1 char:15
+ Remove-PSDrive <<<<  docs:
    + CategoryInfo          : ObjectNotFound: 
(docs::String) [Remove-PSDrive], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.RemovePSDriveCommand
PS docs:\> cd C:
PS C:\> Remove-PSDrive docs
PS C:\>

在Remove-PSDrive命令中使用-F参数在驱动器被占用的情况下也可以强制移除,但这种操作并不是推荐的,因为在共享目录占用情况下操作会产生共享冲突。在驱动器被占用情况下强制删除的实例代码如下:

PS docs:\> Remove-PSDrive -F docs
PS docs:\> c:
PS C:\> cd docs:
Set-Location : Cannot find drive. 
A drive with name 'docs' does not exist.
At line:1 char:3
+ cd <<<<  docs:
    + CategoryInfo          
: ObjectNotFound: (docs:String) 
[Set-Location], DriveNotFoundException
    + FullyQualifiedErrorId : 
DriveNotFound,Microsoft.
PowerShell.Commands.
SetLocationCommand

2.1 驱动器作用域

驱动器遵循作用域规则与变量作用域类似,在函数或脚本块中定义的驱动器将会屏蔽在此之前定义的同名全局驱动器;在函数或脚本块之外,全局变量将有效。下例中的函数映射驱动器并返回项的根目录:

PS C:\> function Get-Documents()
>> {
>>     New-PSDrive -name docs -PSProvider FileSystem `
>>         -root C:\Users\Administrator\Documents
>>     return (Get-Item docs:\)
>> }
>>
PS C:\> Get-Documents

Name       Provider      Root            CurrentLocation
----       --------      ----                 ---------------
docs       FileSystem    C:\Users\Administrator\Documents

PSPath            : Microsoft.PowerShell.Core\FileSystem::
C:\Users\Administrator\Documents\
PSParentPath      :
PSChildName       : Documents
PSDrive           : docs
……
BaseName          : Documents
Mode              : d-r--

PS C:\> cd docs:
Set-Location : Cannot find drive.
 A drive with name 'docs' does not exist.
At line:1 char:3
+ cd <<<<  docs:
    + CategoryInfo          
: ObjectNotFound: (docs:String) 
[Set-Location], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.
Commands.SetLocationCommand

上例中只能在函数内部使用docs:驱动器,在函数外部尝试访问驱动器得到错误信息,说明此时docs:已经无效。

2.2 浏览驱动器

在cmd下的cd命令用来切换到当前驱动器的目录,如:

C:\ >cd d:\
C:\>
C:\>cd D:\temp
C:\>D:
D:\>

在cmd.exe中为每个驱动器保存当前目录,在当前盘符下切换其他盘符的当前目录没有效果。如果切换到目标盘符下,则显示该盘符最后一次设置的当前目录。如当前盘符是C:,用cd命令切换当前目录到D:\temp并没有定位到个目录。但当切换当前驱动器为D:时,当前目录切换为D:\temp。

在PowerShell中不存在每个盘符该包括当前目录的情况,这里只有一个当前位置并应用于所有驱动器。这就意味着可以使用cd命令来切换驱动器,而该命令作为Set-Location这个cmdlet的别名出现。下例说明PowerShell中的目录切换:

PS C:\> Get-Location
Path
----
C:\
PS C:\> Set-Location D:\temp
PS D:\temp>
PS D:\temp> Alias cd

CommandType     Name                       Definition
-----------     ----                              ----------
Alias           cd                               Set-Location

C:和D:这类命令并不是内置命令,而只是函数名。在PowerShell中默认会定义26个字母用于切换到相应的驱动器。下例获取这些驱动器:

PS C:\> Get-Command [A-Z]:

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        A:                                                  Set-Location A:
Function        B:                                                  Set-Location B:
……
Function        Y:                                                  Set-Location Y:
Function        Z:                                                  Set-Location Z:

可以看到这些函数调用Set-Location来定位目标驱动器。

3 提供程序的能力

不同的提供程序会有不同的能力,并且根据其所继承的基类来执行。

3.1 基本提供能力

最小化的提供程序为初始化一个Shell进程并注册它。

3.2 驱动器提供程序

可以具有注册和反注册新驱动器能力的提供程序支持New-PSDrive和Remove-PSDrive两个cmdlet。

3.3 项目提供程序

项提供程序支持如下cmdlet。

(1)Clear-Item:用来清除项内容并用空值类替换,这个空值是提供程序所特有的。操作文件时是个空值,操作注册表时是个空值和子项,操作变量时是$null。

(2)Get-Item:获取指定项目的引用。

(3)Invoke-Item:为指定路径的项调用默认操作,能够执行文件作为或用关联程序打开。

(4)Set-Item:为项设置新值,是提供程序特定的,包括修改文件的内容、设置新的变量值,以及为注册表键值设置默认值。

(5)Resolve-Path:展开通配符并且返回复合通配符表达式的路径。

(6)Test-Path:校验某个路径是否存在,存在,返回$true;否则返回$false。

注册驱动器并操作项是提供程序所必备的功能。

3.4 项容器提供程序

项容器提供程序能够操作不同等级的项并返回包含其他项的项,支持如下cmdlet。

(1)Copy-Item:从父路径复制项到目标路径。

(2)Get-ChildItem:获取指定路径的所有子项,这是文件系统提供程序dir命令的真实内容,dir是其别名。环境、变量、函数和别名提供程序会以特殊方式调用这个功能,当用户请求其子项时,返回指定路径的项。

(3)New-Item:在指定位置创建项并在需要时为其赋初值。如果项已经存在,即可使用-Force参数来重新创建。

(4)Remove-Item:删除指定位置的项,在PowerShell中del是其别名。

(5)Rename-Item:重命名指定位置的项。

所有内置的提供程序都是项容器提供程序,其中一部分并不是分等级结构。

3.5 导航提供程序

导航提供程序支持调用多个项容器的复杂操作,并且支持以下cmdlet。

(1)Join-Path:将两个路径拼接成一个路径并访问,如果路径不存在,则抛出错误。

(2)Move-Item:将项从当前位置移到指定位置。

这些内置的提供程序只针对文件系统、注册表和证书系统。如果尝试对其他提供程序中注册的驱动器执上述cmdlet会引发错误。下例为移动别名时出现的错误:

PS C:\> Move-Item Alias:\dir Alias:\dir2
Move-Item : Cannot retrieve the dynamic parameters for the cmdlet.
 The Navigati
onCmdletProvider methods are not supported by this provider.
At line:1 char:10
+ Move-Item <<<<  Alias:\dir Alias:\dir2

3.6 项内容提供程序

项内容提供程序支持获取项内容的操作,如修改、添加及清空等,它支持如下cmdlet。

(1)Add-Content:为指定项添加值。

(2)Clear-Content:把项内容设置为空,空值是提供程序特定的。

(3)Get-Content:找回特定项的内容。

(4)Set-Content:设置特定项的内容,同时销毁所有旧值。

除了注册表和证书提供程序外,几乎所有内置的提供程序都是项内容提供程序。

3.7 项属性提供程序

项属性提供程序允许项取回和修改属性,它支持如下cmdlet。

(1)Clear-ItemProperty:删除项的属性值,并赋予提供程序所指定的空值,属性本身不会被删除。

(2)Get-ItemProperty:取回项的属性值。

(3)Set-ItemProperty:为指定的项属性设置新值。

除了文件和注册表和提供程序支持项属性以外,其他提供程序均不支持。

3.8 动态项提供程序

动态项提供程序能够在运行时动态添加、移除、复制和移动属性,它支持如下cmdlet。

(1)Copy-ItemProperty;在项之间复制属性和值。

(2)Move-ItemProperty;在项之间移动属性和值。

(3)New-ItemProperty;为指定项创建新属性。

(4)Remove-ItemProperty;为指定项移除属性。

(5)Rename-ItemProperty;重命名项属性。

动态项属性比较特殊,只有文件系统和注册表提供程序支持项属性提供的能力。即只有与注册表相关的提供程序能够创建、移除、复制和移除注册表键值。

3.9 项安全描述提供程序

有些提供程序允许为项设置安全描述符或控制列表,因而可以防止未授权的访问,这些项可以是文件或其他操作系统对象。这些提供程序支持以下两个cmdlet。

(1)Get-Acl:获取指定位置项的访问控制列表(Access Control List,ACL)。

(2)Set-Acl:为指定位置的项设置新的ACL。

只有文件系统和注册表提供程序支持这个功能。

4 总 结

本文着重介绍了提供程序是与外界交互的所有对象类型的抽象机制,本章首先介绍了注册和使用新创建的驱动器,以使路径便于记忆和访问。然后介绍了内置的提供程序及其功能,并且分类介绍了哪些cmdlet可以应用在指定提供程序的项上,对相关的提供程序进行描述。提供程序是用来创建、找回、修改和移除项。它是官方提供的重要的Shell扩展机制之一,Shell与一些内置的提供程序一起发布给用户,其中提供了提供程序的接口。

赛迪网地址:http://tech.ccidnet.com/art/32963/20100630/2101775_1.html

作者: 付海军
出处:http://fuhj02.cnblogs.com
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu/
参与“2010年度中国十大杰出IT博客”评选,请大家帮忙投票,谢谢!http://2010blog.51cto.com/274616/