PowerShell 技能连载 - 导出 Wi-Fi 密码

在上一个技巧中,我们使用 netsh.exe 转储 Wi-Fi 配置。让我们更进一步,提取缓存的密码:

1
2
3
4
5
6
7
8
9
# get cleartext password for each profile
Foreach ($profile in $profiles)
{
$password = (@(netsh wlan show profile name="$profile" key=clear) -like '*Key Content*' -split ': ')[-1]
[PSCustomObject]@{
Profile = $profile
Password = $password
}
}

这只是一个示例,演示了 PowerShell 如何处理由控制台应用程序(例如 netsh.exe)返回的字符串信息。您也有可能遇到挑战:当 Wi-Fi 配置名称使用特殊字符(例如撇号)时,可能无法通过 netsh.exe 进行检索。

PowerShell 技能连载 - 显示 Wi-Fi 配置

PowerShell 不仅限于执行 cmdlet,还可以运行可执行文件。例如,没有内置的 cmdlet 可以列出现有的 Wi-Fi 配置文件,但是 netsh.exe 可以提供以下信息:

1
PS> netsh wlan show profiles

使用 Select-String 仅识别与模式匹配的输出行(冒号后面跟着文本),然后使用 -split 运算符在以 “: “ 分隔字符串,并返回最后一个数组元素 (index -1) 得到配置文件名称:

1
2
3
PS> netsh wlan show profiles |
Select-String ":(.{1,})$" |
ForEach-Object { ($_.Line -split ': ')[-1] }

PowerShell 技能连载 - 重定向流

PowerShell 将输出信息写入六个不同的流,并且仅将输出流分配给变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Invoke-Test
{
"Regular Output"
Write-Host "You always see me!"
Write-Information "Info"
Write-Warning "Warning"
Write-Error "Error"
Write-Debug "Debug"
Write-Verbose "Verbose"
Write-Output "Output"
}

$result = Invoke-Test

其余所有流要么显示在控制台中,要么隐藏在控制台中,具体取决于其适当的首选项变量的设置:

1
2
3
4
5
6
7
8
9
PS> Get-Variable -Name *preference -Exclude *confirm*,*whatif*,*progress*

Name Value
---- -----
DebugPreference SilentlyContinue
ErrorActionPreference Continue
InformationPreference SilentlyContinue
VerbosePreference SilentlyContinue
WarningPreference Continue

有时,可能还需要捕获其他流的输出并对其进行处理,而不是将其输出到控制台。为此,您可以将所有流重定向到输出流,并将总结果捕获到变量中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Invoke-Test
{
"Regular Output"
Write-Host "You always see me!"
Write-Information "Info"
Write-Warning "Warning"
Write-Error "Error"
Write-Debug "Debug"
Write-Verbose "Verbose"
Write-Output "Output"
}


$all = Invoke-Test *>&1

现在,此变量包含所有流的组合输出。为了单独处理流,您可能需要按类型对内容进行分组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS> $groups = $all | Group-Object -Property { $_.GetType().Name } -AsHashTable -AsString

PS> $groups

Name Value
---- -----
WarningRecord {Warning}
InformationRecord {You always see me!, Info}
ErrorRecord {Error}
String {Regular Output, Output}


PS> $groups.WarningRecord
WARNING: Warning

PS> $groups.InformationRecord
You always see me!
Info

PowerShell 技能连载 - 禁止 Write-Host 语句输出

Write-Host 是将信息输出给用户的非常有用的 cmdlet,因为此输出不能被丢弃:

1
2
3
4
5
6
7
8
9
10
11
function Invoke-Test
{
"Regular Output"
Write-Host "You always see me!"
}

# both show
Invoke-Test

# Write-Host still shows
$result = Invoke-Test

不过从 PowerShell 5开始,引擎发生了悄然的变化。Write-Host 产生的输出现在也由流系统控制,并且 Write-HostWrite-Information 共享新的信息流。

