PowerShell自定义对象详解

什么是对象

在面向对象编程的领域有一句话叫:万事万物皆为对象。

我们生活中的每一件东西都可以看作是一个对象,包括我们本身都是一个对象。

这是一种抽象的思想,我们将一件事物提取出特征和行为,将特征定义为属性,将行为封装成方法

对象在程序开发中的概念可以说都一样。

对象通常有自己的属性和方法,比如一个人,它的属性有肤色 /身高/ 性别 等,方法有 走路 /躺下 /呼喊/吃饭/睡觉/打豆豆 等。

什么是PowerShell对象

在powershell中提供了对对象的定义方法;使用这样的方法创建的变量就是powershell对象。

PowerShell是基于面向对象化的,不像传统的shell那样基于文本。这其中最主要的原因就是因为Win平台在管理操作上主要以面向对象为主,因此为了符合系统特点和我们的操作习惯,PowerShell也继承了这一特色。因此,不像传统的shell,在PowerShell中,我们可以随意地与对象进行互动。

1.创建

PS C:\Users\Administrator> $aa = New-Object object
PS C:\Users\Administrator> $aa.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object


PS C:\Users\Administrator> $aa | Get-Member *


 TypeName:System.Object

Name        MemberType Definition
----        ---------- ----------
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
ToString    Method     string ToString()


PS C:\Users\Administrator>

2.添加属性:方法1

PS C:\Users\Administrator> $aa | Add-Member -MemberType NoteProperty -Name "Name" -Value "Jack"
PS C:\Users\Administrator> $aa

Name
----
Jack


PS C:\Users\Administrator> $aa | Get-Member *


 TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Name        NoteProperty string Name=Jack


PS C:\Users\Administrator>

3.添加属性:方法2

PS C:\Users\Administrator> Add-Member -InputObject $aa -MemberType NoteProperty -Name "Language" -Value "Powershell"
PS C:\Users\Administrator> $aa | Get-Member *


 TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=Powershell
Name        NoteProperty string Name=Jack


PS C:\Users\Administrator> $aa

Name Language
---- --------
Jack Powershell


PS C:\Users\Administrator>

4.添加方法

PS C:\Users\Administrator> $aa | Add-Member -MemberType ScriptMethod -Name "sayhello" -Value { write-host "hello" }
PS C:\Users\Administrator> $aa | Get-Member *


 TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=Powershell
Name        NoteProperty string Name=Jack
sayhello    ScriptMethod System.Object sayhello();


PS C:\Users\Administrator> $aa.sayhello()
hello
PS C:\Users\Administrator>
PS C:\Users\Administrator> $S = { $this.Name.ToUpper() }
PS C:\Users\Administrator> $aa | Add-Member -MemberType ScriptMethod -Name "UpperMyName" -Value $S
PS C:\Users\Administrator> $aa

Name Language
---- --------
Jack Powershell


PS C:\Users\Administrator> $aa.UpperMyName()
JACK
PS C:\Users\Administrator>
PS C:\Users\Administrator> $word = "Goodbye!!!"
PS C:\Users\Administrator> $sayword = { Write-Host $word }
PS C:\Users\Administrator> $aa | Add-Member -MemberType ScriptMethod -Name "sayBye" -Value $sayword
PS C:\Users\Administrator> $aa.sayBye()
Goodbye!!!
PS C:\Users\Administrator>

传参(注意$this和传入参数的调用)

$block = {
 param(
 $var
 )
 $result = "{0},{1} I'm {2}" -f $var,"hello world!!",$this.Name
 return $result
}
$aa | Add-Member -MemberType ScriptMethod -Name "sayAnything" -Value $block

PS C:\Users\Administrator> $aa | Add-Member -MemberType ScriptMethod -Name "sayAnything" -Value $block
PS C:\Users\Administrator> $aa.sayAnything("Tom")
Tom,hello world!! I'm Jack
PS C:\Users\Administrator>

若下个验证代码块是否可以正常运行可以使用:

PS C:\Users\Administrator> &$block
,hello world!!
PS C:\Users\Administrator>

或者

PS C:\Users\Administrator> &$block -var "qq"
qq,hello world!!
PS C:\Users\Administrator>

5.移除方法

PS C:\Users\Administrator> $aa | Get-Member


 TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=Powershell
Name        NoteProperty string Name=Jack
sayAnything ScriptMethod System.Object sayAnything();
sayBye      ScriptMethod System.Object sayBye();
sayhello    ScriptMethod System.Object sayhello();
UpperMyName ScriptMethod System.Object UpperMyName();


PS C:\Users\Administrator> $aa.PsObject.Members.Remove("sayAnything")
PS C:\Users\Administrator> $aa | Get-Member


 TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=Powershell
Name        NoteProperty string Name=Jack
sayBye      ScriptMethod System.Object sayBye();
sayhello    ScriptMethod System.Object sayhello();
UpperMyName ScriptMethod System.Object UpperMyName();


PS C:\Users\Administrator>

什么是PowerShell自定义对象

自定义对象可以完全根据自己的设计,定义对象的属性和方法。

PowerShell自定义对象有什么作用

自定义对象可以更符合使用者的要求,因为他的属性和方法完全由使用者自己定义设定;比默认的对象更加灵活。自己创建的自定义对象完完全全根据自己的意愿赋予属性和方法,可以完全做到独一无二。

PowerShell自定义对象的常见用法

1.创建自定义对象

tips:需要powershell 3.0及以上版本

$myObject = [PSCustomObject]@{
 Name = 'Kevin'
 Language = 'PowerShell'
 State    = 'Texas'
}
##创建
PS C:\WINDOWS\System32> $myObject = [PSCustomObject]@{
>> Name = 'Kevin'
>> Language = 'PowerShell'
>> State    = 'Texas'
>> }
PS C:\WINDOWS\System32>

##查看
PS C:\WINDOWS\System32> $myObject

Name  Language   State
----  --------   -----
Kevin PowerShell Texas

##查看属性
PS C:\WINDOWS\System32> $myObject.name
Kevin
PS C:\WINDOWS\System32>

上面这些利用hashtable也能实现基本一样的效果,那我们来做下对比:

$myHashtable = @{
 Name = 'Kevin'
 Language = 'PowerShell'
 State    = 'Texas'
}

##创建
PS C:\WINDOWS\System32> $myHashtable = @{
>> Name = 'Kevin'
>> Language = 'PowerShell'
>> State    = 'Texas'
>> }
PS C:\WINDOWS\System32>
#查看
PS C:\WINDOWS\System32> $myHashtable

Name                           Value
----                           -----
Name                           Kevin
Language                       PowerShell
State                          Texas


##查看属性
PS C:\WINDOWS\System32> $myHashtable.Name
Kevin
PS C:\WINDOWS\System32>

2.自定义对象 vs. HashTable

类型不同

PS C:\WINDOWS\System32> $myObject.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object


PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myHashtable.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Hashtable                                System.Object


PS C:\WINDOWS\System32>

可用的方法不同

PS C:\WINDOWS\System32> $myHashtable.Count
3
PS C:\WINDOWS\System32> $myObject.Count
PS C:\WINDOWS\System32>

Member大大不同

##查看Member
PS C:\WINDOWS\System32> $myObject | Get-Member


 TypeName:System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=PowerShell
Name        NoteProperty string Name=Kevin
State       NoteProperty string State=Texas

##利用select
PS C:\WINDOWS\System32> $myObject | select name

Name
----
Kevin


PS C:\WINDOWS\System32>



##查看Member
PS C:\WINDOWS\System32> $myHashtable | Get-Member


 TypeName:System.Collections.Hashtable

Name              MemberType            Definition
----              ----------            ----------
Add               Method                void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, System.Object value)
Clear             Method                void Clear(), void IDictionary.Clear()
Clone             Method                System.Object Clone(), System.Object ICloneable.Clone()
Contains          Method                bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)
ContainsKey       Method                bool ContainsKey(System.Object key)
ContainsValue     Method                bool ContainsValue(System.Object value)
CopyTo            Method                void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array array, int index)
Equals            Method                bool Equals(System.Object obj)
GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections.IDictionaryEnumerator IDictionary.GetEnumerator(), System.Collections.IEnume...
GetHashCode       Method                int GetHashCode()
GetObjectData     Method                void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context), void ISerializable.GetObj...
GetType           Method                type GetType()
OnDeserialization Method                void OnDeserialization(System.Object sender), void IDeserializationCallback.OnDeserialization(System.Object sender)
Remove            Method                void Remove(System.Object key), void IDictionary.Remove(System.Object key)
ToString          Method                string ToString()
Item              ParameterizedProperty System.Object Item(System.Object key) {get;set;}
Count             Property              int Count {get;}
IsFixedSize       Property              bool IsFixedSize {get;}
IsReadOnly        Property              bool IsReadOnly {get;}
IsSynchronized    Property              bool IsSynchronized {get;}
Keys              Property              System.Collections.ICollection Keys {get;}
SyncRoot          Property              System.Object SyncRoot {get;}
Values            Property              System.Collections.ICollection Values {get;}

