PowerShell 技能连载 - 添加前导零
如果您需要数字前面添加前导零,例如对于服务器名,以下是两种实现方式。第一,您可以将数字转换为字符串,然后用 PadLeft()
函数将字符串填充到指定的长度:
1 | $number = 76 |
如果您需要数字前面添加前导零,例如对于服务器名,以下是两种实现方式。第一,您可以将数字转换为字符串,然后用 PadLeft()
函数将字符串填充到指定的长度:
1 | $number = 76 |
如果您希望显示一个带有按钮,可供用户点击的消息框,请试试这个函数:
1 | function Show-MessageBox |
以下是它的使用方法:
1 | PS> Show-MessageBox -Text 'Do you want to reboot now?' -Caption Reboot -Button YesNoCancel -Icon Exclamatio |
如果您想弹出一个快速而粗糙的输入框,提示用户输入数据,您可以通过 Microsoft Visual Basic 并且“借用”它的 InputBox 控件:
1 | Add-Type -AssemblyName Microsoft.VisualBasic |
但是请注意,这种方法有一些局限性:该输入框可能在您的 PowerShell 窗口之下打开,而且在高分辨率屏中,它的缩放可能不正确。
PowerShell 有许多读取文本文件的方法,它们的性能差异很大。请自己确认一下。以下例子演示了不同的实践,并测量执行的时间。请确保例子中的路径实际存在。如果文件不存在,请选择一个大文件来测试。
1 | # make sure this file exists, or else |
如果您的工作是跨国跨时区的,您可能会需要使用 UTC 时间来代替本地时间。要确保时间格式是语言中性的,我们推荐使用 ISO 格式。以下是使用方法:
1 | $date = Get-Date |
在前一个技能中我们演示了如何使用 ReplacementStrings
读取从 Get-EventLog
中收到的详细的事件日志信息。它工作得很完美,但是 Get-EventLog
职能读取“传统的”Windows 日志。在现代的 Windows 版本中还有许多额外的日志。
这些日志可以通过 Get-WinEvent
读取,而且有许多信息可以发掘。例如,要获取已安装的更新列表,请试试这段代码:
1 | $filter = @{ ProviderName="Microsoft-Windows-WindowsUpdateClient"; Id=19 } |
请注意这只是一个例子。通过以上代码,您可以查询您关心的任意事件 ID 的日志。例如以上代码,可以获取最新安装的 4 条更新:
1 | PS> . 'C:\Users\tobwe\Documents\PowerShell\Untitled5.ps1' <# script is not saved yet #> |
然而,这只是文本,而且要将它转换为一份已安装的更新的漂亮的报告并不容易。通过 Get-EventLog
,类似我们之前的技能介绍的,您可以使用 ReplacementStrings
来方便地存取纯净的信息。但是 Get-WinEvent
没有 ReplacementStrings
。
然而,有一个名为 Properties
的属性。以下是如何将属性转换为类似 ReplacementStrings
的数组的方法:
1 | $filter = @{ ProviderName="Microsoft-Windows-WindowsUpdateClient"; Id=19 } |
这段代码返回以安装更新的美观的列表:
Time Name
---- ----
25.05.2018 09:00:20 Definitionsupdate für Windows Defender Antivirus – KB2267602 (Definition 1....
25.05.2018 07:59:44 9WZDNCRFJ1XX-FITBIT.FITBIT
24.05.2018 11:04:15 Definitionsupdate für Windows Defender Antivirus – KB2267602 (Definition 1....
24.05.2018 08:36:26 9WZDNCRFHVQM-MICROSOFT.WINDOWSCOMMUNICATIONSAPPS
24.05.2018 08:34:30 9N4WGH0Z6VHQ-Microsoft.HEVCVideoExtension
24.05.2018 08:34:24 9WZDNCRFJ2QK-ZDFGemeinntzigeAnstaltdes.ZDFmediathek
23.05.2018 11:57:42 Definitionsupdate für Windows Defender Antivirus – KB2267602 (Definition 1....
23.05.2018 07:37:11 9WZDNCRFHVQM-MICROSOFT.WINDOWSCOMMUNICATIONSAPPS
23.05.2018 07:36:57 9WZDNCRFJ3PT-MICROSOFT.ZUNEMUSIC
23.05.2018 04:01:11 Definitionsupdate für Windows Defender Antivirus – KB2267602 (Definition 1....
22.05.2018 12:26:55 Definitionsupdate für Windows Defender Antivirus – KB2267602 (Definition 1....
22.05.2018 08:34:28 9NBLGGH5FV99-Microsoft.MSPaint
22.05.2018 08:33:25 9WZDNCRFJ364-MICROSOFT.SKYPEAPP
当您使用 PowerShell 来查询事件,缺省情况下获取到的是日志信息的文本消息。例如,如果您想知道谁登录了您的计算机,您可以使用类似这样的代码(需要管理员权限):
1 | Get-EventLog -LogName Security -InstanceId 4624 | |
结果大概类似这样:
25.04.2018 07:48:41 An account was successfully logged on....
25.04.2018 07:48:40 An account was successfully logged on....
24.04.2018 18:18:17 An account was successfully logged on....
...
这并不是很直观,因为 PowerShell 缩短了输出内容。在类似这样的情况下,您可能需要将结果用管道传给 Format-List
:
1 | Get-EventLog -LogName Security -InstanceId 4624 | |
它现在可以生成详细的数据了:
1 | PS> Get-EventLog -LogName Security -InstanceId 4624 | |
这个结果很难处理。如果您希望基于这段文本做一些自动化处理,您需要解析这段文本。
有一个简单得多的方法:您见到的消息只是一个文本模板,Windows 以“替换字符串”的方式插入相关的信息。他们是从 Get-0EventLog
接收到的事件数据的一部分。该数据存在一个数组中,整个数组对应一个事件 ID 的信息。
当您确定了哪个信息存放在哪个数组元素中,要解析出您关心的信息十分容易:
1 | Get-EventLog -LogName Security -InstanceId 4624 | |
当您运行这一小段代码时,它返回只包含您需要的、美观的验证信息:
12.05.2018 17:38:58 SYSTEM\NT-AUTORITÄT Negotiate C:\Windows\System32\services.exe
12.05.2018 17:38:58 tobweltner@zumsel.local\InternalAccount Negotiate C:\Windows\System32\svchost.exe
12.05.2018 17:38:58 SYSTEM\NT-AUTORITÄT Negotiate C:\Windows\System32\services.exe
12.05.2018 17:38:58 SYSTEM\NT-AUTORITÄT Negotiate C:\Windows\System32\services.exe
12.05.2018 17:38:53 SYSTEM\NT-AUTORITÄT Negotiate C:\Windows\System32\services.exe
PowerShell 带来了一系列硬编码的类型加速器,它们的效果就像通常使用的 .NET 类型,而且由于它们比原始数据类型名称短很多,所以它们“加快了打字速度”。
一个很少人知道的事实是类型加速器列表是可以扩展的。以下代码添加一个新的名为 “SuperArray” 的类型加速器,它指向 “System.Collections.ArrayList”。
您现在可以创建一个新的“超级数组”(它用起来像普通的数组,但是拥有一系列额外的方法来向指定的位置增删元素,而且附加数组元素也比普通的数组快得多):
1 | [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Add('SuperArray', [System.Collections.ArrayList]) |
您还可以将一个普通数组转换成“超级数组”:
1 | PS> $a = [superarray](1,2,3) |
请注意虽然不用类型加速器也可以完成这项任务。但是得敲这么长的代码:
1 | PS> $a = [System.Collections.ArrayList](1,2,3) |
“类型加速器”类似 .NET 类型别名。它们的目的是节约打字。例如,[ADSI]
“类型”实际上并不存在。它只不过是 System.DirectoryServices.DirectoryEntry
的别名。您可以将 [ADSI]
替换为 [System.DirectoryServices.DirectoryEntry]
:
1 | PS> [ADSI].FullName |
由于类型加速器是硬编码进 PowerShell 中的,所以使用它们是安全的。以下这行代码将显示所有预定义的类型加速器,如果您想使用 .NET 类型,您可以选用列表中的内容,因为它们在 PowerShell 中都很重要:
1 | PS> [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get |
您是否曾希望将文本直接发送到记事本,而并不将它保存到文件中?
通常,您需要将文本保存到一个文件,然后通知它读取文件。还有一个更特别的方法:通过 Windows 消息和记事本通信,将文字发送到记事本。这是 Out-Notepad
函数的代码:
1 | #requires -Version 2 |
这是它的使用方法:
1 | PS> Get-Service | Out-Notepad |
这两行代码,都能打开一个全新的 Notepad 实例,所有服务信息都写入 Notepad。请注意它们的不同:第一行代码创建一个对象名称的列表。如果您希望对象的显示像在 PowerShell 中那样详细,请确保将他们通过管道送给 Notepad 之前先将它们用管道送给 Out-String
。