我遇到了一个我似乎弄不清楚的问题。我有这段代码,它能做我想要的。它搜索已安装并具有特定UpdateID的Windows更新。
param(
$updateId = $false,
$hostName = $false
)
if(($updateId -eq $false) -or ($hostName -eq $false))
{
Write-Host "checkUpdateInstalled.ps1 -updateId <updateIdValue> -hostName <Remote Host Name>"
exit
}
Invoke-Command -ComputerName $hostName -ScriptBlock {
$searcher = New-Object -ComObject Microsoft.Update.Searcher
$searcher.Search("IsInstalled=1 AND UpdateID='$Using:updateId'")
$tmp.Updates| ForEach-Object {
$i++
Write-Host "UpdateInfo Update No. $i"
Write-Host "Title: `t`t" $_.Title
Write-Host "Description: `t`t " $_.Description
Write-Host "UpdateID: `t`t " $_.Identity.UpdateID
Write-Host "RevisionNumber: `t`t " $_.Identity.RevisionNumber
Write-Host "KBArticleIDs: `t`t " $_.KBArticleIDs
Write-Host "==============================================="
}
}
有了这个解决方案,我不能在Invoke-Command
之外使用$tmp.Updates
,但我试图用ForEach-Object
循环收集的信息工作得很好。在这种情况下,打印$tmp.Updates
可以提供有关特定更新的信息。
所以我尝试了以下方法来访问$tmp
:
## Same top part
$tmp = Invoke-Command -ComputerName $hostName -ScriptBlock {
$searcher = New-Object -ComObject Microsoft.Update.Searcher
$searcher.Search("IsInstalled=1 AND UpdateID='$Using:updateId'")
}
$tmp.Updates| ForEach-Object {
$i++
Write-Host "UpdateInfo Update No. $i"
Write-Host "Title: `t`t" $_.Title
Write-Host "Description: `t`t " $_.Description
Write-Host "UpdateID: `t`t " $_.Identity.UpdateID
Write-Host "RevisionNumber: `t`t " $_.Identity.RevisionNumber
Write-Host "KBArticleIDs: `t`t " $_.KBArticleIDs
Write-Host "==============================================="
}
在此尝试中,循环不打印信息。如果我想打印$tmp.Updates
,我得到的是System.__ComObject
。
有人能理解吗?
这就是Invoke-Command
的设计。
Invoke-Command
不返回远程会话的对象。相反,它返回对象经过多个进程后的表示形式。
首先在远程环境上序列化,然后在本地环境上反序列化。
这是所有传播的东西。在序列化方面,有一些基本类型会被反序列化为"活"类型。对象,例如:
- Byte, SByte, Byte[]
- Int16, Int32, Int64, UInt16, UInt32, Uint64 十进制,单,双
- 时间跨度,日期时间,进度记录
- Char, String, XmlDocument, SecureString
- Boolean,Guid, Uri, Version
那么你就有了没有完全保真地反序列化的类型,但在大多数实际用途中表现为基本类型。
这包括enum,它被反序列化为底层整数。类似地,反序列化器将保留列表的内容,但可能会更改容器的实际类型。(例如:列表反序列化为数组列表,字典反序列化为哈希表,等等…)
最后,你也有一些物体被重新水合成它们的活体。例如,IP地址对象被序列化,然后被反序列化为Deserialized.System.Net.IPAddress
,并通过"rehydration"再次转换为其原始类型,该过程规定了如何再次转换反序列化类型。
对于某些PowerShell类型,有一些内置的补水功能…:
- PSPrimitiveDictionary
- SwitchParameter
- PSListModifier
- PSCredential
以及基类库中的某些类型:
- IPAddress, MailAddress
- CultureInfo
- X509Certificate2, X500DistinguishedName
- 目录安全、文件安全、注册安全
因此,要执行您所查找的操作,您需要返回可序列化的对象。您需要深入COM对象并返回所需的属性值。您可以使用Get-Member
来确定可用的属性,并从那里返回您想要的内容。
您也可以在远程对象上使用ConvertTo-Json
来返回它的json表示,并在本地将其转换回PSObject。在类型方面,您也不会得到准确的表示,但您可能会得到更好的属性/值视图。如果需要,不要忘记将-Depth
参数设置为更高的数字,因为默认是4层深度。
参考
Microsoft Dev-blogs - object是如何从远程地址发送和发送的
返回的序列化对象的深度似乎有限制(没有方法)。这对我来说是有效的,直接返回updates子属性。否则"updates"变成字符串数组。虽然我会使用"get-ciminstance win32_quickfixengineing& quot;相反。
$tmp = Invoke-Command localhost { # elevated
$searcher = New-Object -ComObject Microsoft.Update.Searcher
$searcher.Search('IsInstalled=1')
}
$tmp.Updates
System.__ComObject
System.__ComObject
System.__ComObject
...
$tmp.Updates[0].gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
$tmp = Invoke-Command localhost { # elevated
$searcher = New-Object -ComObject Microsoft.Update.Searcher
$searcher.Search('IsInstalled=1').updates
}
$tmp | % title
MSXML 6.0 RTM Security Update (925673)
Update for Microsoft Report Viewer Redistributable 2010 Service Pack 1 (KB2549864)
Security Update for Microsoft Visual C++ 2005 Service Pack 1 Redistributable Package (KB2538242)
...
返回你想要的属性…
Invoke-Command localhost { # elevated
$searcher = New-Object -ComObject Microsoft.Update.Searcher
$searcher.Search('IsInstalled=1').updates | select title, description,
@{n='UpdateID'; e={$_.Identity.UpdateID}},
@{n='RevisionNumber';e={$_.Identity.RevisionNumber}}, KBArticleIDs
}
Title : Update for Windows Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2001.10)
Description : This package will update Windows Defender Antivirus antimalware platform’s components on the user machine.
UpdateID : c01629fc-64ea-45f3-b7cb-cabc7d566933
RevisionNumber : 200
KBArticleIDs : {4052623}
PSComputerName : localhost
RunspaceId : 57b3ae43-6ee6-4e0c-add1-d9d82aba3f61
invoke-command localhost { get-ciminstance win32_quickfixengineering }
Source Description HotFixID InstalledBy InstalledOn PSComputerName
------ ----------- -------- ----------- ----------- --------------
Update KB5013887 NT AUTHORITYSYSTEM 6/18/2022 12:00:00 AM localhost
Update KB4562830 NT AUTHORITYSYSTEM 2/1/2021 12:00:00 AM localhost
Update KB4577586 NT AUTHORITYSYSTEM 5/24/2021 12:00:00 AM localhost