简体   繁体   English

Windows 更新 API CopyToCache(IStringCollection) - 指定的转换无效

[英]Windows Update API CopyToCache(IStringCollection) - Specified cast is not valid

For reducing traffic on our VPN routes, I need to download the windows updates from an external server while reporting to our internal server.为了减少我们的 VPN 路由上的流量,我需要从外部服务器下载 windows 更新,同时向我们的内部服务器报告。

So I'm doing the following:所以我正在做以下事情:

Create an UpdateSession and Search for Updates, storing them in $SearchResult.创建一个 UpdateSession 并搜索更新,将它们存储在 $SearchResult 中。 Then I download the Updates from an external Server and then I want to pass them into the Windows Update Api via IUpdate2.CopyToCache(IStringCollection)然后我从外部服务器下载更新,然后我想通过IUpdate2.CopyToCache(IStringCollection)将它们传递到 Windows 更新 Api

Everything is just fine, except passing the StringCollection into the Method CopyToCache and it just ends up with an 'Specified cast is not valid.'-Error.一切都很好,除了将 StringCollection 传递给方法 CopyToCache 并且它最终以“指定的强制转换无效。”-错误结束。

This is my code:这是我的代码:

Thank's for help!感谢帮助! eldo-ob埃尔多奥布

$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
$UpdateCollection = New-Object -Com Microsoft.Update.UpdateColl

$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
$AvailibleUpdates = [int16]$SearchResult.Updates.Count

$AvailibleUpdates

$WebClient = New-Object System.Net.WebClient

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

@($SearchResult.Updates.Item(0).BundledUpdates) | Foreach { 
    $_.DownloadContents | Foreach { 
        $FileName = $_.DownloadUrl.Split("/")[-1]
        $downloadFrom = $_.DownloadUrl.Replace("http://contoso-intern.com","https://contoso-extern.com")
        $WebClient.DownloadFile($downloadFrom,("C:\temp\WSUS\{0}" -f $FileName))
        Write-Host "File Downloaded" -ForegroundColor Green
    }
    $StringCollection = New-Object System.Collections.Specialized.StringCollection
    $StringCollection.Add(("C:\temp\WSUS\{0}" -f $FileName))
    $_.CopyToCache($StringCollection)
}

Error Msg:错误消息:

Specified cast is not valid.
At line:24 char:19
+ $_.CopyToCache($StringCollection)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], InvalidCastException
    + FullyQualifiedErrorId : System.InvalidCastException

Update / Solution:更新/解决方案:

# create UpdateSession
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
# create UpdateSearcher
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()

# search for updates & count updates
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
$AvailibleUpdates = [int16]$SearchResult.Updates.Count

# create an WebClient instance for downloading Updates from alternative source
$WebClient = New-Object System.Net.WebClient

# fix some tls issues (not for everyone neccessary) 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# iterate the updates in searchresult
$SearchResult.Updates | ForEach-Object {
    # iterate bundledupdates
    $_.BundledUpdates | ForEach-Object {
        # create COM stringcollection
        $StringCollection = New-Object -ComObject "Microsoft.Update.StringColl.1"
        # iterate downloadcontents
        $_.DownloadContents | ForEach-Object { 
            # get the filename from url
            $FileName = $_.DownloadUrl.Split("/")[-1]
            # create external downloadlink
            $downloadFrom = $_.DownloadUrl.Replace("http://contoso-intern.com","https://contoso-extern.com/wsusreplica")
            # download update with webclient
            $WebClient.DownloadFile($downloadFrom,("C:\temp\WSUS\{0}" -f $FileName))
            # adding downloaded filepath to stringcollection
            $StringCollection.Add(("C:\temp\WSUS\{0}" -f $FileName))
        }
        # copy downloaded file to cache (load into wuapi)
        $_.CopyToCache($StringCollection)
    }
}

# create installer
$Installer = $UpdateSession.CreateUpdateInstaller()
# set the updates
$Installer.Updates = $SearchResult.Updates
# and install
$Installer.Install()

The updates where successfuly installed without using the UpdateDownloader from a self choosen location.在不使用自选位置的 UpdateDownloader 的情况下成功安装的更新。 So now I'm able to report and search updates through the vpn-tunnel and download the updates from an external source, where we can route the traffic beside the vpn tunnel.所以现在我可以通过 vpn 隧道报告和搜索更新,并从外部源下载更新,我们可以在 vpn 隧道旁边路由流量。

You are using a .NET object.您正在使用 .NET object。 After searching the registry for the interface, then looking up the TypeLib for the interface, it pointed to the wuapi.dll.在注册表中搜索接口后,然后查找接口的TypeLib,它指向了wuapi.dll。 I then searched for COM objects that use wuapi.dll as their InprocServer32.然后我搜索了使用 wuapi.dll 作为其 InprocServer32 的 COM 对象。 I found "Microsoft.Update.StringColl.1".我找到了“Microsoft.Update.StringColl.1”。 It has an Add() method, so it should work the same in the code as your other method (I think).它有一个Add()方法,因此它在代码中的工作方式应该与您的其他方法相同(我认为)。 So, replace where you initialize the $StringCollection with this:因此,将初始化 $StringCollection 的位置替换为:

$StringCollection = new-object -ComObject "Microsoft.Update.StringColl.1"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM