7

更新是从本地服务器下载的,而不是从 WUS 或 Microsoft 存储库下载的。本地服务器基于 Linux,每个更新的内容都基于哪个主机。

我不使用UpdateDownloader从 Microsoft 服务器下载,我手动下载更新内容,然后使用CopyToCache.

这些安装得很好

Windows XP、Server 2003、Vista、Server 2008 x86 上的 Microsoft .NET Framework 3.5 SP1 安全更新 (KB2736416)

Microsoft Visual Studio 2010 安全更新 (KB2542054)

这些没有

XP、Server 2003、Vista、Windows 7、Server 2008 x86 上的 Microsoft .NET Framework 4 安全更新 (KB2840628)

Windows XP、Server 2003、Vista 和 Server 2008 x86 上的 Microsoft .NET Framework 3.5 SP1 更新 (KB2836940)

我的流程如何运作

我从本地服务器收到此安装信息,我用它来下载更新的所有下载内容。(KB2840628上方的块引用文本是下面提供的示例)

{
  "app_uris": [
    {
      "file_name": "msipatchregfix-x86_94a84b80b8b45a1ac53a0e5d085513da0f099655.exe",
      "file_uri": "https://192.168.5.108/packages/d13c13c81f94fbb48f39c817a71ff239a31773d3a0e821a968dc42a913892841/msipatchregfix-x86_94a84b80b8b45a1ac53a0e5d085513da0f099655.exe",
      "file_size": 130600
    },
    {
      "file_name": "ndp40-kb2840628-v2-x86_891d50ff3c1322db3fb0fde222ebb0aaa5260272.exe",
      "file_uri": "https://192.168.5.108/packages/d13c13c81f94fbb48f39c817a71ff239a31773d3a0e821a968dc42a913892841/ndp40-kb2840628-v2-x86_891d50ff3c1322db3fb0fde222ebb0aaa5260272.exe",
      "file_size": 13294216
    }
  ],
  "app_id": "d13c13c81f94fbb48f39c817a71ff239a31773d3a0e821a968dc42a913892841",
  "app_name": "Security Update for Microsoft .NET Framework 4 on XP, Server 2003, Vista, Windows 7, Server 2008 x86 (KB2840628)"
}

话虽如此,问题是某些更新安装得非常好,但某些更新(我相信有多个更新bundle-updates)没有通过,这让我发疯!

我首先下载每个Uri,然后将它们加载到更新中CopyToCache

  var collection = new UpdateCollection();
  IList<string> updateFiles = Directory.GetFiles(updateFolder);
  var fileCollection = new StringCollection();

  try
  {
       foreach (var file in updateFiles)
               fileCollection.Add(file);

       //Error happens here on certain updates. Not all.
       ((IUpdate2)update.BundledUpdates[0]).CopyToCache(fileCollection);
       collection.Add(update);
       return collection;
  }
  catch (Exception e)
  {
     return null;
  }

在此之后,返回的集合通过我的WindowsUpdateInstaller方法传递,如下所示:

IUpdateSession Session = new UpdateSession();
var updatesToInstall = //THIS GETS THE RETURN FROM THE ABOVE CODE...
var installer        = (IUpdateInstaller2)Session.CreateUpdateInstaller();

installer.ForceQuiet         = true;
installer.AllowSourcePrompts = false;
installer.Updates            = updatesToInstall;

foreach (IUpdate updateNode in installer.Updates)
{
   updateNode.AcceptEula();
}

//FAILS HERE WITH "-2145124318, Result code: orcFailed",
var installationRes = installer.Install(); 
var installResult   = installationRes.GetUpdateResult(0);

如果我手动双击可执行文件并在不使用代码的情况下手动安装,则更新安装得很好。

4

1 回答 1

3

似乎拥有多个级别的WUApi暴露。以前,我只是简单地检索顶层,这样做会使某些更新由于缺少更新所需的内容而失败;大多数 Windows 更新都有超过 1 级的捆绑包。IUpdatebundleUpdatesbundleUpdates

例如,想象一下这个树状结构,用于 1 次更新(又名 IUpdate):

Update 1
    ---> Bundle 1
       *URL 1
       *URL 2
         ----> Bundle 1A
               *URL 1
               *URL 2
               *URL 3

    ---> Bundle 2
       *URL 1
         ----> Bundle 2A
               *URL 1
               *URL 2
         ----> Bundle 2B
               *URL 1

   ----> Bundle 3
         *URL 1
          ----> Bundle 3A
                *URL 1
                *URL 2

我的解决方案是创建一个递归函数来单独解析每个更新,并将所有 URI 保存在键类型“ bundleName”和list of values 的字典中,该字典将保存该特定包的所有 URI。

像这样:

Dictionary<string, List<string>>

递归函数如下:

 private static Dictionary<string, List<string>> GetAllUpdates(IUpdate iUpdate)
        {
            var bundleDict = new Dictionary<string, List<string>>();

            foreach (IUpdate bundle in iUpdate.BundledUpdates)
            {
                foreach (IUpdateDownloadContent udc in bundle.DownloadContents)
                {
                    var downloadContents = new List<string>();
                    if (String.IsNullOrEmpty(udc.DownloadUrl))
                        continue;

                    var url = udc.DownloadUrl;
                    downloadContents.Add(url);

                    if (!bundleDict.ContainsKey(bundle.Title))   
                        bundleDict.Add(bundle.Title, downloadContents);
                }

                if (bundle.BundledUpdates.Count > 0)
                {
                    var valuesReturned = GetAllUpdates(bundle);
                    foreach (var data in valuesReturned)
                    {
                      if(!bundleDict.ContainsKey(data.Key))     
                         bundleDict.Add(data.Key, data.Value);
                    }

                }
            }

            return bundleDict;
        }
于 2013-10-03T16:18:36.893 回答