PowerShell 技能连载 - 从本地时间以 ISO 格式创建 UTC 时间
如果您的工作是跨国跨时区的,您可能会需要使用 UTC 时间来代替本地时间。要确保时间格式是语言中性的,我们推荐使用 ISO 格式。以下是使用方法:
1 | $date = Get-Date |
如果您的工作是跨国跨时区的,您可能会需要使用 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
。
Format-List
缺省以列表的形式显示对象的属性,如果某个属性包含一个数组,该数组将会转换为文本,而且只显示一小部分数组元素。以下是一个例子:
1 | PS> Get-Process -Id $Pid | Format-List -Property Name, Modules |
这行代码获取 PowerShell 的进程,并且显示它的名称和加载的模块。如您所见,输出的结果并没有显示所有加载的模块。
有一个名为 FormatEnumerationLimit
的神秘变量,控制 Format-List
显示多少个数组元素。
缺省情况下,显示个数限制为 4 个,所以输出结果中最多显示 4 个数组元素。如果将限制值设为 -1,事实上相当于关闭了该限制:
1 | PS> $FormatEnumerationLimit |
如果您再次运行相同的命令,Format-List
将显示所有数组元素:
1 | PS> Get-Process -Id $Pid | Format-List -Property Name, Modules |
如果您想运行一个长时间执行的脚本,何不先关闭显示器,而是傻傻地等着超时以后显示屏保呢?
以下是一个简单的函数,能够立即关闭显示器。只需要移动鼠标或按任意键就可以唤醒:
1 | function Set-DisplayOff |
以下是一个简单的例子,演示如何向网络适配器分配 IP 地址、网关,和 DNS 服务器。这段脚本列出所有活动的网络适配器。当您选择一项并点击确认,脚本将把硬编码的地址赋给网络适配器。
请注意一下脚本只是模拟改变网络配置。如果您希望真的改变网络设置,请移除 -WhatIf
参数:
1 | $NewIP = '192.168.2.12' |
即便是有经验的 PowerShell 用户也会经常忽略 PowerShell 强大的帮助系统,它类似 Linux 中的 man page。您所需要做的只是一次性下载帮助文件。要下载帮助文件,您需要在提升权限的 PowerShell 中运行以下代码:
1 | PS> Update-Help -UICulture en-us -Force |
当帮助文件下载完以后,以下是一个很棒的基础列表,展示 PowerShell 语言的几乎所有细节:
1 | PS> Get-Help about* | Select Name, Synopsis |
您甚至可疑用这行代码创建您自己的 PowerShell 帮助查看器:
1 | Get-Help about* | |
当运行这行代码时,PowerShell 将搜索帮助主题并打开一个网格视图。只需要按住 CTRL
并选择所有您想阅读的主题,然后单击确认。选中的主题将会在独立的帮助查看窗口中打开。