PowerShell 技能连载 - 导出 Wi-Fi 密码
在上一个技巧中,我们使用 netsh.exe 转储 Wi-Fi 配置。让我们更进一步,提取缓存的密码:
1 | # get cleartext password for each profile |
这只是一个示例,演示了 PowerShell 如何处理由控制台应用程序(例如 netsh.exe)返回的字符串信息。您也有可能遇到挑战:当 Wi-Fi 配置名称使用特殊字符(例如撇号)时,可能无法通过 netsh.exe 进行检索。
在上一个技巧中,我们使用 netsh.exe 转储 Wi-Fi 配置。让我们更进一步,提取缓存的密码:
1 | # get cleartext password for each profile |
这只是一个示例,演示了 PowerShell 如何处理由控制台应用程序(例如 netsh.exe)返回的字符串信息。您也有可能遇到挑战:当 Wi-Fi 配置名称使用特殊字符(例如撇号)时,可能无法通过 netsh.exe 进行检索。
PowerShell 不仅限于执行 cmdlet,还可以运行可执行文件。例如,没有内置的 cmdlet 可以列出现有的 Wi-Fi 配置文件,但是 netsh.exe
可以提供以下信息:
1 | PS> netsh wlan show profiles |
使用 Select-String
仅识别与模式匹配的输出行(冒号后面跟着文本),然后使用 -split
运算符在以 “: “ 分隔字符串,并返回最后一个数组元素 (index -1) 得到配置文件名称:
1 | PS> netsh wlan show profiles | |
PowerShell 将输出信息写入六个不同的流,并且仅将输出流分配给变量:
1 | function Invoke-Test |
其余所有流要么显示在控制台中,要么隐藏在控制台中,具体取决于其适当的首选项变量的设置:
1 | PS> Get-Variable -Name *preference -Exclude *confirm*,*whatif*,*progress* |
有时,可能还需要捕获其他流的输出并对其进行处理,而不是将其输出到控制台。为此,您可以将所有流重定向到输出流,并将总结果捕获到变量中:
1 | function Invoke-Test |
现在,此变量包含所有流的组合输出。为了单独处理流,您可能需要按类型对内容进行分组:
1 | PS> $groups = $all | Group-Object -Property { $_.GetType().Name } -AsHashTable -AsString |
Write-Host
是将信息输出给用户的非常有用的 cmdlet,因为此输出不能被丢弃:
1 | function Invoke-Test |
不过从 PowerShell 5开始,引擎发生了悄然的变化。Write-Host
产生的输出现在也由流系统控制,并且 Write-Host
与 Write-Information
共享新的信息流。
如果要隐藏 Write-Host
发出的消息,只需将 #6 流重定向到 $null
:
1 | PS> $result = Invoke-Test 6>$null |
有关流和重定向的更多信息,请访问 https://powershell.one/code/9.html。
PowerShell 通过不同的流输出信息。警告写入到与输出不同的流中,而错误也写入不同的流。每个流都有一个唯一的数字标识符:
ID | Stream |
1 | Output |
2 | Error |
3 | Warning |
4 | Verbose |
5 | Debug |
6 | Information |
如果要丢弃某个流,可以使用重定向运算符(“>
”)并将流重定向到 $null
。此行代码将丢弃任何错误或警告消息:
1 | Get-Process -FileVersionInfo 2>$null 3>$null |
无论您做什么,PowerShell中都有(少量)命令可将信息输出到控制台。无论流重定向或赋值给 $null
都不能禁止这类命令输出,例如:
1 | PS> $null = Get-WindowsUpdateLog *>&1 |
即使所有输出流都被丢弃,Get-WindowsUpdateLog
cmdlet 仍会将大量信息写入控制台。
如果遇到这种情况,最后的方法是暂时禁用内部命令 Out-Default
,如下所示:
1 | # temporarily overwrite Out-Default |
当您查询操作系统详细信息时,WMI 会返回一个数字:
1 | PS> Get-CimInstance -ClassName Win32_OperatingSystem | |
SuiteMask 实际上是一个位掩码,其中每个位代表一个特定的细节。要将其转换为可读的文本,请使用标志枚举:
1 | $SuiteMask = @{ |
这将添加一个计算得出的 SuiteMaskText
属性,该属性列出了已安装的操作系统扩展:
Caption SuiteMask SuiteMaskText
------- --------- -------------
Microsoft Windows 10 Pro 272 TerminalServices, TerminalServicesSingleSession
WMI 返回每个不同的 Windows SKU 的密码编号:
1 | PS> Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty OperatingSystemSKU |
要将此数字转换为有意义的文本(例如出于报告目的),请尝试以下操作:
1 | $OperatingSystemSKU = @{ |
输出将添加一个具有友好名称的新 OperatingSystemSKUText
属性:
Caption OperatingSystemSKU OperatingSystemSKUText
------- ------------------ ----------------------
Microsoft Windows 10 Pro 48 PRODUCT_PROFESSIONAL
WMI 类 Win32_OperatingSystem
提供了有关许多日期时间信息的丰富信息,包括上次启动的日期和安装时间:
1 | $dateTimeProps = 'InstallDate', 'LastBootupTime', 'LocalDateTime', 'CurrentTimeZone', 'CountryCode' |
结果看起来像这样:
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 | $os = Get-CimInstance -ClassName Win32_OperatingSystem |
结果看起来像这样:
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。
每个 Windows 操作系统都有一个描述,您可以使用以下命令查看(和更改)该描述:
1 | PS> control sysdm.cpl |
要通过 PowerShell 自动执行此操作,请使用以下命令:
1 | # change operating system description |