Você já se perguntou por que uma lista de atualizações instaladas do Windows é gerada? E através de qual API obtê-lo? Tentarei dar respostas a essas e outras questões emergentes em meu pequeno estudo.

Antecedentes ou como tudo começou.
Todos os anos é realizada uma conferência de jovens especialistas
em nossa empresa , onde cada participante pode resolver o problema de um departamento (uma lista de tópicos é proposta com antecedência). E o departamento de SPAS (suporte de software e hardware) teve a seguinte tarefa, que me interessou, além disso, tornou possível retornar à programação novamente (infelizmente, no momento em que trabalho nesta empresa como um simples operador de NPPS).
Anteriormente, para cada "TO" com a ajuda do WSUS, todas as atualizações lançadas eram puxadas e distribuídas para todas as máquinas. O TSB (boletins de serviço técnico) também aparecia periodicamente, indicando que era necessário instalar as atualizações necessárias na forma de pacotes isolados. Como resultado, acumulamos atualizações que não podem ser rastreadas no WSUS, mas só podem ser vistas através do painel de controle na seção "Atualizações instaladas".

Há situações em que a estação de trabalho ou o servidor "trava" e você precisa restaurá-lo a partir de uma imagem criada há algum tempo. Ao recuperar a partir de uma imagem, há uma chance de que possamos perder as atualizações necessárias (que vieram na forma de pacotes isolados) que foram instaladas antes da falha da máquina. Explicado da forma mais detalhada possível, porque os esclarecimentos já serão um segredo comercial.
É por isso que surgiu a idéia de criar um programa que pudesse extrair essa lista de atualizações (de preferência
remotamente pela rede local), gravar em um arquivo / banco de dados, comparar a lista atual com um determinado modelo e enviar uma mensagem ao sistema SCADA por meio de um dos protocolos - SNMP, OPC.
Como você deve ter adivinhado no título do artigo, eu já tinha uma tarefa difícil de escolher o método de recuperação de lista. Como sempre, decidi procurar o caminho certo no mecanismo de pesquisa, fiz perguntas sobre recursos especializados (
um ,
dois , por algum motivo, o fluxo de pilha em inglês não gostou da minha pergunta e precisou ser excluído), mas todas as respostas não deram o resultado desejado. Portanto, eu mesmo tive que descobrir isso, o que será discutido mais adiante.
Comandos do console
Vamos começar com um simples e aproveitar o que o Windows nos oferece sem usar ferramentas de terceiros. Isso pode ser feito usando os seguintes comandos:
- lista wmic qfe
- systeminfo
- dism / online / get-packages
- através do PowerShell:
- Obter hotfix
- Get-SilWindowsUpdate (disponível apenas nas edições do servidor)
- Get-WmiObject -Class win32_quickfixengineering - através do acesso à classe WMI win32_quickfixengineering (sobre o WMI um pouco mais tarde)
Você pode obter a lista através da interface gráfica através do item padrão do Painel de Controle “Adicionar / Remover Programas”, mas não podemos copiar nada a partir daí. Cada ferramenta do painel de controle é representada por um arquivo .cpl na pasta Windows \ System. Os arquivos .Cpl na pasta do sistema do Windows são baixados automaticamente quando o painel de controle é iniciado. O arquivo Appwiz.cpl é responsável pelo item do programa. Sua análise não levou a nada.
A saída do comando do console pode ser redirecionada para um arquivo e, em seguida, pode ser analisada, mas isso está errado, além de uma chamada de programa (de acordo com as regras do SB, não funcionará) e não há dúvida de receber a lista remotamente. Portanto, sugiro que você simplesmente chame os comandos, compare o número de atualizações em cada lista com a lista no Painel de Controle e continue nossa investigação.
Formalmente, todos os métodos para obter a lista de atualizações podem ser divididos em dois grupos: local e de rede.