##利用select
PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myHashtable | select Name

Name
----



PS C:\WINDOWS\System32>

注意:对于hashtable而言,我们的例子中演示的结果虽然也能通过$myHashtable.Name显示出与$myObject.Name一样的结果;但是,$myHashtable.Name真正的写法应该是$myHashtable.Item("Name")

因为hashtable仅仅是键值对,所以无法通过使用Format-TableExport-CSVSelect的方法对数据进行处理。

3.HashTable转换成PSCustomObject

PS C:\WINDOWS\System32> $myHashtable = @{
>>     Name     = 'Kevin'
>>     Language = 'PowerShell'
>>     State    = 'Texas'
>> }
>> $myObject = [pscustomobject]$myHashtable
PS C:\WINDOWS\System32> $myObject

Name  Language   State
----  --------   -----
Kevin PowerShell Texas


PS C:\WINDOWS\System32>

注意:强烈建议如果在需要使用自定义对象的情况时从一开始使用;因为像这种从hashtable转换的PSCustomObject,实际上肯恶搞并不完全保障对象属性的顺序。

当然,这种情况目前可以通过[ordered]@()来解决,但这不时本片文章的讨论重点。

将哈希表保存到文件的最佳方法是将其保存为 JSON。 可以将其导入回 [PSCustomObject]

$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json

4.历史遗留问题

$myHashtable = @{
 Name     = 'Kevin'
 Language = 'PowerShell'
 State    = 'Texas'
}

$myObject = New-Object -TypeName PSObject -Property $myHashtable

老版本的powershell使用上述方法创建自定义对象;但这种方法创建的速度比较慢,而且时公认要逐步废弃的方法;除非你是老版本,否则请务必精良使用新的方法创建。

5.自定义对象的属性

5.1添加属性

PS C:\WINDOWS\System32> $myObject

Name  Language   State
----  --------   -----
Kevin PowerShell Texas


PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'
PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myObject

Name  Language   State ID
----  --------   ----- --
Kevin PowerShell Texas KevinMarquette


PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myObject.ID
KevinMarquette
PS C:\WINDOWS\System32>

5.2移除属性

PS C:\WINDOWS\System32> $myObject.psobject.properties.remove('ID')
PS C:\WINDOWS\System32> $myObject

Name  Language   State
----  --------   -----
Kevin PowerShell Texas


PS C:\WINDOWS\System32>

.psobject 是内部成员,它使你能够访问基对象元数据。

5.3列出属性名称

PS C:\WINDOWS\System32> $myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
Language
Name
State

PS C:\WINDOWS\System32> $myObject | Get-Member


 TypeName:System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=PowerShell
Name        NoteProperty string Name=Kevin
State       NoteProperty string State=Texas


PS C:\WINDOWS\System32>

或者

PS C:\WINDOWS\System32> $myobject.psobject.properties.name
Name
Language
State
PS C:\WINDOWS\System32>

5.4动态访问属性

$myObject.Name
or
$myObject.'Name'

都是允许的方法

PS C:\WINDOWS\System32> $myObject.Name
Kevin
PS C:\WINDOWS\System32> $myObject.'Name'
Kevin
PS C:\WINDOWS\System32>


因此我们可以利用第二种方式并定义变量的形式实现动态访问自定义对象的属性

$property = 'Name'
$myObject.$property

PS C:\WINDOWS\System32> $property = 'Name'
PS C:\WINDOWS\System32> $myObject.$property
Kevin
PS C:\WINDOWS\System32>

6.PSCustomObject转换为HshTable

PS C:\WINDOWS\System32> $hashtable = @{}
PS C:\WINDOWS\System32> foreach( $property in $myobject.psobject.properties.name )
>> {
>>     $hashtable[$property] = $myObject.$property
>> }
PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $hashtable

Name                           Value
----                           -----
Name                           Kevin
Language                       PowerShell
State                          Texas


PS C:\WINDOWS\System32>

7.自定义对象的方法(Method)

如果需要将脚本方法添加到对象,则可以使用 Add-MemberScriptBlock 执行此操作。 必须使用 this 自动变量引用当前对象。 下面是将对象转换为哈希表的 scriptblock

$ScriptBlock = {
 $hashtable = @{}
 foreach( $property in $this.psobject.properties.name )
 {
 $hashtable[$property] = $this.$property
 }
 return $hashtable
}

然后

