[TOC]

0x00 对象操作处理相关命令

描述: 下述命令常用于对象的相关操作,涉及创建、排序分组与比较等。

1
2
3
4
5
6
7
8
9
10
Get-Command -Noun Object | ? { $_.Source -eq "Microsoft.PowerShell.Utility" } | Format-Table -Property Name,Version,CommandType
# Name Version CommandType
# ---- ------- -----------
# Compare-Object 3.1.0.0 Cmdlet
# Group-Object 3.1.0.0 Cmdlet
# Measure-Object 3.1.0.0 Cmdlet
# New-Object 3.1.0.0 Cmdlet
# Select-Object 3.1.0.0 Cmdlet
# Sort-Object 3.1.0.0 Cmdlet
# Tee-Object 3.1.0.0 Cmdlet


0x01 对象创建属性和方法

New-Object 命令 - 创建新的对象

描述: 通过New-Object cmdlet 创建Microsoft.NET Framework或COM对象的实例,您可以指定.NET Framework类的类型(缺省)或COM对象的ProgID(需要使用ComObject参数)。

基础语法:

1
2
New-Object [-TypeName] <System.String> [[-ArgumentList] <System.Object[]>] [-Property <System.Collections.IDictionary>] [<CommonParameters>]
New-Object [-ComObject] <System.String> [-Property <System.Collections.IDictionary>] [-Strict] [<CommonParameters>]

参数说明:

  • TypeName : .NET Framework类。
  • ComObject : 指定要使用的 COM 类的编程标识符(或 ProgId )(获取请参照基础语法对象章)。
  • Strict : 生成非终止错误(只能在Com对象中使用)。
  • Property : 指定传递的参数采用 { } 进行包含。


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 0.New-Object可以创建一个对象,空对象什么都没有,如果调用它不会返回任何东西, 但可以在后续为他增加方法和属性。
PS > $obj = New-Object object #空对象

# 1.通过String类输入字符和数字创建一个包含指定个数字符的字符串
PS > New-Object String("*",10)
# **********

# 2.创建System.Version对象(.NET Framework类)
New-Object -TypeName System.Version -ArgumentList "1.2.3.4" # 方式1: 通过New-object创建对象
[System.Version]"1.2.3.4" # 方式2: 通过类型转换创建对象
# Major Minor Build Revision
# ----- ----- ----- --------
# 1 2 3 4

# 3.创建Internet Explorer COM对象(注意必须以管理员权限运行才行)
$IE1 = New-Object -COMObject InternetExplorer.Application.1 -Strict -Property @{Navigate2="www.microsoft.com"; Visible = $True} # 实践脚本编写中推荐
# 方式2:下面的命令得到与上面示例相同的结果。
$IE2 = New-Object -COMObject InternetExplorer.Application`
$IE2.Navigate2("www.microsoft.com")`
$IE2.Visible = $True`


# 4.将多个参数传递给.net的构造函数 (Collections - 集合)
# PowerShell将数组的每个成员绑定到构造函数的一个参数。
$array = @('One', 'Two', 'Three')
$parameters = @{
TypeName = 'System.Collections.Generic.HashSet[string]'
ArgumentList = ([string[]]$array, [System.StringComparer]::OrdinalIgnoreCase)
}
$set = New-Object @parameters # # $set | Get-Member -MemberType Property
$set
# One
# Two
# Three
$set.length # 显示每个字符串的字符串长度
# 3
# 3
# 5

# 5.调用将数组作为单个参数的构造函数
$array = @('One', 'Two', 'Three')
# This command throws an exception.
$set = New-Object -TypeName 'System.Collections.Generic.HashSet[string]' -ArgumentList $array
# This command succeeds.
$set = New-Object -TypeName 'System.Collections.Generic.HashSet[string]' -ArgumentList (,[string[]]$array)
$set
One
Two
Three

# 6.进行事件日志访问
# .NET Framework 类库包括一个名为 System.Diagnostics.EventLog 的类
[System.Diagnostics.EventLog]::GetEventLogs()
# Max(K) Retain OverflowAction Entries Log
# ------ ------ -------------- ------- ---
# 20,480 0 OverwriteAsNeeded 15,146 Application
# 20,480 0 OverwriteAsNeeded 0 HardwareEvents
# 512 7 OverwriteOlder 0 Internet Explorer
# 20,480 0 OverwriteAsNeeded 0 Key Management Service
# 128 0 OverwriteAsNeeded 62 OAlerts
# Security
# 20,480 0 OverwriteAsNeeded 35,409 System
# 15,360 0 OverwriteAsNeeded 8,402 Windows PowerShell
# 如果随后键入 $AppLog 你将可以看到它包含应用程序日志:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
# Max(K) Retain OverflowAction Entries Log
# ------ ------ -------------- ------- ---
# 20,480 0 OverwriteAsNeeded 15,146 Application

# 若要访问远程计算机上的应用程序日志,必须同时将日志名称和计算机名称(或 IP 地址)作为参数提供。
$RemoteAppLog = New-Object -TypeName System.Diagnostics.EventLog Application,192.168.1.81
# 采用对象方法清除事件日志, 可以使用 Get-Member 来显示与对象关联的方法
$AppLog | Get-Member -MemberType Method
PS C:\WINDOWS\system32> $AppLog
Max(K) Retain OverflowAction Entries Log
------ ------ -------------- ------- ---
20,480 0 OverwriteAsNeeded 15,146 Application

PS C:\WINDOWS\system32> $AppLog.Clear() # 清除后Entries条目为0
PS C:\WINDOWS\system32> $AppLog
Max(K) Retain OverflowAction Entries Log
------ ------ -------------- ------- ---
20,480 0 OverwriteAsNeeded 0 Application

Tips : Windows PowerShell 允许你使用具有 .NET Framework 和 COM 接口的软件组件,使用它们可执行许多系统管理任务。

Tips : 由于大多数 .NET Framework 核心类都包含在 System 命名空间中,所以如果 PS 找不到你指定的类型名称的匹配项,它将自动尝试查找你在 System 命名空间中指定的类,所以可以忽略System。

Tips : 可以采用 New-Object 来处理组件对象模型 (COM) 件, 组件的范围从 Windows 脚本宿主 (WSH) 包含的各种库到 ActiveX 应用程序(如大多数系统上安装的 Internet Explorer)。

1
2
3
4
5
6
# 通过指定以下 progid 来创建 WSH 对象: WScript.Shell 、 WScript.Network 、 Scripting.Dictionary 和 Scripting.FileSystemObject
# 有时使用 WSH 类执行某些任务(如创建快捷方式)仍更加简单。
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject


Add-Member 命令 - 向PowerShell对象的实例添加自定义属性和方法。

描述: 该 cmdlet 允许您将成员(属性和方法)添加到PowerShell对象的实例中。例如可以添加包含对象描述的NoteProperty成员或运行脚本以更改对象的ScriptMethod成员。

语法说明

1
2
3
4
5
6
7
add-Member [-MemberType] {AliasProperty | CodeProperty | Property | NoteProperty | ScriptProperty | Properties | PropertySet | Method | CodeMethod | ScriptMethod | Methods | ParameterizedProperty | MemberSet | Event | Dynamic | All} [-Name] <System.String> [[-Value] <System.Object>] [[-SecondValue] <System.Object>] [-Force] -InputObject <System.Management.Automation.PSObject> [-PassThru] [-TypeName <System.String>] [<CommonParameters>]

Add-Member [-NotePropertyName] <System.String> [-NotePropertyValue] <System.Object> [-Force] -InputObject <System.Management.Automation.PSObject> [-PassThru] [-TypeName <System.String>] [<CommonParameters>]

Add-Member [-NotePropertyMembers] <System.Collections.IDictionary> [-Force] -InputObject <System.Management.Automation.PSObject> [-PassThru] [-TypeName <System.String>] [<CommonParameters>]

Add-Member -InputObject <System.Management.Automation.PSObject> [-PassThru] [-TypeName <System.String>] [<CommonParameters>]


参数说明:
MemberType 参数 : 指定要添加到成员的的类型,添加包括属性和方法。

  • 1.属性相关
    • NoteProperty(增加一个属性)
    • Property:真正的属性
    • AliasProperty:另外一个属性的别名
    • CodeProperty:通过静态的.Net方法返回属性的内容
    • ScriptProperty:通过脚本执行返回一个属性的值
    • ParameterizedProperty:需要传递参数的属性
  • 2.方法相关
    • ScriptMethod(增加一个执行Powershell脚本方法)
    • Method:正常的方法
    • CodeMethod:映射到静态的.NET方法

PassThru 参数 : 生成输出对象。
Force 参数 : 强制执行比如覆盖已存在的成员(属性)


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 1.创建一个PSObject对象并为其添加属性
PS > $obj=New-Object PSObject
PS > Add-Member -MemberType NoteProperty -Name "A" -Value "1" -InputObject $obj
PS > Add-Member -MemberType NoteProperty -Name "B" -Value "2" -InputObject $obj
PS > Add-Member -MemberType NoteProperty -Name "C" -Value "3" -InputObject $obj
PS > Add-Member -MemberType NoteProperty -Name "D" -Value "4" -InputObject $obj
PS > $obj
# A B C D
# - - - -
# 1 2 3 4
PS > Add-Member -MemberType NoteProperty -Name "E" -Value "5" -InputObject $obj
PS > $obj
# 未知对象格式化ETS遵循一个规律如果对象的属性`少于5个则表格显示,否则列表显示`。
# A : 1
# B : 2
# C : 3
# D : 4
# E : 5

# 2.向表示Test.txt文件的FileInfo对象添加一个值为“Done”的Status note属性。
PS C:\Users\WeiyiGeek> $A = Get-ChildItem ping.bat
PS C:\Users\WeiyiGeek> $A | Add-Member -NotePropertyName Status -NotePropertyValue Done
PS C:\Users\WeiyiGeek> $A.ToString()
# C:\Users\WeiyiGeek\ping.bat
PS C:\Users\WeiyiGeek> $A.Status
# Done

# 3.以下示例将Size alias属性添加到表示Test.txt文件的对象中,向PSObject添加别名属性。
PS C:\Users\WeiyiGeek> $A.Length # 55 Bytes
PS C:\Users\WeiyiGeek> $A | Add-Member -MemberType AliasProperty -Name Size -Value Length # 新属性是长度属性的别名。
PS C:\Users\WeiyiGeek> $A.Size # 55 Bytes

# 4.此示例将StringUse注释属性添加到字符串,因为Add成员不能向字符串输入对象添加类型,最后一个命令显示新属性
$S = "WeiyiGeek"
$S = Add-Member -NotePropertyMembers @{StringUse="Display";StringName="Name"} -InputObject $S -PassThru
$S # WeiyiGeek
$S.StringUse # Display
$S.StringName # Name

# 5.创建一个对象给它添加静态属性和动态属性(执行PS脚本返回的值),以及添加PS脚本方法。
$obj=New-Object PSObject
$d = [ordered]@{Name="Server";System="Server Core";PSVersion="4.0"}
$obj | Add-Member -NotePropertyMembers $d -TypeName Asset -PassThru -Force
# Name System PSVersion
# ---- ------ ---------
# Server Server Core 4.0
$obj | Add-Member -MemberType NoteProperty -Name AddTime -Value (get-date)
$obj | Add-Member -MemberType ScriptProperty -Name CurrentTime -Value {get-date}
$obj
# AddTime CurrentTime
# ------- -----------
# 2021/4/28 22:42:48 2021/4/28 22:43:06
$obj | Add-Member ScriptMethod corkscrew { "Pop! Cheers!" } # 直接通过管道增加一个新方法
Add-member -MemberType ScriptMethod -InputObject $obj demo1 {"I'm is function, $obj "}
Add-Member -memberType ScriptMethod -InputObject $obj -Name demo2 -Value { "I'm Write now, Args : $Args" }
PS C:\Users\WeiyiGeek> $obj.demo1()
#I'm is function, @{AddTime=04/28/2021 22:42:48; CurrentTime=System.Management.Automation.PSScriptProperty}
PS C:\Users\WeiyiGeek> $obj.demo2("WeiyiGeek")
# I'm Write now, Args : WeiyiGeek
PS C:\Users\WeiyiGeek> $obj.corkscrew()
# Pop! Cheers!


# 6.将SizeInMB脚本方法添加到FileInfo对象,该对象将文件大小计算为最接近的兆字节。
$A = Get-ChildItem *.sh # 可以是多个文件
$S = {[math]::Round(($this.Length / 1MB), 5)}
$A | Add-Member -MemberType ScriptMethod -Name "SizeInMB" -Value $S
$A.SizeInMB()
0.01263
0.00176
0.00164


# 7.此函数用于将一个对象的所有属性复制到另一个对象。foreach循环使用Get-Member cmdlet获取From对象的每个属性。
function Copy-Property ($From, $To)
{
$properties = Get-Member -InputObject $From -MemberType Property
foreach ($p in $properties)
{
$To | Add-Member -MemberType NoteProperty -Name $p.Name -Value $From.$($p.Name) -Force
}
}


Get-Member 命令 - 对象属性和方法获取

描述: Get-Member 可帮助发现可用于命令的对象、属性和方法。任何生成基于对象的输出的命令都可以通过管道传递到该Cmdlet中。

Tips : 此处对于属性、对象和方法的名词介绍不在做过多的介绍(学习过面向对象编程的都应该知道)。
Tips :为了获得关于静态成员的信息,类的成员(而不是实例的成员)使用static参数,要仅获取某些类型的成员如(NoteProperties)请使用MemberType参数。

语法说明:

1
2
Get-Member [[-Name] <System.String[]>] [-Force] [-InputObject <System.Management.Automation.PSObject>] [-MemberType {AliasProperty | CodeProperty | Property | NoteProperty | ScriptProperty | Properties | PropertySet | Method | CodeMethod | ScriptMethod | Methods | P
arameterizedProperty | MemberSet | Event | Dynamic | All}] [-Static] [-View {Extended | Adapted | Base | All}] [<CommonParameters>]

参数说明:
MemberType : 指定成员类型取值包括:

  • Property:真正的属性
  • AliasProperty:另外一个属性的别名
  • CodeProperty:通过静态的.Net方法返回属性的内容
  • NoteProperty:随后增加的属性
  • ScriptProperty:通过脚本执行返回一个属性的值
  • ParameterizedProperty:需要传递参数的属性
  • Method:正常的方法
  • CodeMethod:映射到静态的.NET方法
  • ScriptMethod:一个执行Powershell脚本的方法
    Static : 获取成员的静态方法
    View :仅获取特定类型的属性和方法,指定一个或多个值。
  • Extended : 仅获取在Types.ps1xml文件中或通过使用Add Member cmdlet添加的属性和方法。
  • Adapted : 仅获取在PowerShell扩展类型系统中定义的属性和方法。
  • Base : 仅获取.NET对象的原始属性和方法(没有扩展或调整)。
  • All : Gets the members in the Base, Adapted, and Extended views.

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# 1.检索计算机上运行的 Windows 时间服务的相关信息的属性
Get-Service -Name w32time | Get-Member
# TypeName 指示返回的对象类型。
# TypeName:System.ServiceProcess.ServiceController

# 知道命令生成的对象类型之后,就可以使用此信息查找接受该类型的对象作为输入的命令
Get-Command -ParameterType ServiceController
# CommandType Name Version Source
# ----------- ---- ------- ------
# Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
# Cmdlet Restart-Service 3.1.0.0 Microsoft.PowerShell.Management
......

# 2.查看对象的静态方法
Get-Member -static -memberType *Method

# 3.查看Get-Host 对象的属性以及方法
Host | Get-Member -MemberType Property
# Name MemberType Definition
# ---- ---------- ----------
# CurrentCulture Property cultureinfo CurrentCulture {get;}
# CurrentUICulture Property cultureinfo CurrentUICulture {get;}
# DebuggerEnabled Property bool DebuggerEnabled {get;set;}
# InstanceId Property guid InstanceId {get;}
# IsRunspacePushed Property bool IsRunspacePushed {get;}
# Name Property string Name {get;}
# PrivateData Property psobject PrivateData {get;}
# Runspace Property runspace Runspace {get;}
# UI Property System.Management.Automation.Host.PSHostUserInterface UI {get;}
# Version Property version Version {get;}
(Host).Version # 以Version属性值获得PS版本
# Major Minor Build Revision
# ----- ----- ----- --------
# 5 1 19041 610

Host | Get-Member -MemberType Method
# TypeName:System.Management.Automation.Internal.Host.InternalHost
# Name MemberType Definition
# ---- ---------- ----------
# EnterNestedPrompt Method void EnterNestedPrompt()
# Equals Method bool Equals(System.Object obj)
# ExitNestedPrompt Method void ExitNestedPrompt()
# GetHashCode Method int GetHashCode()
# GetType Method type GetType()
# .........
# ToString Method string ToString()
(Host).GetHashCode();
# 14844108


# 4.通过将 Get-Service 的结果通过管道传递到 Select-Object 并将 * 通配符指定为 Property 参数的值来选择所有属性或者进行制定。
Get-Service -Name TermService | Get-Member -MemberType Property
# Status Name DisplayName
# ------ ---- -----------
# Running TermService Remote Desktop Services

(Get-Service -Name TermService).ServiceName
# TermService
(Get-Service -Name TermService).DisplayName
# Remote Desktop Services
(Get-Service -Name TermService).Status
# Running

# 采用 Select-Object 命令搞定服务名称、描述、以及其状态
Get-Service -Name TermService | Select-Object -Property ServiceName,DisplayName,Status
# ServiceName DisplayName Status
# ----------- ----------- ------
# TermService Remote Desktop Services Running


# 5.方法是可执行的操作
Get-Service -Name TermService | Get-Member -MemberType Method
# 例如 Stop 方法可用于停止 Windows 远程桌面服务。
(Get-Service -Name TermService).Stop()


# 6.使用 Start-Service cmdlet 指定 PassThru 参数,以使其生成输出,然后通过管道将输出传递到 Get-Member
Start-Service -Name w32time -PassThru | Get-Member
# TypeName:System.ServiceProcess.ServiceController
# Name MemberType Definition
# ---- ---------- ----------
# Name AliasProperty Name = ServiceName
# RequiredServices AliasProperty RequiredServices = ServicesDependedOn
# Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs)
# Close Method void Close()


# 7.获取服务对象的扩展成员
# 描述: 此示例获取通过使用 `Types.ps1xml` 文件或 `Add Member` cmdlet扩展的服务对象的方法和属性。
$obj=New-Object PSObject
$d = [ordered]@{Name="Server";System="Server Core";PSVersion="4.0"}
$obj | Add-Member -NotePropertyMembers $d -TypeName Asset -PassThru -Force
$obj | Get-Member -View Extended
# TypeName:Asset
# Name MemberType Definition
# ---- ---------- ----------
# Name NoteProperty string Name=Server
# PSVersion NoteProperty string PSVersion=4.0
# System NoteProperty string System=Server Core


# 8.此示例获取事件查看器中系统日志中事件日志对象的脚本属性。
Get-WinEvent -LogName System -MaxEvents 1 | Get-Member -View All
Get-WinEvent -LogName System -MaxEvents 1 | Select-Object -Property Id,LevelDisplayName,LogName,Message
# Id LevelDisplayName LogName Message
# -- ---------------- ------- -------
# 7040 信息 System Background Intelligent Transfer Service 服务的启动类型从 自动启动 更改为 按需启动。


# 9.接受从通道里面传递的对象也可以指定-InputObject参数接收。
$array = @(1,'hello')
$array | Get-Member # 显示 TypeName:System.Int32 - TypeName:System.String
Get-Member -InputObject $array # 显示 TypeName:System.Object[]

Tips : 许多初学者认为无法使用 Get-* 命令进行颠覆性更改。 但是如果方法使用不当,也会带来严重后果。

Tips : 若要通过管道将命令传递到 Get-Member,命令必须生成基于对象的输出,例如以下命令是不行的 Get-Service -Name w32time | Out-Host | Get-Member,因为Out-Host 直接写入 PowerShell 主机,但它不会为管道生成基于对象的输出。 因此无法通过管道将该命令传输到 Get-Member。



0x02 排序分组

Sort-Object 命令 - 按属性值对对象排序

描述:主要是根据传递过来的对象的属性作为条件来进行排序,例如升序(Ascending)或者降序(Descending),别名是 sort;

基础语法:

1
2
# 语法
Sort-Object [[-Property] <System.Object[]>] [-CaseSensitive] [-Culture <System.String>] [-Descending] [-InputObject <System.Management.Automation.PSObject>] [-Unique] [<CommonParameters>]

实际案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 1.因此输出按默认排序属性Name排序。
Get-ChildItem -Path C:\Test | Sort-Object

# 2.按文件长度对当前目录排序
PS> Get-ChildItem -Path C:\Test -File | Sort-Object -Property Length

# 3.按内存使用情况对进程排序
PS> Get-Process | Sort-Object -Property WS | Select-Object -Last 5

# 4.按Id对HistoryInfo对象排序
Get-History | Sort-Object -Property Id -Descending
# 默认会根据length进行升序排序
ls | Sort-Object Length
# 如果要降序排列使用Descending选项
ls | Sort-Object Length -Descending
# 通过ls获取当前目录的所有文件信息,然后通过Sort -Descending对文件信息按照Name降序排列,最后将排序好的文件的Name和Mode格式化成Table输出。
ls | sort -Descending Name | Format-Table Name,Mode
# Name Mode
# d.txt -a---
# c.txt -a---

# 5.主要关键字降序排序,次要关键字升序的排序
Get-Service | Sort-Object @{expression="Length";Descending=$true},@{expression="Name";Ascending=$true}
# Status Name DisplayName
# ------ ---- -----------
# Running Appinfo Application Information
# Running BthAvctpSvc AVCTP service
# Running BrokerInfrastru... Background Tasks Infrastructure Ser...
# Running BDESVC BitLocker Drive Encryption Service

# 6.按时间跨度对文本文件排序
Get-ChildItem -Path C:\Test\*.txt | Sort-Object -Property @{Expression = {$_.CreationTime - $_.LastWriteTime}; Descending = $False} | Format-Table CreationTime, LastWriteTime, FullName

# 7.对文本文件中的名称或者整型进行排序(并去重)
Get-Content -Path C:\Test\ServerNames.txt | Sort-Object -Unique
# 在第二个示例中,`Get Content`获取文件的内容,并将管道行发送到`Sort Object` cmdlet。`Sort Object`使用脚本块将字符串转换为整数。
# 在示例代码中,`[int]`将字符串转换为整数,`$\`表示每个字符串在管道中的位置。整数对象通过管道发送到“Sort Object”cmdlet。
# `Sort Object`按数字顺序对整数对象进行排序。
Get-Content -Path C:\Test\ProductId.txt | Sort-Object {[int]$_}


Group-Object 命令 - 对包含指定属性的相同值的对象进行分组。

语法参数:

1
Group-Object [[-Property] <System.Object[]>] [-AsHashTable] [-AsString] [-CaseSensitive] [-Culture <System.String>] [-InputObject <System.Management.Automation.PSObject>] [-NoElement] [<CommonParameters>]

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 1.查看当前关闭和开启的所有服务,并且通过状态进行分组
PS > Get-Service | Group-Object Status | Format-Table -AutoSize -Wrap
# Count Name Group
# ----- ---- -----
# 170 Stopped {AarSvc_48f8d, AJRouter, ALG, AppIDSvc...}
# 103 Running {AMD External Events Utility, AnyShare Service, Appinfo, AudioEndpointBuilder...}


# 2.当前目录的文件以扩展名进行分组
PS> ls | Group-Object Extension
# Count Name Group
# ----- ---- -----
# 5 {11, 2, Dell-Latitude-E6330-Mojave-Hackintosh-EFI, 课件...}
# 1 .py {123.py}
# 1 .gz {back.tar.gz}
# 9 .lnk {eclipse.exe.lnk..}
$files = Get-ChildItem -Path $PSHOME -Recurse
$files | Group-Object -Property extension -NoElement | Sort-Object -Property Count -Descending
# Count Name
# ----- ----
# 365 .xml
# 231 .cdxml
# 根据当前应用程序的发布者分组
Get-Process | Group-Object Company -NoElement | Sort-Object -Property Count -Descending


# 3.奇与偶数分组
1..20 | Group-Object -Property {$_ % 2}
# Count Name Group
# ----- ---- -----
# 10 0 {2, 4, 6, 8...}
# 10 1 {1, 3, 5, 7...}


# 4.按EntryType对事件日志事件进行分组(根据数量排序)
Get-WinEvent -LogName System -MaxEvents 1000 | Group-Object -Property Level -NoElement | Sort-Object -Property Count -Descending
# Count Name
# ----- ----
# 720 4
# 151 2
# 127 3
# 2 1
Get-WinEvent -LogName System -MaxEvents 1000 | Group-Object -Property LevelDisplayName
# Count Name Group
# ----- ---- -----
# 719 信息 {System.Diagnostics.Eventing.Reader.EventLogRecord...}
Get-WinEvent -LogName System -MaxEvents 1000 | Group-Object -Property Id | Sort-Object -Property Count -Descending
# Count Name Group
# ----- ---- -----
# 374 7040 {System.Diagnostics.Eventing.Reader.EventLogRecord...}
# 186 16 {System.Diagnostics.Eventing.Reader.EventLogRecord...}


# 6.在哈希表中对对象进行分组
$A = Get-Command Get-*, Set-* -CommandType cmdlet | Group-Object -Property Verb -AsHashTable -AsString
# $A
# Name Value
# ---- -----
# Get {Get-Acl, Get-Alias, Get-AppLockerFileInformation, Get-AppLockerPolicy...}
# Set {Set-Acl, Set-Alias, Set-AppBackgroundTaskResourcePolicy, Set-AppLockerPolicy...}
$A.Get
# CommandType Name Version Source
# ----------- ---- ------- ------
# Cmdlet Get-Acl 3.0.0.0 Microsoft.PowerShell.Security
# Cmdlet Get-Alias 3.1.0.0 Microsoft.PowerShell.Utility
# Cmdlet Get-AppLockerFileInformation 2.0.0.0 AppLocker
# Cmdlet Get-AppLockerPolicy 2.0.0.0 AppLocker

# 7.使用表达式来进行分组
# 根据文件的大小是否大于1kb分组
ls | Group-Object {$_.Length -gt 1kb}
# 如果按照文件名的首字母分组
ls | Group-Object {$_.name.SubString(0,1).toUpper()}

TIPS: Group-Object并不是唯一可以完成分组功能的命令,事实上格式化命令,例如Format-Object支持一个GroupBy的参数,也可以完成分组。


Get-Unique 命令 - 删除重复对象

描述: Get-Unique 可以从已排序的对象列表中删除重复对象, 它会逐个遍历对象,每次遍历时都会与前一个对象进行比较,如果和前一个对象相等就会抛弃当前对象,否则就保留一般是排序后再进行去重,与Linux中uniq命令有一致之处;

基础语法:

1
2
3
Get-Unique [-AsString] [-InputObject <System.Management.Automation.PSObject>] [<CommonParameters>]

Get-Unique [-InputObject <System.Management.Automation.PSObject>] [-OnType] [<CommonParameters>]

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1.去重实例 Get-Unique 与 Sort-Object -Unique 效果一致。
PS > 1,2,3,1 | Get-Unique
# 1
# 2
# 3
# 1
PS > 1,2,3,1 | Sort-Object -Unique
# 1
# 2
# 3

# 2.不换行显示(值得需学习)
PS > Get-ChildItem | foreach{$_.Extension} | Sort-Object | Get-Unique | Write-Host -NoNewline
.CHM.chw.docx.gz.jpg.lnk.png.properties.py.sql.txt


# 3.获取文本文件中的唯一单词
$A = $( foreach ($line in Get-Content C:\Test1\File1.txt) {
$line.tolower().split(" ")
}) | Sort-Object | Get-Unique
$A.count


# 4.获取目录中唯一的对象类型
Get-ChildItem | Sort-Object {$_.GetType()} | Get-Unique -OnType

# 5.AsString参数告诉“Get Unique”将ProcessName值视为字符串。如果没有此参数`Get Unique`将ProcessName值视为对象,并且只返回对象的一个实例,即列表中的第一个进程名。
Get-Process | Sort-Object | Select-Object processname | Get-Unique -AsString
# ProcessName
# -----------
# ApplicationFrameHost
# ...


0x03 筛选过滤

描述: 如果您要过滤某些对象和对象的属性可以采用以下cmdlet.

  • 如果要过滤对象可以使用 Where-Object;
  • 如果要过滤对象的属性,可以使用 Select-Object;
  • 如果要自定义个性化的过滤效果可以使用 ForEach-Object。
  • 最后如果想过滤重复的结果,可是使用 Get-Uinque。

Select-Object 命令 - 对象属性数据筛选呈现

描述:显示特定对象属性的列字段的数据进行呈现,即选择对象或对象特性;

语法说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
语法
Select-Object
[[-Property] <System.Object[]>] [-ExcludeProperty <System.String[]>]
[-ExpandProperty <System.String>]
[-First <System.Int32>]
[-InputObject <System.Management.Automation.PSObject>]
[-Last <System.Int32>]
[-Skip <System.Int32>]
[-Unique]
[-Wait]
[<CommonParameters>]

Select-Object [[-Property] <System.Object[]>] [-ExcludeProperty <System.String[]>] [-ExpandProperty <System.String>] [-InputObject <System.Management.Automation.PSObject>] [-SkipLast <System.Int32>] [-Unique] [<CommonParameters>]

Select-Object [-Index <System.Int32[]>] [-InputObject <System.Management.Automation.PSObject>] [-Unique] [-Wait] [<CommonParameters>]


基础实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 1.获取get-process对象中的 Handle,Id,ProcessName 三个属性此为表格的形式
# Tips :除非使用自定义格式设置,否则返回超过四个属性的命令默认为列表。
PS > get-process | Select-Object Handle,Id,ProcessName
# Handle Id ProcessName
# ------ -- -----------
# 0 Idle
# 4 System
# 8 svchost
PS C:\Users\WeiyiGeek> Get-Service -Name w32time | Select-Object -Property Status, DisplayName, Can*
# Status : Running
# DisplayName : Windows Time
# CanPauseAndContinue : False
# CanShutdown : True
# CanStop : True


# 2.按特性选择对象并设置结果格式
Get-Process Explorer | Select-Object -Property ProcessName -ExpandProperty Modules | Format-List


# 3.显示第一个或者前几个条目
PS> Get-service | Select-Object -First 2
# Status Name DisplayName
# ------ ---- -----------
# Stopped AarSvc_48f8d AarSvc_48f8d
# Stopped AJRouter AllJoyn Router Service
Get-Process | Sort-Object -Property WS | Select-Object -Last 5
# 列出占用CPU最大的5个进程
Get-process | sort -Descending cpu | select -First 5


# 4.从数组中选择唯一字符
"a","b","c","a","a","a" | Select-Object -Unique
# a
# b
# c


# 5.在事件日志中选择最新和最旧的事件
$a = Get-EventLog -LogName "Windows PowerShell"
$a | Select-Object -Index 0, ($A.count - 1)
# Index Time EntryType Source InstanceID Message
# ----- ---- --------- ------ ---------- -------
# 7427 4月 07 15:29 Information PowerShell 400 引擎状态已从 None 更改为 Available。...
# 1 11月 05 00:10 Information PowerShell 600 提供程序“Registry”为 Started...

# 5.支持通配符过滤排除显示指定属性
PS> Dir | Select-Object * -Exclude 'Last*'
# 限制对象的数量
Dir | Select-Object -ExcludeProperty "*N*" -First 5


# 6.选择除第一个对象以外的所有对象
New-PSSession -ComputerName (Get-Content Servers.txt | Select-Object -Skip 1)

# 7.重命名文件并选择几个要查看的文件
Get-ChildItem *.txt -ReadOnly |
Rename-Item -NewName {$_.BaseName + "-ro.txt"} -PassThru |
Select-Object -First 5 -Wait

# 8.演示-ExpandProperty参数的复杂性
# Create a custom object to use for the Select-Object example.
$object = [pscustomobject]@{Name="CustomObject";[email protected](1,2,3,4,5)}
# Use the ExpandProperty parameter to Expand the property.
$object | Select-Object -ExpandProperty Expand -Property Name
# 1
# 2
# 3
# 4
# 5

# 9.在对象上创建自定义特性
$customObject = 1 | Select-Object -Property MyCustomProperty
$customObject.MyCustomProperty = "New Custom Property"
$customObject
# MyCustomProperty
# ----------------
# New Custom Property

# 10.为每个InputObject创建计算属性
Get-Process | Select-Object -Property ProcessName,{$_.StartTime.DayOfWeek}
# ProcessName $_.StartTime.DayOfWeek
# ---- ----------------------
# alg Wednesday
# ati2evxx Wednesday
# ati2evxx Thursday

# 添加自定义属性以计算传入的每个FileInfo对象的大小(以KB为单位)。 (非常值得学习)
# Use the pipeline variable to divide each file's length by 1 KiloBytes
$size = @{label="Size(KB)";expression={$_.length/1KB}}

# Create an additional calculated property with the number of Days since the file was last accessed.
# You can also shorten the key names to be 'l', and 'e', or use Name instead of Label.
$days = @{l="Days";e={((Get-Date) - $_.LastAccessTime).Days}}

# You can also shorten the name of your label key to 'l' and your expression key to 'e'.
Get-ChildItem $PSHOME -File | Select-Object Name, $size, $days
# Name Size(KB) Days
# ---- -------- ----
# Certificate.format.ps1xml 12.5244140625 223
# Diagnostics.Format.ps1xml 4.955078125 223
# DotNetTypes.format.ps1xml 134.9833984375 223


Where-Object 命令 - 自定义条件过滤

描述:它的主要作用是可以自定义过滤条件,并过滤从管道传递来的对象数据。(一般在管道符之后)

关系操作符号:

WeiyiGeek.

WeiyiGeek.

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#1.获得C:\Windows目录下所有大小超过200 bytes的文件。(? / where)
> Get-ChildItem C:\Windows | Where-Object -FilterScript {$_.Length -gt 200}
> ls . | Where-Object -FilterScript {$_.Extension -eq ".txt"}
##目录: C:\Users\Administrator
# Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2019/11/18 20:58 4 1.txt


#2.别名使用与like相似过滤
> ls . | ? -FilterScript {$_.BaseName -like "无线网络连接-GEEK"}


#3.我要获得所有名为svchost的进程信息。
> Get-Process | Where-Object{$_.ProcessName -eq "svchost"}
# Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
# ------- ------ ----- ----- ------ -- -- -----------
# 354 33 8956 11296 0.14 276 0 svchost
Get-Process | Where-Object ProcessName -EQ "svchost" #PowerShell 3.0版本后Where就有了更简单的写法我们不需要?和{};
# 608 28 21124 23296 95 4.80 292 svchost

#4.甚至可以筛选之后继续筛选(在JAVA中我们叫链式编程)
Get-Process | Where-Object{$_.ProcessName -eq "svchost"} | Where-Object{$_.Id -gt 1000}


#5.补充过滤案例
PS D:\> get-alias | Where-Object -FilterScript {$_.Name -like 'sa*'}
CommandType Name Version Source
----------- ---- ------- ------
Alias sajb -> Start-Job
Alias sal -> Set-Alias
Alias saps -> Start-Process
Alias sasv -> Start-Service


0x04 统计对比

Measure-Object 命令 - 计算对象的数字特性,以及字符串对象(如文本文件)中的字符、单词和行。

描述: Measure-Object 允许指定待统计对象的属性如求最小值、最大值、平均值、和

基础语法:

1
2
3
4
# 语法
Measure-Object [[-Property] <System.String[]>] [-Average] [-InputObject <System.Management.Automation.PSObject>] [-Maximum] [-Minimum] [-Sum] [<CommonParameters>]

Measure-Object [[-Property] <System.String[]>] [-Character] [-IgnoreWhiteSpace] [-InputObject <System.Management.Automation.PSObject>] [-Line] [-Word] [<CommonParameters>]

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 1.要查看当前目录文件占用空间的情况。
PS > ls | measure length -Average -Sum -Maximum -Minimum
# Count : 26
# Average : 6109027.96153846
# Sum : 158834727
# Maximum : 97612275
# Minimum : 250
# Property : length

# 2.统计文本文件中的字符数,单词数,行数
"One", "Two", "Three", "Four" | Set-Content -Path C:\Temp\tmp.txt
Get-Content C:\Temp\tmp.txt | Measure-Object -Character -Line -Word
# Lines Words Characters Property
# ----- ----- ---------- --------
# 4 4 15

# 3.包含指定特性的度量对象
$services = Get-Service
$processes = Get-Process
$services + $processes | Measure-Object
$services + $processes | Measure-Object -Property DisplayName

# 4.测量CSV文件的内容
Import-Csv d:\test\serviceyrs.csv | Measure-Object -Property years -Minimum -Maximum -Average

# 5.测量布尔值
Get-ChildItem | Measure-Object -Property psiscontainer -Maximum -Sum -Minimum -Average

# 6.换行符`n将字符串分隔为单独的行用以下参数分别统计行、单词、字符数
"One`nTwo`nThree" | Measure-Object -Line -Word -Character
Lines Words Characters Property
----- ----- ---------- --------
3 3 13