Todos os métodos foram testados em imagens limpas do sistema (Windows 7, 8, Server 2012 R2) com atualizações integradas. Após cada atualização pelo Update Center dos servidores oficiais da Microsoft, uma verificação adicional era realizada. Vamos nos debruçar sobre cada um deles com mais detalhes.
WUA
WUApi (API do Windows Update Agent) - Usando a API do Windows Update Agent. A opção mais óbvia, cujo nome fala por si. Usaremos a biblioteca Wuapi.dll para isso.
Nota: a seguir, para minha conveniência, incorporarei todos os resultados na Lista. Isso pode não ser racional, mas me pareceu uma boa ideia.
Exemplo de implementaçãousing WUApiLib; public static List<string> listUpdateHistory() {
Há uma segunda variação desse método:
Update Session - recebendo informações conectando-se à sessão de atualização do Windows Update Agent (nesse caso, não trabalhamos diretamente com a biblioteca).
Exemplo de implementação public static List<string> Sessionlist(string pc) { List<string> result = new List<string>(50);
A Microsoft sugere o
uso remoto
da API .
As principais desvantagens desses dois métodos são que eles não permitem encontrar correções de KB que não são distribuídas pelo Windows Update. Você só pode ver o que passou pelo próprio agente de atualização, ou seja, essa opção não é adequada para nós.
DISM
O Gerenciamento e Manutenção de Imagens de Implantação é uma ferramenta de linha de comando que pode ser usada para atender uma imagem do Windows ou para preparar uma imagem de um Ambiente de Pré-instalação do Windows (Windows PE). É um substituto para o Gerenciador de Pacotes (Pkgmgr.exe), PEimg e Intlcfg.
Este utilitário é usado para integrar atualizações, service packs à imagem do sistema. As atualizações do Windows são módulos separados que podem ser apresentados de várias maneiras:
- Arquivos .cab (Cabinet) - arquivos. Projetado para distribuição e instalação usando os módulos do Windows Update em um modo automatizado;
- Arquivos .msu (Pacote Independente do Microsoft Update) - arquivos executáveis. Projetado para distribuição e instalação pelos próprios usuários no modo manual por meio do catálogo de atualizações da Microsoft. Na verdade, eles são um conjunto empacotado que consiste em arquivos .cab-, .xml, .txt.
O comando
dism / online / get-packages mencionado anteriormente exibe informações básicas sobre todos os pacotes no sistema wim image / current. A Microsoft cuidou de nós e fornece
pacotes NuGet para uso conveniente da API.
Exemplo de implementação using Microsoft.Dism; public static List<string> DISMlist() { List<string> result = new List<string>(220); try { DismApi.Initialize(DismLogLevel.LogErrors); var dismsession = DismApi.OpenOnlineSession(); var listupdate = DismApi.GetPackages(dismsession); int ab = listupdate.Count;
O número de atualizações coincidiu com o número da lista do Painel de Controle até a primeira atualização pelo centro de controle - depois disso, o número de atualizações se tornou menor (eram 214, passou a 209), embora logicamente elas devam aumentar. Exemplos de saída
Antes de atualizar ,
Depois de atualizar .
Qual é a razão disso, posso apenas especular - talvez algumas atualizações substituam as anteriores, portanto, o número se tornou menor.
Um pouco mais tarde, deparei-me com um utilitário do
DISM ++ chinês, que não é baseado na API do DISM ou na API do DISM Core, mas as bibliotecas que ele possui não possuem os métodos que eu preciso abrir, então abandonei essa idéia e continuei pesquisando mais.
WSUS
O Windows Server Update Services (
WSUS ) é um servidor para atualização de sistemas operacionais e produtos da Microsoft. O servidor de atualizações é sincronizado com o site da Microsoft, baixando atualizações que podem ser distribuídas na LAN corporativa. Novamente, uma ferramenta especial projetada para trabalhar com atualizações.
Distribuído apenas nas edições do servidor do Windows, portanto, o seguinte suporte foi implantado:
- o sistema principal é o Windows Server 2016;
- e por meio do sistema de virtualização Hyper-V, dois sistemas operacionais clientes foram implantados:
Todos os sistemas estão conectados a uma única rede local virtual, mas
sem acesso à Internet .
Algumas dicasPara não alocar uma partição do disco rígido para o novo sistema, eu uso o
WinNTSetup e instalo o sistema em discos VHD - o gerenciador de inicialização, começando no Windows 7 (edições Professional / Ultimate), faz um ótimo trabalho ao inicializar a partir de uma imagem de disco. Os discos assim obtidos podem ser usados com segurança no Hyper-V - você mata dois coelhos com uma cajadada ao mesmo tempo. Lembre-se de fazer uma cópia do repositório BCD antecipadamente através do
comando bcdedit / export e: \ bcd_backup.bcd .
Como não queria configurar o AD para distribuição de atualizações, simplesmente registrei o caminho para o servidor WSUS nas políticas de grupo:

Preste atenção à porta, devido a um erro de digitação (8350 em vez de 8530), não foi possível receber atualizações nas máquinas clientes, embora tudo tenha sido feito corretamente. Além disso, os nomes dos itens nas políticas de grupo no Windows 7 e Windows 8 são diferentes.
Para receber o relatório usando o WSUS, você deve instalar o pacote adicionalmente - o sistema notificará você disso.
E agora um pouco de código Como não há Internet, a situação com as atualizações aparece como na captura de tela abaixo:

O comportamento é semelhante ao WUApi - se as atualizações não passaram por eles, eles não sabem disso. Portanto, esse método não funciona novamente.
Wmi
A Instrumentação de Gerenciamento do Windows (
WMI ) na tradução literal é um kit de ferramentas de gerenciamento do Windows.
O WMI é um padrão implementado pela Microsoft para gerenciar uma empresa
pela Internet para administração centralizada e monitoramento de várias partes de uma infraestrutura de computador executando uma plataforma Windows. O WMI é um sistema unificado aberto de interfaces de acesso a todos os parâmetros do sistema operacional, dispositivos e aplicativos que nele operam.
Este método permite receber dados da máquina local e remotamente na rede local. Para acessar objetos WMI, é usada uma WQL (WMI Query Language) específica, que é uma das variedades de SQL. Receberemos a lista através da classe WMI
win32_quickfixengineering .
Exemplo de implementação using System.Management; public static List<string> GetWMIlist(params string[] list) { List<string> result = new List<string>(200);
Quantitativamente, tudo coincide (mesmo após as atualizações), por isso foi decidido usar esse método. Para criação programática de solicitações WMI, recomendo que você use o seguinte utilitário -
WMI Delphi Code Creator . Graças a ela, olhei para o meu código um pouco diferente e decidi usar um espaço em branco neste programa.
XML
Os dados obtidos pelo método WMI não me pararam, e eu decidi pela "engenharia reversa de superfície". Usaremos o utilitário
Process Monitor da coleção de software
Sysinternals Suite para identificar arquivos e ramificações do registro que são usadas ao chamar os comandos do console listados acima e acessar o item "Atualizações Instaladas" através do Painel de Controle.
Chamei minha atenção o arquivo wuindex.xml, localizado na pasta C: \ Windows \ servicing \ Packages \. Para analisá-lo, foi escrito o seguinte programa:
Exemplo de aplicativo de console using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Text.RegularExpressions; using System.IO; namespace XMLviewer { class Program { static void Main(string[] args) { string writePath = AppDomain.CurrentDomain.BaseDirectory + "XML " + Environment.MachineName + ".txt"; if (!File.Exists(writePath)) { Console.WriteLine(" txt "); } else { Console.WriteLine(" XML .txt , "); File.Delete(writePath); }
Infelizmente, esse arquivo não foi encontrado em todos os sistemas e o princípio de sua geração e atualização permaneceu um mistério para mim. Portanto, novamente este método não nos convém.
Cbs
Aqui chegamos ao que todos esses métodos estão associados. Continuando a análise dos logs do Process Monitor, identifiquei as seguintes pastas e arquivos.
O arquivo DataStore.edb localizado na
pasta C: \ Windows \ SoftwareDistribution \ DataStore . Este é um banco de dados que contém o histórico de todas as atualizações da versão instalada do Windows, incluindo aquelas que estão apenas na fila.
O programa ESEDatabaseView foi usado para analisar o arquivo DataStore.edb. Há uma tabela tbUpdates no banco de dados, cujo conteúdo é difícil de interpretar.

Após chamar minha atenção para o processo
TiWorker.exe , que era chamado toda vez que eu abria um item no Painel de Controle. Ele "caminhou" por várias pastas, uma das quais me levou no caminho certo.
C: \ Windows \ SoftwareDistribution é uma pasta usada pelo Windows Update para baixar atualizações para um computador e instalá-las, além de armazenar informações sobre todas as atualizações instaladas anteriormente.
Pasta WinSxS localizada em
C: \ Windows \ winsxs . Essa é a pasta de serviço do sistema operacional Windows usada para armazenar versões instaladas anteriormente dos componentes do sistema. Devido à sua presença, é possível reverter para uma versão mais antiga da atualização, se necessário.
C: \ Windows \ servicing - o componente principal de todo o sistema, cujo nome é
CBS (Component-Based Service) .
O CBS é um serviço baseado em componente que faz parte do Windows e está integrado ao serviço Windows Update. Em contraste com o
serviço Serviço Baseado em
Arquivo (FBS) (para sistemas operacionais anteriores ao Windows Vista), no qual os arquivos foram atualizados diretamente nos diretórios do sistema, o CBS introduziu uma hierarquia completa de diretórios e uma família inteira (pilha) de módulos / bibliotecas de serviços.
CbsApi.dll é a principal biblioteca de suporte da tecnologia CBS. Não possui métodos abertos, então não pude usá-lo diretamente. A Microsoft usa o TrustedInstaller.exe e o TiWorker.exe para acessar os métodos desta biblioteca e, já através desses processos, exibe os dados de que precisamos. Os registros são mantidos em
C: \ Windows \ Logs \ CBS \ CBS.log .
No momento da criação do protótipo do programa (você pode ver maio de 2019 nas capturas de tela), não havia informações em russo sobre a CBS, mas no final de agosto havia um artigo muito bom no blog -
http://datadump.ru/component-based-servicing . Um artigo muito interessante que confirmou minha experiência e reuniu as informações necessárias. E mais sobre o tema:
http://www.outsidethebox.ms/17988/Conclusão
A Microsoft complicou demais a tarefa trivial de obter uma lista de atualizações e tornou esse processo não totalmente óbvio. Tudo isso é feito por segurança, mas não por facilidade de uso. Concordo com o autor do
artigo - a previsibilidade e a transparência começaram a estar ausentes no recebimento de atualizações.
Como resultado do estudo, foi escrito o seguinte
programa , cuja demonstração pode ser vista neste vídeo:
Os planos para adicionar:
- comparar a lista de atualizações necessárias com a recebida;
- envie o resultado via SNMP / OPC (se alguém tiver experiência, compartilhe nos comentários);
- organize a instalação das atualizações "offline" ausentes da pasta especificada.
Se você conhece mais métodos para obter uma lista não apenas de atualizações, mas também de componentes adicionais (Adobe Flash, Acrobat Reader, etc.) ou se tem outras sugestões interessantes, escreva sobre isso nos comentários ou nas mensagens privadas - terei prazer em receber qualquer comentário . E participe da pesquisa deste artigo - para saber se minha experiência com o público do Habrahabr será interessante.