如果要隐藏 Write-Host 发出的消息,只需将 #6 流重定向到 $null

1
PS> $result = Invoke-Test 6>$null

有关流和重定向的更多信息,请访问 https://powershell.one/code/9.html

PowerShell 技能连载 - 丢弃数据流

PowerShell 通过不同的流输出信息。警告写入到与输出不同的流中,而错误也写入不同的流。每个流都有一个唯一的数字标识符:

IDStream
1Output
2Error
3Warning
4Verbose
5Debug
6Information

如果要丢弃某个流,可以使用重定向运算符(“>”)并将流重定向到 $null。此行代码将丢弃任何错误或警告消息:

1
Get-Process -FileVersionInfo 2>$null 3>$null

PowerShell 技能连载 - 忽略(任何)输出

无论您做什么,PowerShell中都有(少量)命令可将信息输出到控制台。无论流重定向或赋值给 $null 都不能禁止这类命令输出,例如:

1
PS> $null = Get-WindowsUpdateLog *>&1

即使所有输出流都被丢弃,Get-WindowsUpdateLog cmdlet 仍会将大量信息写入控制台。

如果遇到这种情况,最后的方法是暂时禁用内部命令 Out-Default,如下所示:

1
2
3
4
5
6
7
8
9
10
11
# temporarily overwrite Out-Default
function Out-Default {}

# run your code (guaranteed no output)
Get-WindowsUpdateLog

# test any other direct console write
[Console]::WriteLine("Hello")

# restore Out-Default
Remove-Item -Path function:Out-Default

PowerShell 技能连载 - 识别操作系统详细信息

当您查询操作系统详细信息时,WMI 会返回一个数字:

1
2
3
PS> Get-CimInstance -ClassName Win32_OperatingSystem |
Select-Object -ExpandProperty SuiteMask
272

SuiteMask 实际上是一个位掩码,其中每个位代表一个特定的细节。要将其转换为可读的文本,请使用标志枚举:

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
$SuiteMask = @{
Name = 'SuiteMaskText'
Expression = {
[Flags()] Enum EnumSuiteMask
{
SmallBusinessServer = 1
Server2008Enterprise = 2
BackOfficeComponents = 4
CommunicationsServer = 8
TerminalServices = 16
SmallBusinessServerRestricted = 32
WindowsEmbedded = 64
DatacenterEdition = 128
TerminalServicesSingleSession = 256
HomeEdition = 512
WebServerEdition = 1024
StorageServerEdition = 8192
ComputeClusterEdition = 16384
}

[EnumSuiteMask][int]$_.SuiteMask
}
}

Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -Property Caption, SuiteMask, $SuiteMask

这将添加一个计算得出的 SuiteMaskText 属性,该属性列出了已安装的操作系统扩展:

Caption                  SuiteMask                                   SuiteMaskText
-------                  ---------                                   -------------
Microsoft Windows 10 Pro       272 TerminalServices, TerminalServicesSingleSession

PowerShell 技能连载 - 识别 Windows 类型

WMI 返回每个不同的 Windows SKU 的密码编号:

1
2
PS> Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty OperatingSystemSKU
48

