我正在Powershell中编写一个脚本,以从每台计算机获取更新信息,并将信息与另一个通过CVE ID识别更新的系统相关联。我发现在WSUS中有一个“CVEIDs”属性用于更新,这在MSDN中有记录,但我不知道如何访问该属性。从WSUS中检索CVE ID是这个脚本的关键,所以我希望有人可以提供帮助!
以下是我无法访问的属性:
IUpdate2 :: CveIDs属性 - http://msdn.microsoft.com/en-us/library/aa386102(VS.85).aspx
根据这个,接口IUpdate2需要IUnknown :: QueryInterface方法 - “http://msdn.microsoft.com/en-us/library/ee917057(PROT.10).aspx”
“可以通过调用IUpdateCollection :: Item(opnum 8)(第3.22.4.1节)方法来检索IUpdate实例。
客户端可以使用IUnknown :: QueryInterface方法获取IUpdate2,IUpdate3,IUpdate4或IUpdate5接口。此外,如果更新是驱动程序,则客户端可以使用IUnknown :: QueryInterface方法获取IWindowsDriverUpdate,IWindowsDriverUpdate2,IWindowsDriverUpdate3,IWindowsDriverUpdate4或IWindowsDriverUpdate5接口。 “
这是我的代码的骨架:
[System.Reflection.Assembly] :: LoadWithPartialName(“Microsoft.UpdateServices.Administration”)|出空
if(!$ wsus) {
$ wsus = [Microsoft.UpdateServices.Administration.AdminProxy] :: GetUpdateServer($ server,$ false,$ port) }
$ computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope $ updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope $ updateScope.UpdateSources = [Microsoft.UpdateServices.Administration.UpdateSources] :: MicrosoftUpdate $ wsusMachines = $ wsus.GetComputerTargets($ computerScope)
$ wsusMachines | ForEach-Object { 写主机$ .FullDomainName $ updates = $ .GetUpdateInstallationInfoPerUpdate($ updateScope)
$ updates | ForEach-Object { $ update = $ wsus.GetUpdate($ .UpdateId)#返回实现Microsoft.UpdateServices.Administration.IUpdate的对象 $ updateTitle = $ update.Title |写主机 $ updateInstallationState = $ .UpdateInstallationState |写主机 $ updateSecurityBulletin = $ update.SecurityBulletins |写主机 $ updateCveIds = $ update.CveIDs #ERROR:属性'CveIDs'属于IUpdate2,不属于IUpdate } }
答案 0 :(得分:0)
我不熟悉此API,但在COM查询界面的情况下,请尝试使用PowerShell中的强制转换来检索实现IUpdate的对象:
[Microsoft.UpdateServices.Administration.IUpdate2]$wsus.GetUpdate($.UpdateId)
答案 1 :(得分:0)
您可以尝试使用我的get-interface脚本,它可能会工作,但我猜它不会像powershell munges和特殊情况的COM对象。您的里程可能会有所不同:
function Get-Interface {
#.Synopsis
# Allows PowerShell to call specific interface implementations on any .NET object.
#.Description
# Allows PowerShell to call specific interface implementations on any .NET object.
#
# As of v2.0, PowerShell cannot cast .NET instances to a particular interface. This makes it
# impossible (shy of reflection) to call methods on explicitly implemented interfaces.
#.Parameter Object
# An instance of a .NET class from which you want to get a reference to a particular interface it defines.
#.Parameter InterfaceType
# An interface type, e.g. [idisposable], implemented by the target object.
#.Example
# // a class with explicitly implemented interface
# public class MyObj : IDisposable {
# void IDisposable.Dispose()
# }
#
# ps> $o = new-object MyObj
# ps> $i = get-interface $o ([idisposable])
# ps> $i.Dispose()
#.ReturnValue
# A PSCustomObject with ScriptMethods and ScriptProperties representing methods and properties on the target interface.
#.Notes
# AUTHOR: Oisin Grehan http://www.nivot.org/
# LASTEDIT: 2009-03-28 18:37:23
# REVISION: 0.2
[CmdletBinding()]
param(
[parameter(valuefrompipeline=$true, position=0)]
[ValidateNotNull()]
$Object,
[parameter(position=1)]
[ValidateScript( { $_.IsInterface } )]
[type]$InterfaceType
)
$script:t = $Object.GetType()
try {
$script:m = $t.GetInterfaceMap($InterfaceType)
} catch [argumentexception] {
throw "Interface $($InterfaceType.Name) not found on ${t}!"
}
$script:im = $m.InterfaceMethods
$script:tm = $m.TargetMethods
# TODO: use param blocks in functions instead of $args
# so method signatures are visible via get-member
$body = {
param($o, $i)
$script:t = $o.GetType()
$script:m = $t.GetInterfaceMap($i)
$script:im = $m.InterfaceMethods
$script:tm = $m.TargetMethods
for ($ix = 0; $ix -lt $im.Count; $ix++) {
$mb = $im[$ix]
# for the function body, we close over $ix to capture the index
# so even on the next iteration of this loop, the $ix value will
# be frozen within the function's scriptblock body
set-item -path function:script:$($mb.Name) -value {
# call corresponding target method
$tm[$ix].Invoke($o, $args)
}.GetNewClosure() -verbose -force
if (!$mb.IsSpecialName) {
# only export the function if it is not a getter or setter.
Export-ModuleMember $mb.Name -verbose
}
}
}
write-verbose $body.tostring()
# create dynamic module
$module = new-module -ScriptBlock $body -Args $Object, $InterfaceType -Verbose
# generate method proxies - all exported members become scriptmethods
# however, we are careful not to export getters and setters.
$custom = $module.AsCustomObject()
# add property proxies - need to use scriptproperties here.
# modules cannot expose true properties, only variables and
# we cannot intercept variables get/set.
$InterfaceType.GetProperties() | % {
$propName = $_.Name
$getter = $null
$setter = $null
if ($_.CanRead) {
# where is the getter methodinfo on the interface map?
$ix = [array]::indexof($im, $_.GetGetMethod())
# bind the getter scriptblock to our module's scope
# and generate script to call target method
#
# NOTE: we cannot use a closure here because sessionstate
# is rebound to the module's, and $ix would be lost
$getter = $module.NewBoundScriptBlock(
[scriptblock]::create("`$tm[{0}].Invoke(`$o, @())" -f $ix))
}
if ($_.CanWrite) {
# where is the setter methodinfo on the interface map?
$ix = [array]::indexof($im, $_.GetSetMethod())
# bind the setter scriptblock to our module's scope
# and generate script to call target method
#
# NOTE: we cannot use a closure here because sessionstate
# is rebound to the module's, and $ix would be lost
$setter = $module.NewBoundScriptBlock(
[scriptblock]::create(
"param(`$value); `$tm[{0}].Invoke(`$o, `$value)" -f $ix))
}
# add our property to the pscustomobject
$prop = new-object management.automation.psscriptproperty $propName, $getter, $setter
$custom.psobject.properties.add($prop)
}
# insert the interface name at the head of the typename chain (for get-member info)
$custom.psobject.TypeNames.Insert(0, $InterfaceType.FullName)
# dump our pscustomobject to pipeline
$custom
}