PS C:\WINDOWS\System32> $memberParam = @{
>>     MemberType = "ScriptMethod"
>>     InputObject = $myobject
>>     Name = "ToHashtable"
>>     Value = $scriptBlock
>> }
PS C:\WINDOWS\System32> Add-Member @memberParam
PS C:\WINDOWS\System32>
PS C:\WINDOWS\System32> $myObject

Name  Language   State
----  --------   -----
Kevin PowerShell Texas


PS C:\WINDOWS\System32> $myObject | Get-Member


 TypeName:System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Language    NoteProperty string Language=PowerShell
Name        NoteProperty string Name=Kevin
State       NoteProperty string State=Texas
ToHashtable ScriptMethod System.Object ToHashtable();


PS C:\WINDOWS\System32>

使用自定义的Method

PS C:\WINDOWS\System32> $myObject.ToHashtable()

Name                           Value
----                           -----
Name                           Kevin
Language                       PowerShell
State                          Texas


PS C:\WINDOWS\System32>

8.自定义对象类型的 PSTypeName

既然我们有了一个对象,我们还可以用它做一些可能不那么显而易见的事情。 第一件事就是为它指定 PSTypeName。 以下是我看到的最常用的方法:

$myObject.PSObject.TypeNames.Insert(0,"My.Object")


PS C:\Users\Administrator> $myObject.PSObject.TypeNames
My.Object
System.Management.Automation.PSCustomObject
System.Object
PS C:\Users\Administrator>

或者

$myObject1 = [PSCustomObject]@{
 PSTypeName = 'My.Object'
 Name       = 'Kevin'
 Language   = 'PowerShell'
 State      = 'Texas'
}

PS C:\Users\Administrator> $myObject.PSObject.TypeNames
My.Object
System.Management.Automation.PSCustomObject
System.Object
PS C:\Users\Administrator>
##我本人更新换这种方式

9.自定义对象结合array使用的例子(一般写脚本收集数据时比较常用)

$myObject1 = [PSCustomObject]@{
 Name     = 'Arthur'
 Language = 'PowerShell'
 State    = 'Texas'
}


$myObject2 = [PSCustomObject]@{
 Name     = 'Bill'
 Language = 'Python'
 State    = 'Texas'
}
$a = @()

$a += $myObject1
$a += $myObject2

PS C:\Users\Administrator> $a

Name     Language   State
----     --------   -----
Arthur   PowerShell Texas
Bill     Python     Texas


PS C:\Users\Administrator>
PS C:\Users\Administrator> $a | select Name

Name
----
Arthur
Bill

PS C:\Users\Administrator>

Powershell自定义变量进阶篇

1.Update-TypeData

PowerShell 为我们决定默认情况下显示哪些属性。 很多本机命令都有一个可以完成所有繁重工作的 .ps1xml格式化文件

1.1带有 DefaultPropertySet 的 Update-TypeData

$TypeData = @{
 TypeName = 'My.Object'
 DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData

$myObject = [PSCustomObject]@{
 PSTypeName = 'My.Object'
 Name       = 'Kevin'
 Language   = 'PowerShell'
 State      = 'Texas'
}

PS C:\Users\Administrator> $myObject | Format-List
Name     : Kevin
Language : PowerShell

PS C:\Users\Administrator> $myObject | Format-List *
Name     : Kevin
Language : PowerShell
State    : Texas

PS C:\Users\Administrator>

现在,我可以轻松地创建具有很多属性的对象,并在从 shell 中查看时,为其提供一个经过定制的干净清爽的视图。

1.2带有 ScriptProperty 的 Update-TypeData

如何为你的对象创建脚本属性呢?

$myObject = [PSCustomObject]@{
 PSTypeName = 'My.Object'
 Name       = 'Kevin'
 Language   = 'PowerShell'
 State      = 'Texas'
}

$TypeData = @{
 TypeName = 'My.Object'
 MemberType = 'ScriptProperty'
 MemberName = 'UpperCaseName'
 Value = {$this.Name.toUpper()}
}
Update-TypeData @TypeData


PS C:\Users\Administrator> $myObject | Format-List *


Name          : Kevin
Language      : PowerShell
State         : Texas
UpperCaseName : KEVIN



PS C:\Users\Administrator>

你可以在创建对象之前或之后执行此操作,它仍可正常工作。 这就是将 Add-Member 与脚本属性一起使用带来的不同之处。 当你通过我前面提及的方式使用 Add-Member 时,它只存在于对象的特定实例上。 此方法适用于具有此 TypeName 的所有对象。

本文如有考虑步骤出现任何纰漏,欢迎大家不吝指正。
——夏明亮

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容