要将此数字转换为有意义的文本(例如出于报告目的),请尝试以下操作:

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
$OperatingSystemSKU = @{
Name = 'OperatingSystemSKUText'
Expression = {
$value = $_.OperatingSystemSKU

switch([int]$value)
{
0 {'PRODUCT_UNDEFINED'}
1 {'PRODUCT_ULTIMATE'}
2 {'PRODUCT_HOME_BASIC'}
3 {'PRODUCT_HOME_PREMIUM'}
4 {'PRODUCT_ENTERPRISE'}
5 {'PRODUCT_HOME_BASIC_N'}
6 {'PRODUCT_BUSINESS'}
7 {'PRODUCT_STANDARD_SERVER'}
8 {'PRODUCT_DATACENTER_SERVER'}
9 {'PRODUCT_SMALLBUSINESS_SERVER'}
10 {'PRODUCT_ENTERPRISE_SERVER'}
11 {'PRODUCT_STARTER'}
12 {'PRODUCT_DATACENTER_SERVER_CORE'}
13 {'PRODUCT_STANDARD_SERVER_CORE'}
14 {'PRODUCT_ENTERPRISE_SERVER_CORE'}
15 {'PRODUCT_ENTERPRISE_SERVER_IA64'}
16 {'PRODUCT_BUSINESS_N'}
17 {'PRODUCT_WEB_SERVER'}
18 {'PRODUCT_CLUSTER_SERVER'}
19 {'PRODUCT_HOME_SERVER'}
20 {'PRODUCT_STORAGE_EXPRESS_SERVER'}
21 {'PRODUCT_STORAGE_STANDARD_SERVER'}
22 {'PRODUCT_STORAGE_WORKGROUP_SERVER'}
23 {'PRODUCT_STORAGE_ENTERPRISE_SERVER'}
24 {'PRODUCT_SERVER_FOR_SMALLBUSINESS'}
25 {'PRODUCT_SMALLBUSINESS_SERVER_PREMIUM'}
26 {'PRODUCT_HOME_PREMIUM_N'}
27 {'PRODUCT_ENTERPRISE_N'}
28 {'PRODUCT_ULTIMATE_N'}
29 {'PRODUCT_WEB_SERVER_CORE'}
30 {'PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT'}
31 {'PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY'}
32 {'PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING'}
33 {'PRODUCT_SERVER_FOUNDATION'}
34 {'PRODUCT_HOME_PREMIUM_SERVER'}
35 {'PRODUCT_SERVER_FOR_SMALLBUSINESS_V'}
36 {'PRODUCT_STANDARD_SERVER_V'}
37 {'PRODUCT_DATACENTER_SERVER_V'}
38 {'PRODUCT_ENTERPRISE_SERVER_V'}
39 {'PRODUCT_DATACENTER_SERVER_CORE_V'}
40 {'PRODUCT_STANDARD_SERVER_CORE_V'}
41 {'PRODUCT_ENTERPRISE_SERVER_CORE_V'}
42 {'PRODUCT_HYPERV'}
43 {'PRODUCT_STORAGE_EXPRESS_SERVER_CORE'}
44 {'PRODUCT_STORAGE_STANDARD_SERVER_CORE'}
45 {'PRODUCT_STORAGE_WORKGROUP_SERVER_CORE'}
46 {'PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE'}
47 {'PRODUCT_STARTER_N'}
48 {'PRODUCT_PROFESSIONAL'}
49 {'PRODUCT_PROFESSIONAL_N'}
50 {'PRODUCT_SB_SOLUTION_SERVER'}
51 {'PRODUCT_SERVER_FOR_SB_SOLUTIONS'}
52 {'PRODUCT_STANDARD_SERVER_SOLUTIONS'}
53 {'PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE'}
54 {'PRODUCT_SB_SOLUTION_SERVER_EM'}
55 {'PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM'}
56 {'PRODUCT_SOLUTION_EMBEDDEDSERVER'}
57 {'PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE'}
58 {'PRODUCT_PROFESSIONAL_EMBEDDED'}
59 {'PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT'}
60 {'PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL'}
61 {'PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC'}
62 {'PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC'}
63 {'PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE'}
64 {'PRODUCT_CLUSTER_SERVER_V'}
65 {'PRODUCT_EMBEDDED'}
66 {'PRODUCT_STARTER_E'}
67 {'PRODUCT_HOME_BASIC_E'}
68 {'PRODUCT_HOME_PREMIUM_E'}
69 {'PRODUCT_PROFESSIONAL_E'}
70 {'PRODUCT_ENTERPRISE_E'}
71 {'PRODUCT_ULTIMATE_E'}
72 {'PRODUCT_ENTERPRISE_EVALUATION'}
76 {'PRODUCT_MULTIPOINT_STANDARD_SERVER'}
77 {'PRODUCT_MULTIPOINT_PREMIUM_SERVER'}
79 {'PRODUCT_STANDARD_EVALUATION_SERVER'}
80 {'PRODUCT_DATACENTER_EVALUATION_SERVER'}
84 {'PRODUCT_ENTERPRISE_N_EVALUATION'}
85 {'PRODUCT_EMBEDDED_AUTOMOTIVE'}
86 {'PRODUCT_EMBEDDED_INDUSTRY_A'}
87 {'PRODUCT_THINPC'}
88 {'PRODUCT_EMBEDDED_A'}
89 {'PRODUCT_EMBEDDED_INDUSTRY'}
90 {'PRODUCT_EMBEDDED_E'}
91 {'PRODUCT_EMBEDDED_INDUSTRY_E'}
92 {'PRODUCT_EMBEDDED_INDUSTRY_A_E'}
95 {'PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVE'}
96 {'PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER'}
97 {'PRODUCT_CORE_ARM'}
98 {'PRODUCT_CORE_N'}
99 {'PRODUCT_CORE_COUNTRYSPECIFIC'}
100 {'PRODUCT_CORE_SINGLELANGUAGE'}
101 {'PRODUCT_CORE'}
103 {'PRODUCT_PROFESSIONAL_WMC'}
105 {'PRODUCT_EMBEDDED_INDUSTRY_EVAL'}
106 {'PRODUCT_EMBEDDED_INDUSTRY_E_EVAL'}
107 {'PRODUCT_EMBEDDED_EVAL'}
108 {'PRODUCT_EMBEDDED_E_EVAL'}
109 {'PRODUCT_NANO_SERVER'}
110 {'PRODUCT_CLOUD_STORAGE_SERVER'}
111 {'PRODUCT_CORE_CONNECTED'}
112 {'PRODUCT_PROFESSIONAL_STUDENT'}
113 {'PRODUCT_CORE_CONNECTED_N'}
114 {'PRODUCT_PROFESSIONAL_STUDENT_N'}
115 {'PRODUCT_CORE_CONNECTED_SINGLELANGUAGE'}
116 {'PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC'}
117 {'PRODUCT_CONNECTED_CAR'}
118 {'PRODUCT_INDUSTRY_HANDHELD'}
119 {'PRODUCT_PPI_PRO'}
120 {'PRODUCT_ARM64_SERVER'}
121 {'PRODUCT_EDUCATION'}
122 {'PRODUCT_EDUCATION_N'}
123 {'PRODUCT_IOTUAP'}
124 {'PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER'}
125 {'PRODUCT_ENTERPRISE_S'}
126 {'PRODUCT_ENTERPRISE_S_N'}
127 {'PRODUCT_PROFESSIONAL_S'}
128 {'PRODUCT_PROFESSIONAL_S_N'}
129 {'PRODUCT_ENTERPRISE_S_EVALUATION'}
130 {'PRODUCT_ENTERPRISE_S_N_EVALUATION'}
135 {'PRODUCT_HOLOGRAPHIC'}
138 {'PRODUCT_PRO_SINGLE_LANGUAGE'}
139 {'PRODUCT_PRO_CHINA'}
140 {'PRODUCT_ENTERPRISE_SUBSCRIPTION'}
141 {'PRODUCT_ENTERPRISE_SUBSCRIPTION_N'}
143 {'PRODUCT_DATACENTER_NANO_SERVER'}
144 {'PRODUCT_STANDARD_NANO_SERVER'}
145 {'PRODUCT_DATACENTER_A_SERVER_CORE'}
146 {'PRODUCT_STANDARD_A_SERVER_CORE'}
147 {'PRODUCT_DATACENTER_WS_SERVER_CORE'}
148 {'PRODUCT_STANDARD_WS_SERVER_CORE'}
149 {'PRODUCT_UTILITY_VM'}
159 {'PRODUCT_DATACENTER_EVALUATION_SERVER_CORE'}
160 {'PRODUCT_STANDARD_EVALUATION_SERVER_CORE'}
161 {'PRODUCT_PRO_WORKSTATION'}
162 {'PRODUCT_PRO_WORKSTATION_N'}
164 {'PRODUCT_PRO_FOR_EDUCATION'}
165 {'PRODUCT_PRO_FOR_EDUCATION_N'}
168 {'PRODUCT_AZURE_SERVER_CORE'}
169 {'PRODUCT_AZURE_NANO_SERVER'}
171 {'PRODUCT_ENTERPRISEG'}
172 {'PRODUCT_ENTERPRISEGN'}
175 {'PRODUCT_SERVERRDSH'}
178 {'PRODUCT_CLOUD'}
179 {'PRODUCT_CLOUDN'}
180 {'PRODUCT_HUBOS'}
182 {'PRODUCT_ONECOREUPDATEOS'}
183 {'PRODUCT_CLOUDE'}
184 {'PRODUCT_ANDROMEDA'}
185 {'PRODUCT_IOTOS'}
186 {'PRODUCT_CLOUDEN'}
default {"$value"}
}

}
}

Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -Property Caption, OperatingSystemSKU, $OperatingSystemSKU

