草庐IT

c# - 如何以编程方式检查 Windows 更新的适用性规则?

coder 2023-07-12 原文

通过探索 Windows 更新 .msu 文件的内容(例如,使用 7zip 等工具),您可能会发现一系列文件,这些文件定义了先决条件和 适用规则。例如:

<UpdateIdentity UpdateID="E6CF1350-C01B-414D-A61F-263D14D133B4" RevisionNumber="1" /><Properties UpdateType="Category" /><ApplicabilityRules><IsInstalled><True /></IsInstalled></ApplicabilityRules>
....
<UpdateIdentity UpdateID="2bf7ed9c-6f43-493a-b156-db20f08c44c4" RevisionNumber="101" /><Properties UpdateType="Detectoid" /><Relationships /><ApplicabilityRules><IsInstalled><b.RegSz Key="HKEY_LOCAL_MACHINE" Subkey="SYSTEM\CurrentControlSet\Control\Nls\Language" Value="InstallLanguage" Comparison="EqualTo" Data="0409" /></IsInstalled></ApplicabilityRules>
....
<UpdateIdentity UpdateID="6AECE9A4-19E3-4BC7-A20C-070A5E31AFF4" RevisionNumber="100" /><Properties UpdateType="Detectoid" /><Relationships>
...
<UpdateIdentity UpdateID="3B4B8621-726E-43A6-B43B-37D07EC7019F" /><ApplicabilityRules><IsInstalled><b.WmiQuery Namespace="root\cimv2" WqlQuery="SELECT Manufacturer FROM Win32_ComputerSystem WHERE Manufacturer = 'Samsung Electronics' or Manufacturer = 'Hewlett-Packard' or Manufacturer = 'Gateway'" /></IsInstalled></ApplicabilityRules>
...

现在,给定一个特定的 .msu 文件和我的本地计算机,是否有一种方法可以迭代这些规则并找出是否有一个不满足 - 以及哪个?

我可以为此目的使用 WSUS 3.0 类库吗?或者有没有工具/脚本?

我真正想要的是确切地知道是什么条件导致计算机拒绝某个 Windows 更新 (KB2973201) 并显示消息 The update is not applicable to your computer(这背后的错误代码是WU_E_NOT_APPLICABLE ).

关于更新的这些适用性规则的文档似乎太少了。有什么好的资源吗?

引用资料:

最佳答案

Now, given a certain .msu file and my local computer, is there a way to iterate over those rules and find out if one is not satisfied - and which one?
Can I use WSUS 3.0 Class Library for this purpose? Or is there a tool / script?

您可以 Update Applicability Rules通过 WSUS 3.0 类库,尽管它不提供检查规则是否会通过的功能,除非(我猜)你运行安装程序但它不会告诉你哪个失败了。

Simon 提到 WUAPI 库没有公开内部规则,并且(afaik)没有办法将 WUAPI ResultCodes 与失败的 ApplicabilityRules 相匹配。

不幸的是,Microsoft.Deployment.WindowsInstaller.dll 等库无法处理 MSU 文件,因此我们无法使用“现成”选项。因此,您必须使用代码和 (msu.xml) XML 文件手动执行此操作:

<Updates>
  <UpdateIdentity UpdateID="E6CF1350-C01B-414D-A61F-263D14D133B4" RevisionNumber="1" />
  <Properties UpdateType="Category" />
  <ApplicabilityRules>
    <IsInstalled>
      <True />
    </IsInstalled>
  </ApplicabilityRules>
  <UpdateIdentity UpdateID="2bf7ed9c-6f43-493a-b156-db20f08c44c4" RevisionNumber="101" />
  <Properties UpdateType="Detectoid" />
  <Relationships />
  <ApplicabilityRules>
    <IsInstalled>
      <b.RegSz Key="HKEY_LOCAL_MACHINE" Subkey="SYSTEM\CurrentControlSet\Control\Nls\Language" Value="InstallLanguage" Comparison="EqualTo" Data="0409" />
    </IsInstalled>
  </ApplicabilityRules>
  <UpdateIdentity UpdateID="6AECE9A4-19E3-4BC7-A20C-070A5E31AFF4" RevisionNumber="100" />
  <Properties UpdateType="Detectoid" />
  <Relationships></Relationships>
  <UpdateIdentity UpdateID="3B4B8621-726E-43A6-B43B-37D07EC7019F" />
  <ApplicabilityRules>
    <IsInstalled>
      <b.WmiQuery Namespace="root\cimv2" WqlQuery="SELECT Manufacturer FROM Win32_ComputerSystem WHERE Manufacturer = 'Dell Inc.' or Manufacturer = 'Samsung Electronics' or Manufacturer = 'Hewlett-Packard' or Manufacturer = 'Gateway'" />
    </IsInstalled>
  </ApplicabilityRules>
</Updates>

使用此代码查看哪些 ApplicabilityRules 失败:

private void btnWillPassApplicabilityRules_Click(object sender, EventArgs e)
{
    XDocument doc = XDocument.Load("msu.xml");
    var elements = doc.Element("Updates").Elements("ApplicabilityRules").Elements("IsInstalled").Elements();

    foreach (var element in elements) {
        if (element.ToString().StartsWith("<b.RegSz")) {
            string subKeyName = element.Attribute("Subkey").Value;
            string keyName = element.Attribute("Value").Value;
            string keyValue = element.Attribute("Data").Value;

            //TODO: Leave the Registry Hive "Switch()" upto reader to fully implement
            if (!ValueExistsInRegistry(Registry.LocalMachine, subKeyName, keyName, keyValue)) {
                Console.WriteLine("Install is not applicable as Applicability Rule failed: " + element.ToString());
            }
        }
        else if (element.ToString().StartsWith("<b.WmiQuery")) {
            string nameSpace = element.Attribute("Namespace").Value;
            string wqlQuery = element.Attribute("WqlQuery").Value;
            if (!ValueExistsInWMI(nameSpace, wqlQuery)) {
                Console.WriteLine("Install is not applicable as Applicability Rule failed: " + element.ToString());
            }
        }
    }
}

private bool ValueExistsInRegistry(RegistryKey root, string subKeyName, string keyName, string keyValue)
{
    using (RegistryKey key = root.OpenSubKey(subKeyName)) {
        if (key != null) return keyValue == key.GetValue(keyName).ToString();
    }
    return false;
}

private bool ValueExistsInWMI(string nameSpace, string wqlQuery)
{
    ManagementScope scope = new ManagementScope(String.Format("\\\\{0}\\" + nameSpace, "."), null);  //The "." is for your local PC
    scope.Connect();
    ObjectQuery query = new ObjectQuery(wqlQuery);
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    if (searcher.Get().Count == 0) {
        return false;
    }
    else {
        return true;
    }
    return false;
}
}

在运行适用性规则之前,最好先检查更新是否会通过操作系统 (OS) 和服务包 (SP) 适用性测试。 如果升级不适用于操作系统和 SP,则检查注册表/wmi 等以确定升级是否会通过规则是没有意义的

要查看 ApplicabilityInfo,请运行 expand 命令行实用程序:

expand -f:* "C:\temp\msu\Windows6.1-KB2973201-x64.msu" "C:\temp\msu"

这将创建以下文件:

  • WSUSSCAN.cab
  • Windows6.1-KB2973201-x64.cab
  • Windows6.1-KB2973201-x64.xml
  • Windows6.1-KB2973201-x64-pkgProperties.txt

创建 xml 和 txt 文件大约需要 5 秒钟。打开 pkgProperties.txt 文件,顶行有信息:

ApplicabilityInfo="Windows 7.0 Client SP1;Windows 7.0 Server Core SP1;Windows 7.0 Embedded SP1;Windows 7.0 Server SP1;Windows 7.0 WinPE 3.1;"

MSDN 引用:Description of the Windows Update Standalone Installer in Windows

关于c# - 如何以编程方式检查 Windows 更新的适用性规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29843971/

有关c# - 如何以编程方式检查 Windows 更新的适用性规则?的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  7. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  8. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  9. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  10. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

随机推荐