代码改变世界

Windows PowerShell 2.0语言对象与对象类型

2010-11-15 01:22  @天行健中国元素  阅读(3059)  评论(3编辑  收藏  举报

PowerShell中遵循的一切都是对象,具有一些专属的特性,可以使用这些属性来区别它们。由于Windows和Unix/Linux之间有本质区别,因此在Windows中要实现强大的Shell外壳不能遵循Unix/Linux的技术路线。而用对象来操作Windows无疑是最好的选择,对象可以有不同的类型和原型,并且可以存储不同的数据。对象的首要的属性是其类型,类型包含对象支持的操作。对于.NET类,可以使用所有.NET对象支持的Type()方法来获取对象的类型,如下例所示:

PS C:\> (42).GetType()

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Int32                                    System.ValueType

PS C:\> "Hello World!".GetType()

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     String                                   System.Object

PS C:\> (1,2,3).GetType()

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

访问对象属性

一个对象类型包含对象成员,成员具有常用属性和方法,可以是输入域或事件。属性通常用来向外界展示对象的数据,数据通常存放在一个属性中,而这个属性又以一个对象的形式存在。可以使用如下符号来访问属性值:

PS C:\> $User=@{}

PS C:\> $User.Name="小胖"

PS C:\> $User.Name

小胖

上例创建一个新的字典对象并将其存储在$User变量中,然后将“小胖”这个字符串赋值给Name属性,最后一行取出属性值。

属性可以是只读或者可读写的,这取决于其值是否可以修改。如果为一个只读属性执行赋值操作,Shell外壳将会报错:

PS C:\> "Hello".length=7

"Length" is a ReadOnly property.

At line:1 char:9

+ "Hello". <<<< length=7

String对象是不可变对象,其属性length是字符串对象本身固有的属性,不能通过为其赋值来改变。

许多对象包含称为“索引值”的特殊属性,这种属性公开对象序列并允许通过一个名称或索引来访问,即通常使用的数组。例如:

PS C:\> $friuit="apples","banana","orange"

PS C:\> $friuit[0]

apples

PS C:\> $friuit[2]

Orange

数组下标从0开始编号,最大值为数组长度值-1。

使用对象方法

对象方法是描述对象支持操作的脚本块,通常携带参数并返回其他对象。如下例查找一个字符串中是否包含另外一个字符串:

PS C:\> "Hello".Contains("Hell")

True

方法也可不带参数,下例用ToUpper方法将字符串对象转换为大写:

<CENTER><ccid_nobr>

<table width="400" border="1" cellspacing="0" cellpadding="2"

bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">

<tr>

    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">

    <pre><ccid_code>

PS C:\> "lowercase Changecase Uppercase".ToUpper()

LOWERCASE CHANGECASE UPPERCASE

需要强调的是,不传递参数调用方法时不能省略后面的圆括号;否则PowerShell会认为是获得方法本身的对象,如下例所示:

PS C:\> "lowercase Changecase Uppercase".ToUpper

MemberType          : Method

OverloadDefinitions : {System.String ToUpper(), System.String ToUpper(CultureIn

                      fo culture)}

TypeNameOfValue     : System.Management.Automation.PSMethod

Value               : System.String ToUpper(), System.String ToUpper(CultureInf

                      o culture)

Name                : ToUpper

IsInstance          : True

上例获取方法本身的详细信息,通常情况下仅仅是想去调用该方法。

对象适配器

PowerShell允许使用多种应用程序的自动化对象、活动目录数据Active Directory Data、WMI,以及使用不同技术和原型实现的对象。这样需要一种机制来使得这些对象具有.NET对象那样的外观和工作方式,这种机制称为“对象适配”。对于内置对象,Shell知道如何与各种对象类型配合工作,这些数据会在一系列的适配器对象间传递;对于外部对象,Shell将其包裹在内部的.NET对象中作为的原始对象的视图出现。这种视图对象是PSObject,用适配器获取属性和方法。通常情况下PSObject仅仅作为一个原始对象,可以使用特殊的PSBase属性来获取一个原始对象,这样Shell可以使用一系列适配器操作对象。

(1)ManagementObjectAdapter

这个适配器针对WMI设计,使得操作WMI对象非常容易,如以对象属性的方式来遍历其属性集合:

PS C:\> (Get-WmiObject win32_process)[0].PSBase

.Properties["Caption"].Value

System Idle Process

上例使用PSBase属性获取原始的未经适配器处理的对象,通过适配器只需要如下简单代码:

PS C:\> (Get-WmiObject win32_process)[0].Caption

System Idle Process

(2)DirectoryEntryAdapter

这个适配器和Windows活动目录配合工作,工作方式与ManagementObjectAdapter相似。

(3)DataRowAdapter

这个适配器是关于ADO.NET DAataRow对象,可获取其行数据。例如Xml文件的内容如下:

<Users>

            <User>

                  <Name>John</Name>

                  <Age>25</Age>

            </User>

            <User>

                  <Name>Mike</Name>

                  <Age>20</Age>

            </User>

</Users>

则获取其中行数据的方法如下:

PS C:\> $ds=New-Object Data.DataSet

PS C:\> $ds.ReadXml("C:\PowerShell\data.xml")

InferSchema

PS C:\> $ds.Tables[0].Rows[0].Name

John

PS C:\> $ds.Tables[0].Rows[0].PSBase["Name"]

John

(4)DataRowViewAdapter

该适配器的工作方式与DataRowAdapter相似,它针对ADO.NET的DataRowView对象。

(5)XmlNodeAdapter

这是个非常重要的类型转换适配器,使对象和XML属性作为更容易操作的对象属性。.NET中XML的处理看起来太过复杂,使得用户不清楚一个值是作为XML的属性,还是作为一个元素值存在。而这个适配器将所有的值作为PowerShell代码的属性保存,下例读取XMI文件中的内容:

PS C:\> $xmlDoc= New-Object xml.XmlDocument

PS C:\> $xmlDoc.Load("c:\PowerShell\Data.xml")

PS C:\> $xmlDoc.Users.User[0]

Name                                    Age

----                                    ---

John                                    25

将内部元素以属性形式公开给外部并允许快速查询XML树,不需要通过XPath之类的重量级工具。

(6)ComAdapter

以往使用COM对象时必须处理编译类型信息并访问COM类库,而在PowerShell中的COM适配器可以实现这些功能并隐藏具体的细节。下例说明Internet Explorer COM对象在PowerShell中如何工作。

首先检查当前是否运行Internet Explorer浏览器进程:

PS C:\> Get-Process i*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

      0       0        0         16     0               0    Idle

可以看到未启动相关实例名为“iexplorer.exe”的进程,启动一个进程:

PS C:\> $ie=New-Object -Com InternetExplorer.Application

PS C:\> Get-Process i*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

      0       0        0         16     0               0 Idle

    265      11     9048      13308    85     0.36   1876 iexplore

PS C:\> $ie.Visible=$true

PS C:\> $ie.Visible=$false

PS C:\> Get-Process i*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

      0       0        0         16     0               0    Idle

    596      23    37636      45576   161     4.09   1876  iexplore

PS C:\> $ie.Visible=$true

PS C:\> $ie.Visible=$false

PS C:\> $ie.Application

Application          : System.__ComObject

Parent               : System.__ComObject

Container            :

Document             : System.__ComObject

TopLevelContainer    : True

Type                 : HTML 文档

Left                 : 774

Top                  : 500

Width                : 692

Height               : 457

LocationName         : 网易

LocationURL          : http://www.163.com/

Busy                 : False

Name                 : Windows Internet Explorer

HWND                 : 591414

FullName             : C:\Program Files\Internet Explorer\IEXPLORE.EXE

Path                 : C:\Program Files\Internet Explorer\

Visible              : False

StatusBar            : True

StatusText           : 完成

ToolBar              : 1

MenuBar              : True

FullScreen           : False

ReadyState           : 4

Offline              : False

Silent               : False

RegisterAsBrowser    : False

RegisterAsDropTarget : True

TheaterMode          : False

AddressBar           : True

Resizable            : True

注意在执行第1个语句时创建了IE进程,启动IE的同时会获得焦点,此时命令行已经失去焦点。在建立对象$ie时启动了一个IE的进程,只是这个进程在后台运行。语句$ie.Visible=$true显示界面,为了判断隐藏这个进程界面后再次显示的窗口是不是第1次启动时的窗口,使用这个IE浏览一个网站。加载网站之后,使用命令$ie.Visible=$false隐藏界面。查询进程可以看到进程仍然运行,用$ie.Application查看当前IE加载的文档信息。如果再次显示界面并关闭这个进程,再次使用$ie.Visible=$true操作对象,即可看到如下错误。这意味着在使用PowerShell的ComAdapter对COM对象进行操作时COM对象以RPC服务器的形式存在。而ComAdapter是服务的客户端,它向RPC服务器发出请求。服务器执行相应的操作并返回结果,整个过程对应针对COM对象应用的操作:

PS C:\> $ie.Visible=$true

Exception setting "Visible": "RPC 服务器不可用。 (异常来自 HRESULT:0x800706BA)"

At line:1 char:5

+ $ie. <<<< Visible=$true

类型扩展

对象适配器是改变对象表现方式的主要机制,但是其根源仍然是PowerShell。适配器作为.NET对象来执行,而且是PowerShell代码基础不可分割的组成部分。由于没有提供接口允许用户创建自己的适配器或在现有适配器之上扩展,因此PowerShell提供了一种机制用于修改对象类型。即对象扩展,使用户能够通过提供额外的代码和数据在运行时为对象和对象类型添加成员,包括属性和方法。如下代码获取System.Diagnostics.Process类型的扩展属性:

PS C:\> (Get-Process)[0] |Get-Member -type Aliasproperty

   TypeName: System.Diagnostics.Process

Name    MemberType    Definition

----    ----------    ----------

Handles AliasProperty Handles = Handlecount

Name    AliasProperty Name = ProcessName

NPM     AliasProperty NPM = NonpagedSystemMemorySize

PM      AliasProperty PM = PagedMemorySize

VM      AliasProperty VM = VirtualMemorySize

WS      AliasProperty WS = WorkingSet

这段代码获取所有进程中最高优先级的进程,并显示其别名属性。可以看到PowerShell扩展了Process类型,所以能够使用其中一些属性公开的较短名称,用Name来代替ProcessName;用WS来代替WorkingSet等。

别名属性仅仅是通过名称引用其他属性并返回该属性的值,属性别名化通常是用来缩短一些最常用的特性来使得对象用起来方便,如:

PS C:\> Get-Member -Input(1,2,3) -type AliasProperty

   TypeName: System.Object[]

Name  MemberType    Definition

----  ----------    ----------

Count AliasProperty Count = Length

能够通过访问PSExtended属性来访问类型对象视图,下例获取Process类型的所有扩展成员:

<CENTER><ccid_nobr>

<table width="400" border="1" cellspacing="0" cellpadding="2"

bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">

<tr>

    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">

    <pre><ccid_code>

PS C:\> (Get-Process)[0].PSExtended | Get-Member

   TypeName: System.Management.Automation.PSMemberSet

Name            MemberType     Definition

----            ----------     ----------

Handles         AliasProperty  Handles = Handlecount

Name            AliasProperty  Name = ProcessName

NPM             AliasProperty  NPM = NonpagedSystemMemorySize

PM              AliasProperty  PM = PagedMemorySize

VM              AliasProperty  VM = VirtualMemorySize

WS              AliasProperty  WS = WorkingSet

__NounName      NoteProperty   System.String __NounName=Process

PSConfiguration PropertySet    PSConfiguration {Name, Id, PriorityClass, Fil...

PSResources     PropertySet    PSResources {Name, Id, Handlecount, WorkingSe...

Company         ScriptProperty System.Object Company {get=$this.Mainmodule.F...

CPU             ScriptProperty System.Object CPU {get=$this.TotalProcessorTi...

Description     ScriptProperty System.Object Description {get=$this.Mainmodu...

FileVersion     ScriptProperty System.Object FileVersion {get=$this.Mainmodu...

Path            ScriptProperty System.Object Path {get=$this.Mainmodule.File...

Product         ScriptProperty System.Object Product {get=$this.Mainmodule.F...

ProductVersion  ScriptProperty System.Object ProductVersion {get=$this.Mainm...

总结

PowerShell作为强大且复杂的语言,并没有过于严格或对新手不友好。因为它把所有的对象类型通过适配器和扩展统一存取,所以用户能够找到快速入手的途径。本文分别针对PowerShell的对象属性,对象方法和对象适配器,以及对象类型扩展进行描述,最常用的对象是获取实体扩展,从而提高了脚本编写者的创造性,并降低了学习的难度。

微软MSDN原文地址:http://msdn.microsoft.com/zh-cn/ff943778.aspx

赛迪网原文地址:http://news.ccidnet.com/art/32857/20100608/2081057_1.html

作者: 付海军
出处:http://fuhj02.cnblogs.com
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu