术语
PowerShell中关于对象的4个术语:
- 对象:即“表行”。它代表单个事物,比如说单个进程或是单个服务。
- 属性:即“表列”。它代表关于对象的一部分信息,比如说进程名称、进程ID或服务状态。
- 方法:即“行为”。方法与某个对象关联并使得对象完成某些任务,比如说杀死进程或启动服务。
- 集合:这是整个对象的集合,我们曾称之为“表”。
使用对象的原因
第一个原因是Windows本身就是一个面向对象的操作系统。
另一个使用对象的原因是这样会使事情简单,并给你提供更加强大的功能和更好的灵活性。
当你运行类似Get-Process的命令时,你将会得到格式化好的文本作为输出结果。
PowerShell使用对象消除所有的文本操作开销。由于对象的工作机制类似内存中的表,因此你无须告知PowerShell信息所在的文本位置,而是仅仅需要输入列名。
Windows并不是基于文本,而是基于API的操作系统,Windows重度依赖对象模型。因此PowerShell以更原生的方式与Windows共同工作。
探索对象:Get-Member
如果说对象就像内存中一个巨大的表,而PowerShell仅仅在屏幕上展示表的一部分,那么如何看到其他你需要使用的属性呢?
可以在任何产生某些输出的命令之后,使用Get-Member
(别名Gm):
- 注意:若管道无结果输入,则gm也不会产生结果。
请注意Get-Member输出结果的第一行。这一行是TypeName,是分配给特定类型对象的唯一名称。
当一个Cmdlet产生一个对象的集合时,整个集合直到管道末尾之前都可以被访问。因此,上面的Gm可以完整访问进程对象的属性和方法,这是由于该命令还未被过滤用于显示。
单独过滤对象的属性或方法:
get-service | Get-Member -MemberType Method
get-service | Get-Member -MemberType Properties
一个对象的属性、方法以及其他附加到对象的东西都被称为成员。就好像对象本身是一个乡村俱乐部,所有属性和方法都是俱乐部的成员。这也是Get-Member名称的由来:该命令获取对象成员的列表。
理解对象“标签”- 属性
当查看Gm的输出结果时,会有一些不同种类的属性:
- 脚本属性;
- 属性;
- NoteProperty;
- 别名属性。
通常来说,.Net Framework中的对象——也就是所有PowerShell对象的来源——只包含“属性”。PowerShell会动态添加其他内容:ScriptProperty、NoteProperty、AliasProperty等。
PowerShell有一个扩展类型系统(ETS)负责添加这些后来的属性。为什么它会这么做?拿某些案例来说,它使得对象具有更好的一致性,比如为原生只具有类似ProcessName属性的对象添加Name属性(这也是别名属性的作用)。
属性总是包含一个值。例如,进程对象的ID属性可能是1234,对象的名称属性的值可能是NotePad。属性用于描述关于对象的某些方面:它的状态、它的ID、它的名称等。
在PowerShell中,属性通常是只读的,意味着你无法通过给Name属性赋一个新值来改变服务的名称。
对象行为 - 方法
很多对象都支持一个或多个方法,可以用来指导对象的行为。如进程对象包含一个Kill方法,它会终止进程。
例如,如果需要终止一个进程,可以通过3个办法实现
(Get-Process notepad).kill()
Get-Process notepad | Stop-Process
Stop-Process notepad
事件
除了属性和方法之外,对象还有一个事件。事件是以对象的方式通知你某些事情发生了。
一个进程对象,举例来说,可以在进程结束时触发Exited事件。你可以将你自己的命令附加到这些事件上,比如说,当进程结束时发送一封邮件。以这种方式和事件交互是高级主题。
排序对象:Sort-Object
大部分PowerShell Cmdlets以确定性的方式产生对象,这意味着每次运行命令时都会以相同的顺序产生对象。例如,服务和进程都按照字母表顺序对名称进行排序。事件日志倾向于按照事件排序。那么假如我们希望改变排序方式,该如何做?
例如,假设我们希望显示一个进程列表,按照对虚拟内存(Vitrual Memory, VM)的消耗由高到低进行排列。我们将需要基于VM属性对列表进行重新排序。PowerShell提供了一个简单的Cmdlet:Sort-Object
其默认是升序,可以使用-descending
参数进行反转排序。Sort-Object
命令的-property
参数接受多个值。为了防止两个进程使用的虚拟内存相同,我们还希望按照进程ID进行排序。
选择对象属性:Select-Object
该Cmdlet从管道接受对象,然后可以指定希望显示的属性。这对于将对象输出到HTML的ConvertTo-HTML命令来说非常有用,因为该Cmdlet通常会创建包含所有属性的表。
注:Select-Object
是将管道输入的属性从进程对象中复制出来,然后再进行下一步处理。
可以比较以下两个结果:
Select-Object
还拥有-First
和-Last
参数,这两个参数可以保留管道中对象的子集。
- 例如,
Get-Process | Select -First 10
将会保留前10个对象。 - 但不能加过滤条件,比如选择特定的进程,只能选择前(或最后)10个。
理解对象的输出形式
PowerShell管道在最后一个命令执行之前总是传递对象。在最后一个命令执行时,PowerShell将会查看管道中所包含的对象,并根据不同的配置文件决定哪一个属性被用于构建展示在屏幕上的最终结果。它还会基于一些内部规则和配置文件确定展示是表还是列表。
范例1:
在本例中,首先运行Get-Process,该命令将进程对象放入管道。下一个命令是Sort-Object,该命令并不会改变管道中的内容,仅仅是改变对象的顺序,直到Sort-Object结束,管道仍然只包含进程。最后一个命令是Out-File。在这里,PowerShell生成输出结果,也就是管道中所包含的内容——进程对象,并根据PowerShell的内部规则将对象格式化,最终结果被存入指定文件。
范例2:
该命令以同样的方式运行,但Select-Object就有所不同了。进程对象总是拥有相同的成员。Select-Object并不能通过删除不需要的属性减少属性列表。如果这样的话,结果就不再是进程对象,而是Select-Object创建一个名为PSObject的自定义对象,PowerShell使用这个对象将属性从进程对象中复制出来,结果是自定义对象被放入管道。
当PowerShell发现光标已经到达命令行结尾时,它必须知道如何对文本输出结果进行排版。这是由于管道中包含的对象不再是进程对象,PowerShell不会再将默认规则和配置应用于进程对象,而是通过查询PSObject的规则和配置,这也是当前管道中包含的配置类型。由于PSObjects用于自定义输出,微软并没有为PSObjects提供任何规则或配置。而是PowerShell将尽最大努力进行猜测并产生表。
你可以使用Gm查看管道中不同的对象。请记住,你可以在任何产生输出结果的Cmdlet之后使用Gm。
请注意,PowerShell会展示出管道中对象的类型名称作为Gm输出结果的一部分。在第二个例子中,对象类型为System.Diagnostics.Process
,但是在第一个例子中,管道里包含另一种类型的对象。
即便Gm产生对象并将对象放入管道,在运行Gm之后,管道也不再包含进程对象或是“经过筛选”的对象,它仅包含由Gm生成的对象类型:Microsoft.PowerShell.Commands.MemberDefinition
。
首先是Get-Process命令,将进程对象放入管道。然后运行Gm,该命令分析进程对象并生成该对象的Member Definition对象。然后将结果再次利用管道传输给Gm,该命令将分析并产生MemberDefinition成员列表作为输出结果。