PowerShell 技能连载 - 查找已安装的更新(第 2 部分)
Windows 更新客户端维护了它自己的已安装更新。下面的示例代码不是查询一般的系统事件日志,也不是主动搜索可能需要一些时间的更新,而是查询和读取 Windows Update 客户端的安装历史:
1 | $Session = New-Object -ComObject Microsoft.Update.Session |
Windows 更新客户端维护了它自己的已安装更新。下面的示例代码不是查询一般的系统事件日志,也不是主动搜索可能需要一些时间的更新,而是查询和读取 Windows Update 客户端的安装历史:
1 | $Session = New-Object -ComObject Microsoft.Update.Session |
Get-Hotfix
返回已安装的更新,但实际上只是 Win32 Win32_QuickFixEngineering
WMI 类的一个包装器。它并不会返回所有已安装的更新。
一个更好的方法可能是查询事件日志:
1 | Get-EventLog -LogName System -InstanceId 19 | |
虽然这可能不完整,并且事件日志项有可能被清除。唯一权威的答案可能来自 Windows Update 客户端,它实际上是查看系统中的文件:
1 | $pattern = 'KB\d{6,9}' |
PowerShell 可以使用 Windows Update 客户端相同逻辑查询缺少的更新:
1 | $UpdateSession = New-Object -ComObject Microsoft.Update.Session |
下面是返回更新标题和知识库编号(如果可用)的更复杂的方法:
1 | $UpdateSession = New-Object -ComObject Microsoft.Update.Session |
有没有想过为什么 CPU 负载有时会这么高,或者为什么黑色的窗口会一闪而过?我们可以检查程序启动的事件日志,并找出什么时候什么程序自动启动了:
1 | Get-EventLog -LogName System -InstanceId 1073748869 | |
假设您有管理员特权,以下是一个快速、简单地转储所有登录事件的方法。这样你就可以知道谁登录了一台特定的电脑,以及使用了哪种身份验证类型:
1 | #requires -RunAsAdministrator |
经常有一种情况,URL 重定向到另一个最终的 URL。这种情况下,如果您希望知道一个指定的 URL 究竟指向哪,可以用类似这样的函数:
1 | function Resolve-Url |
例如,最新的 PowerShell 总是在这个 URL 发布:https://github.com/PowerShell/PowerShell/releases/latest
解析这个 URL,就可以获取最新的 URL。这是找到可用的最新 PowerShell 版本的快速方法:
1 | PS C:\> Resolve-Url -url https://github.com/PowerShell/PowerShell/releases/latest |
当您用 PowerShell 从 internet 下载文件,您可能会想知道下载需要多少时间。您可以检查已下载的数据大小,而且在知道总下载尺寸的情况下可以计算进度百分比。
以下是得到文件尺寸的快速方法:
1 | function Get-DownloadSize |
以下是一个示例:
1 | PS> "https://github.com/PowerShell/PowerShell/releases/download/v6.2.1/PowerShell-6.2.1-win-x64.zip" | Get-DownloadSize |
有些时候如果一个脚本能检测按键,而不需要干预脚本和输入,那是很棒的事情。通过这种方式,您可以增加按住 SHIFT
键的逻辑,例如退出脚本或者启用详细日志。在用户数据脚本中,您可以在 PowerShell 启动时根据是否按下某些键加载模块以及进行其它调整。
这归结到一个问题:最好的以及最少干预的检测按键的方式是什么?以下是解决方案:
1 | Add-Type -AssemblyName WindowsBase |
增加了两个缺省的程序集之后,您的脚本可以操作 Windows.Input.Keyboard
类。这个类有一个 IsKeyDown()
方法。它可以检测键盘的按键,并且当该按键当前处于按下状态时会返回 $true
。
以上示例代码持续运行知道用户按下左侧的 SHIFT
键。
在前一个技能中我们介绍了 FileSystemWatcher
对象以及如何用它监控文件夹的变化。不过,为了不错过所有变化,需要使用异步的方法,类似这样:
1 | $FileSystemWatcher = New-Object System.IO.FileSystemWatcher |
在这个例子中,当检测到任何一个变化事件,就会触发一个事件,并且 FileSystemWatcher
继续监听。由 PowerShell 负责响应这个事件,并且它使用一个事件处理器来响应。事件处理器是在后台执行的。
如果不想使用后台事件管理器,请运行这行代码:
1 | Get-EventSubscriber -SourceIdentifier Monitoring1 | Unregister-Event |
请注意每个支持的变更类型会发出不同的事件。在这个例子中,我们关注 “Created
“ 事件,当创建新文件或新文件夹的时候会发出这个事件。要响应其它变化类型,请添加更多的事件处理器。这将返回所有支持的事件名称:
1 | PS C:\> $FileSystemWatcher | Get-Member -MemberType *Event |
以下是一段演示 PowerShell 如何用 FileSystemWatcher
同步地监控一个包含字文件夹的文件夹变化:
1 | $folder = $home |
这段代码将会监测用户配置文件中 FileName
和 LastWrite
属性的变化。
一个同步的监听器会导致 PowerShell 处于忙碌状态,所以要退出监听,需要设置一个 1000ms 的超时值,PowerShell 将会将控制权返回给你,而如果您没有按下 CTRL
+C
,则循环会继续。
请注意同步的 FileSystemWatcher
可能会错过改变:正好当 WaitForChange()
返回时一个文件发生改变,那么在下一次调用 WaitForChange()
之前的文件变化都会丢失。
如果不想错过任何变化,请使用异步的方法(请见下一个技能)。