Подтвердить что ты не робот

Как программно проверить правила применения обновления Windows?

Изучая содержимое файла .msu для обновления Windows (например, используя такой инструмент, как 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 для этой цели? Или есть инструмент / script?

То, что я на самом деле хочу, - это точно знать, какое условие заставил компьютер отклонить определенное обновление Windows (KB2973201) с сообщением. Обновление не применимо к вашему компьютеру (код ошибки позади этого - WU_E_NOT_APPLICABLE).

Кажется, что слишком мало документации относительно этих правил применимости обновления. Есть ли хорошие источники?

Литература:

4b9b3361

Ответ 1

Теперь, учитывая определенный .msu файл и мой локальный компьютер, есть ли способ перебрать эти правила и выяснить, не удовлетворен ли он - и какой?
Могу ли я использовать библиотеку классов WSUS 3.0 для этой цели? Или есть инструмент / script?

Вы можете Обновить правила применимости через библиотеку классов WSUS 3.0, хотя она не предлагает функциональности, чтобы проверить, пройдут ли правила, если ( Я полагаю), вы запускаете установщик, но это не говорит вам, какой из них не удалось.

Саймон упомянул, что библиотека WUAPI не раскрывает внутренние правила, и (afaik) нет способа сопоставить WUAPI ResultCodes с ApplicabilityRules, которые терпят неудачу.

И, к сожалению, библиотеки, такие как Microsoft.Deployment.WindowsInstaller.dll, не работают с файлами MSU, поэтому нам не повезло с "готовыми" вариантами. Поэтому вам нужно сделать это вручную с кодом и XML файлом (msu.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;
}
}

Прежде чем запускать Правила применимости, лучше всего проверить, будет ли обновление проходить тест применимости операционной системы (ОС) и пакета обновления SP (SP). Нет никакого смысла проверять реестр /wmi и т.д., Чтобы определить, будет ли обновление проходить правила, если оно не применимо к ОС и SP.

Чтобы просмотреть приложение 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 Ref: Описание автономного установщика Windows Update в Windows

Ответ 2

Вы можете использовать API агента Windows Update для запроса установленных обновлений (на самом деле у него много информации), что-то вроде этого:

  // in .NET, you need to add a reference
  // to the WUAPI COM component located in \windows\system32\wuapi.dll
  // to be able to access the WUAPI object model
  UpdateSearcher searcher = new UpdateSearcher();
  searcher.Online = false; // you can remove this line if you allow the API to get online to search
  var res = searcher.Search("IsInstalled=0"); // search not installed update
  foreach (IUpdate update in res.Updates)
  {
      Console.WriteLine("update:" + update.Title);

      // get history information
      // this can return nothing for example it it was hidden by end user
      // note we use update identity and rev number here for matching a specific update
      var histories = searcher.QueryHistory(0, searcher.GetTotalHistoryCount()).OfType<IUpdateHistoryEntry>().Where(
          h => h.UpdateIdentity.UpdateID == update.Identity.UpdateID && h.UpdateIdentity.RevisionNumber == update.Identity.RevisionNumber);
      foreach (var history in histories)
      {
          Console.WriteLine(" code:" + history.ResultCode);
          Console.WriteLine(" hr:0x" + history.HResult.ToString("X8"));
      }
  }

Однако это не скажет вам, какие внутренние правила (реестр/wmi и т.д.) используются для определения того, были ли установлены обновления. Это не распространяется на WUAPI.