输出将添加一个具有友好名称的新 OperatingSystemSKUText 属性:

Caption                  OperatingSystemSKU OperatingSystemSKUText
-------                  ------------------ ----------------------
Microsoft Windows 10 Pro                 48 PRODUCT_PROFESSIONAL

PowerShell 技能连载 - 操作系统的启动和安装时间

WMI 类 Win32_OperatingSystem 提供了有关许多日期时间信息的丰富信息,包括上次启动的日期和安装时间:

1
2
3
$dateTimeProps = 'InstallDate', 'LastBootupTime', 'LocalDateTime', 'CurrentTimeZone', 'CountryCode'

Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -Property $dateTimeProps

结果看起来像这样:

InstallDate     : 03.09.2019 12:42:41
LastBootupTime  : 03.05.2020 12:15:45
LocalDateTime   : 04.05.2020 10:43:55
CurrentTimeZone : 120
CountryCode     : 49

如果您想知道系统运行了多少分钟,或者自安装以来已经过去了几天,请使用 New-TimeSpan:

1
2
3
4
5
6
7
$os = Get-CimInstance -ClassName Win32_OperatingSystem

$installedDays = (New-TimeSpan -Start $os.InstallDate).Days
$runningMinutes = [int](New-TimeSpan -Start $os.LastBootupTime).TotalMinutes

"Your copy of Windows was installed $installedDays days ago."
"Your system is up for {0:n0} minutes." -f $runningMinutes

结果看起来像这样:

Your copy of Windows was installed 243 days ago.
Your system is up for 1.353 minutes.

Get-CimInstance cmdlet可用于在本地和远程计算机上查询信息(前提是您具有适当的权限)。有关如何远程使用Get-CimInstance的更多信息,请访问https://powershell.one/wmi/remote-access

PowerShell 技能连载 - 改变操作系统描述

每个 Windows 操作系统都有一个描述,您可以使用以下命令查看(和更改)该描述:

1
PS> control sysdm.cpl

要通过 PowerShell 自动执行此操作,请使用以下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
# change operating system description
# (requires admin privileges)
$values = @{
Description = 'My Computer'
}
Set-CimInstance -Query 'Select * from Win32_OperatingSystem' -Property $values

# read description
# (no admin privileges required)
$description = Get-CimInstance -ClassName Win32_OperatingSystem |
Select-Object -ExpandProperty Description

"OS Description: $description"