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://txj.shell.tor.hu