WUApiLib IUpdateInstaller2产生错误;一些操作系统更新安装其他人扔HResult -2145124318

时间:2013-09-24 19:33:12

标签: c# .net windows-update wuapi

正在从本地服务器而不是从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上的Microsoft .NET Framework 4安全更新,Server 2003,   Vista,Windows 7,Server 2008 x86(KB2840628)

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

我的流程如何运作

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

{
  "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的更新)不会通过,它让我疯了! / p>

我首先下载每个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);

如果我手动双击可执行文件并手动安装它而不使用代码,则更新安装就好了。

1 个答案:

答案 0 :(得分:2)

WUApi似乎公开IUpdate,其中包含bundleUpdates的多个级别。之前,我只是检索bundleUpdates的最高级别,这样做会导致某些更新因更新所需内容丢失而失败;大多数Windows更新都有超过1级的捆绑。

例如,假设这个树状结构为1 Update(又名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

我的解决方案是创建一个Recursive函数来单独解析每个更新,并将所有URI保存在密钥类型“bundleName”和list of value的字典中,该字典将包含该特定包的所有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;
        }