Compare-Object 命令 - 比较两组对象

描述: 比较前后两个时间段开启了那些进程,服务状态有什么变化,新增和减少了对象。

基础语法:

1
2
# 语法
Compare-Object [-ReferenceObject] <System.Management.Automation.PSObject[]> [-DifferenceObject] <System.Management.Automation.PSObject[]> [-CaseSensitive] [-Culture <System.String>] [-ExcludeDifferent] [-IncludeEqual] [-PassThru] [-Property <System.Object[]>] [-SyncWindow <System.Int32>] [<CommonParameters>]


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 1.比较不同时间段进程信息 (=>表示新增的对象, <=表示剔除的对象>)
PS > $before=Get-Process
PS > $after=get-process
PS > Compare-Object $before $after
PS > Compare-Object -ReferenceObject $before -DifferenceObject $after
# InputObject SideIndicator
# ----------- -------------
# System.Diagnostics.Process (YoudaoDict) <=
# System.Diagnostics.Process (YoudaoDictHelper) <=
# System.Diagnostics.Process (YoudaoDictHelper) <=
# System.Diagnostics.Process (YoudaoEH) <=
# System.Diagnostics.Process (YoudaoOcr) <=
# System.Diagnostics.Process (YoudaoWSH) <=


# 2.比较每个对象的属性变化,因为它有一个参数-property
PS > $svc1=Get-Service wsearch
PS > $svc1.stop()
PS > $svc2=Get-Service wsearch
PS > Compare-Object $svc1 $svc2 -Property Status,Name
# Status Name SideIndicator
# ------ ---- -------------
# StartPending wsearch =>
# Running wsearch


# 3.比较文件的内容(显示不同的)
PS C:PowerShell> "Hellow
>> Power
>> Shell" >a.txt
>>
PS C:PowerShell> "Hollow
>> Shell
>> Linux" >b.txt
>>
PS C:PowerShell> Compare-Object (Get-Content .a.txt) (Get-Content .b.txt)
InputObject SideIndicator
---------- - -------------
Hollow => 目标文件中不相同的行
Linux =>
Hellow <= 源文件中不相同的行

# 4.比较每一行内容并排除差异(即显示两边文件都有的)
$objects = @{
ReferenceObject = (Get-Content -Path ./Testfile1.txt)
DifferenceObject = (Get-Content -Path ./Testfile2.txt)
}
Compare-Object @objects -IncludeEqual -ExcludeDifferent
# InputObject SideIndicator
# ----------- -------------
# Weiyieek ==
# 2 ==

# 5.使用PassThru参数时显示差异
$a = $True
Compare-Object -IncludeEqual $a $a -PassThru
(Compare-Object -IncludeEqual $a $a -PassThru) | Get-Member


# 6.使用属性比较两个简单对象
Compare-Object -ReferenceObject 'abc' -DifferenceObject 'xyz' -Property Length -IncludeEqual
# Length SideIndicator
# ------ -------------
# 3 ==

# 7.比较实现IComparable的复杂对象
Compare-Object ([TimeSpan]"0:0:1") "0:0:1" -IncludeEqual
# InputObject SideIndicator
# ----------- -------------
# 00:00:01 ==
# 在第二种情况下,TimeSpan被转换成一个字符串这样对象就不同了。
Compare-Object "0:0:1" ([TimeSpan]"0:0:1")
# InputObject SideIndicator
# ----------- -------------
# 00:00:01 =>
# 0:0:1 <=