什么是Windows PowerShell?它吃什么?第4部分:使用对象,自定义类



PowerShell解释器窗口中命令的文本输出只是一种以人类可读形式显示信息的方式。实际上,环境专注于处理对象:cmdlet和函数在输入处接收它们,并在输出处返回它们,并且在交互模式和脚本中可用的变量类型基于.NET类。在本周期的第四篇文章中,我们将更详细地研究如何使用对象。

目录:


PowerShell




ForEach-Object, Group-Object Measure-Object
.NET COM (New-Object)

PSCustomObject


PowerShell


回想一下,对象是数据字段(属性,事件等)及其处理方法(方法)的集合。它的结构由类型决定,该类型通常基于统一.NET Core平台中使用的类。也可以使用COM,CIM(WMI)和ADSI对象。除了PowerShell之外,还需要属性和方法来对数据执行各种操作,对象还可以作为参数传递给函数和cmdlet,将其值分配给变量,并且还存在一种用于编写命令(管道或管道)的机制。管道中的每个命令依次将其输出传递给下一个命令-一个对象一个对象。为了进行处理,可以使用编译的cmdlet或创建自己的高级功能对管道中的对象执行各种操作:过滤,排序,分组甚至更改其结构。这种形式的数据传输具有很大的优势:接收团队不需要解析字节流(文本),可以通过引用相应的属性和方法轻松提取所有必要的信息。

查看对象结构


例如,运行Get-Process cmdlet,该cmdlet允许您获取有关系统中正在运行的进程的信息:



它显示一些格式化的文本数据,这些数据无法让您了解返回的对象及其方法的属性。要微调输出,您需要学习如何检查对象的结构,Get-Member cmdlet将帮助我们:

Get-Process | Get-Member



在这里,我们已经看到了类型和结构,例如,在附加参数的帮助下,我们可以仅显示输入输入的对象的属性:

Get-Process | Get-Member -MemberType Property

需要这些知识才能以交互方式解决管理任务或编写自己的脚本:例如,通过Responding属性获取有关挂起进程的信息。

对象过滤


PowerShell允许您管道满足特定条件的对象:

Where-Object {   }

在运算符括号中执行脚本块的结果应为逻辑值。如果为true($ true),则进入Where-Object cmdlet的对象将沿管道向下传递,否则(值$ false)将被删除。例如,我们列出了已停止的Windows Server服务,即 状态属性设置为已停止的那些:

Get-Service | Where-Object {$_.Status -eq "Stopped"}



在这里,我们再次看到了文本表示形式,但是如果您想了解通过管道的对象的类型和内部结构,这很容易:

Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member



排序对象


对对象进行流水线处理时,通常需要对它们进行排序。属性名称(排序键)传递给Sort-Object cmdlet,它返回按其值排序的对象。正在运行的进程的输出可以根据所花费的处理器时间(cpu属性)轻松地进行排序:

Get-Process | Sort-Object –Property cpu

调用Sort-Object cmdlet时,可以省略-Property参数-默认使用该参数。对于反向排序,请使用-Descending参数:

Get-Process | Sort-Object cpu -Descending



选择对象及其零件


Select-Object cmdlet允许您使用-First或-Last参数在管道的开头或结尾选择特定数量的对象。使用它,您可以选择单个对象或某些属性,也可以基于它们创建新对象。让我们使用简单的示例来查看cmdlet的工作。

以下命令显示有关消耗最大RAM(WS属性)的10个进程的信息:

Get-Process | Sort-Object WS -Descending | Select-Object -First 10



您只能选择通过管道的对象的某些属性,并根据它们创建新的属性:

Get-Process | Select-Object ProcessName, Id -First 1

作为管道的结果,我们将获得一个新对象,该对象的结构与Get-Process cmdlet返回的结构不同。我们将使用Get-Member进行验证:

Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member



请注意,Select-Object返回一个对象(-First 1),该对象只有我们指定的两个字段:它们的值是从第一个对象复制的,该对象通过Get-Process cmdlet传递到管道。使用选择对象,在PowerShell脚本中创建对象的方法之一是基于:

$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()



使用选择对象,可以将计算的属性添加到必须表示为哈希表的对象中在这种情况下,其第一个键的值对应于属性的名称,第二个键的值对应于管道的当前元素的属性的值:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}



让我们看一下通过管道的对象的结构:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member



ForEach-Object,Group-Object和Measure-Object


还有其他cmdlet用于处理对象。例如,我们将讨论三个最有用的:

ForEach-Object允许您为管道中的每个对象执行PowerShell代码:

ForEach-Object {   }

组对象按属性值将对象分组:

Group-Object PropertyName

如果使用-NoElement参数运行它,则可以找出组中元素的数量。

Measure-Object通过管道中对象字段的值聚合各种汇总参数(计算总和,并找到最小值,最大值或平均值):

Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum

通常,所考虑的cmdlet是交互使用的,脚本通常使用Begin,Process和End块创建函数

创建.NET和COM对象(新对象)


带有.NET Core和COM接口的许多软件组件对系统管理员有用。使用System.Diagnostics.EventLog类,可以直接从Windows PowerShell管理系统日志。让我们看一个使用带有-TypeName参数的New-Object cmdlet创建此类的实例的示例:

New-Object -TypeName System.Diagnostics.EventLog



由于我们没有指定特定的事件日志,因此该类的结果实例不包含任何数据。要更改此设置,必须在创建过程中使用-ArgumentList参数调用特殊的构造方法。如果要访问应用程序日志,请将字符串“ Application”作为参数传递给构造函数:

$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog



请注意:我们将命令的输出保存在$ AppLog变量中。尽管管道通常以交互方式使用,但脚本编写通常需要维护对象引用。此外,主要的.NET Core类包含在System名称空间中:默认情况下,PowerShell在其中搜索指定的类型,因此编写Diagnostics.EventLog而不是System.Diagnostics.EventLog是非常正确的。

要使用日记,可以参考适当的方法:

$AppLog | Get-Member -MemberType Method



假设使用具有访问权限的Clear()方法将其清除:

$AppLog.Clear()

New-Object cmdlet也用于处理COM组件。它们有很多-从Windows脚本服务器附带的库到ActiveX应用程序,例如Internet Explorer。要创建COM对象,需要使用所需类的程序标识符ProgId指定-ComObject参数:

New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject

要使用任意结构创建自己的对象,使用New-Object看起来太陈旧和麻烦;此cmdlet用于与PowerShell外部的软件组件一起使用。在后续文章中,将更详细地讨论此问题。除了.NET和COM对象之外,我们还将学习CIM(WMI)和ADSI对象。

调用静态方法


无法创建某些.NET Core类的实例:这些实例包括System.Environment和System.Math。它们是静态的,仅包含静态属性和方法。本质上,这些是不创建对象而使用的参考库。您可以通过文字引用静态类,将类型名称括在方括号中。此外,如果使用Get-Member查看对象的结构,我们将看到类型System.RuntimeType而不是System.Environment:

[System.Environment] | Get-Member



要仅查看静态元素,您需要使用-Static参数调用Get-Member(注意对象的类型):

[System.Environment] | Get-Member -Static



要访问静态属性和方法,使用两个连续的冒号而不是文字后面的句点:

[System.Environment]::OSVersion

要么

$test=[System.Math]::Sqrt(25) 
$test
$test.GetType()



键入PSCustomObject


在PowerShell中可用的众多数据类型中,值得一提的是PSCustomObject,其设计用于存储具有任意结构的对象。使用New-Object cmdlet创建这样的对象被认为是一种经典但繁琐且过时的方法:

$object = New-Object  –TypeName PSCustomObject -Property @{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'}

让我们看一下对象的结构:

$object | Get-Member



从PowerShell 3.0开始,可以使用另一种语法:

$object = [PSCustomObject]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

您可以通过以下等效方式之一访问数据:

$object.Name

$object.'Name'

$value = 'Name'
$object.$value

这是将现有哈希表转换为对象的示例:

$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()



这种对象的缺点之一是它们的属性顺序可以改变。为避免这种情况,必须使用[ordered]属性:

$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

创建对象还有其他选择:上面我们检查了Select-Object cmdlet的使用它仍然需要处理元素的添加和删除。对上一个示例中的对象执行此操作非常简单:

$object | Add-Member –MemberType NoteProperty –Name Age  –Value 33
$object | Get-Member



Add-Member cmdlet允许您不仅使用“ -MemberType ScriptMethod”构造将属性添加方法,而且还可以将方法添加到先前创建的$对象对象:

$ScriptBlock = {
    #  
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member

注意:为了存储新方法的代码,我们使用了ScriptBlock类型的$ ScriptBlock变量。



要删除属性,请使用适当的方法:

$object.psobject.properties.remove('Name')

创建自己的课程


PowerShell 5.0引入了使用面向对象编程语言的特征语法定义类的功能。服务字Class是为此目的而设计的,在此之后,您应该指定类名称并在操作符括号中描述其主体:

class MyClass
{
    #  
}

这是.NET Core的真实类型,其主体描述其属性,方法和其他元素。考虑一个简单的类定义的例子:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
}

若要创建对象(类的实例),请使用New-Object cmdlet 或[MyClass]类型的文字和伪静态方法(默认构造函数):

$object = New-Object -TypeName MyClass

要么

$object = [MyClass]::new()

让我们分析对象的结构:

$object | Get-Member



不要忘记作用域:您不能将类型名称称为字符串,也不能在定义该类的脚本或模块之外使用类型文字。同时,函数可以返回将在模块或脚本之外可用的类(对象)的实例。

创建对象后,填写其属性:

$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object



请注意,在类描述中,不仅设置了属性类型,还设置了它们的默认值:

class Example
{
     [string]$Name = 'John Doe'
}

类方法的描述类似于函数的描述,但是不使用函数字函数。与函数中一样,如有必要,将参数传递给方法:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
     
     # 
     Smile([bool]$param1)
     {
         If($param1) {
            Write-Host ':)'
         }
     }
}

现在,我们班级的代表知道了如何微笑:

$object = [MyClass]::new()
$object.Smile($true)

方法可以重载,此外,该类具有静态属性和方法,以及其名称与类本身名称一致的构造函数。脚本或PowerShell模块中定义的类可以用作另一个的基础-这就是实现继承的方式。同时,允许使用现有的.NET类作为基础类:

class MyClass2 : MyClass
{
      #  ,     MyClass
}
[MyClass2]::new().Smile($true)

我们在PowerShell中使用对象的描述几乎不详尽。在以下出版物中,我们将尝试通过一些实际例子来加深它:本系列的第五篇文章将专门讨论将PowerShell与第三方软件组件集成的问题。过去的部分可以在下面的链接中找到。



1: Windows PowerShell
2: Windows PowerShell
3: ,


All Articles