PowerShell 技能连载 - 查找已安装和缺失的更新(第四部分)
有些时候,Microsoft.Update.Session
对象可以用来检查一台机器上是否安装了某个更新。有些作者用这种方法查询更新的标题字符串:
1 | #requires -Version 3.0 |
请注意这个方法不仅更快,而且由于它将任务分成两个函数,所以您还可以读出所有已安装的更新标题:
1 | PS> Get-UpdateInstalled -KBNumber 2267602 |
有些时候,Microsoft.Update.Session
对象可以用来检查一台机器上是否安装了某个更新。有些作者用这种方法查询更新的标题字符串:
1 | #requires -Version 3.0 |
请注意这个方法不仅更快,而且由于它将任务分成两个函数,所以您还可以读出所有已安装的更新标题:
1 | PS> Get-UpdateInstalled -KBNumber 2267602 |
当您想检查系统中已安装的更新,与其搜索在线更新,并和本地安装的更新比对,更好的方法是查询本地更新历史。
以下代码返回系统中所有已存在的更新。它不需要在线连接。
1 | #requires -Version 2.0 |
当 PowerShell 通过 Microsoft.Update.Session
对象向 Windows 请求更新时,一些信息似乎无法读取。以下代码获取已安装的更新信息。而 KBArticleIDs
只是显示为 ComObject
。
1 | #requires -Version 2.0 |
要解决这个问题,请使用计算属性。它能将无法读取的 COM 对象通过管道传给 Out-String
命令。通过这种方法,PowerShell 内部的内部逻辑使用它的魔力来解析 COM 对象内容:
1 | #requires -Version 2.0 |
Windows 可以自动确定系统中缺失的更新,在有 Internet 连接的情况下。PowerShell 可以使用相同的系统接口来查询该信息。以下代码返回系统中所有已安装的更新:
1 | #requires -Version 2.0 |
要查看缺失的更新,请将 IsInstalled=1
改为 IsInstalled=0
:
1 | #requires -Version 2.0 |
在前一个技能中我们介绍了自 PowerShell 3 以上版本支持的 PreCommandLookupAction
。今天我们将介绍一个特别的实现。
当您运行一下代码时,PowerShell 将会接受所有以 “*” 开头的命令并将命令的输出记录到一个文本文件中。当命令执行完毕,将会打开该文本文件。
现在您可以运行 *dir
来代替 dir
,来保存结果,或用 *Get-Process
代替 Get-Process
。
1 | $ExecutionContext.SessionState.InvokeCommand.PreCommandLookupAction = { |
PowerShell 有一系列“秘密”的(更好的说法是没有在文档中体现的)设置。一个是 PreCommandLookupAction
,它有一个很强的功能:当 PowerShell 一旦准备好执行一个命令时,就会先执行这个操作。
您的事件处理器可以调整、改变,操作护原始的命令,以及提交给它的参数。
今天我们将用这个简单的特性来秘密地将一个命令替换成另一个:
1 | $ExecutionContext.SessionState.InvokeCommand.PreCommandLookupAction = { |
这个事件处理器寻找 Get-Service
命令,并将它替换成 dir
。所以当您运行 Get-Service
时,会变成获得一个文件夹列表。当然,这是没有实际意义的,正常情况下应该使用 alias 别名。下一个技巧中,我们将演示一些更有用的例子。
在前一个技能中我们了解了 ConvertFrom-StringData
如何将纯文本的键值对转换为哈希表。还缺少另一个方向的操作:将哈希表转为纯文本。有了它以后,您就拥有了一个将设置和信息保存到文件的小型框架。
我们首先创建一个包含一些数据的哈希表:
1 | $test = @{ |
结果看起来如下:
1 | Name Value |
以下是名为 ConvertFrom-Hashtable
的函数,传入一个哈希表,并将它转换为纯文本:
1 | filter ConvertFrom-Hashtable |
让我们看看哈希表是如何转换的:
1 | PS> $test | ConvertFrom-Hashtable |
您可以用 ConvertFrom-StringData
转换到另一种形式:
1 | PS> $test | ConvertFrom-Hashtable | ConvertFrom-StringData |
所以基本上,您可以将哈希表保存为纯文本,并在稍后使用它:
1 | $test = @{ |
请注意这种方法对简单的字符串和数字型数据有效。它不能处理复杂数据类型,因为这个转换操作并不能序列化对象。
在前一个技能中我们使用了 ConvertFrom-StringData
来将纯文本键值对转换为哈希表。
以下是一个转换失败的例子:
1 | $settings = @' |
当您查看结果时,很快能发现失败的原因:
1 | Name Value |
显然,ConvertFrom-StringData
将 “\
“ 视为一个转义符,在上述例子中增加了一个制表符 (“\t
“),并吃掉了字面量 “t”。
要解决这个问题,请始终将 “\
“ 转义为 “\\
“。以下是正确的代码:
1 | $settings = @' |
现在结果看起来正确了:
1 | Name Value |
假设您需要将设置用最简单的方式保存到一个文件中。设置文件可能看起来像这样:
1 | $settings = ' |
您可以将这些设置用 Set-Content
保存到文件中,并用 Get-Content
再把它们读出来。
那么,如何解析该信息,来存取独立的项目呢?有一个名为 ConvertFrom-StringData
的 cmdlet,可以将键值对转化为哈希表:
1 | $settings = @' |
在前一个技能中我们演示了一段代码,可以在后台线程中更新 PowerShell 标题栏,显示一个实时时钟。
难道不能更完美一点,显示当前的路径位置?挑战之处在于,如何让后台线程知道前台 PowerShell 的当前路径?
有一个名为 $ExecutionContext
的 PowerShell 变量可以提供关于上下文状态的各种有用信息,包括当前路径。我们将 $ExecutionContext
从前台传递给后台线程,该后台线程就可以显示当前前台的路径。
试试看:
1 | $code = |
当您运行这段代码时,PowerShell 的状态栏显示当前路径和实时时钟。当您切换当前路径时,例如运行 “cd c:\windows
“,标题栏会立刻更新。
用以上代码可以处理许多使用场景: