powershell - via - Como posso encontrar o código de atualização para um arquivo MSI instalado?




script vbs instalar programas (2)

Em certos casos, a necessidade de recuperar códigos de atualização do MSI para pacotes implantados pode surgir.

Cenários comuns:

  • Eu assumi o projeto MSI de outra pessoa e preciso determinar quais códigos de atualização foram usados ​​para versões anteriores que já estão em estado natural. Isso é necessário para lidar com cenários de atualização. Não tenho nenhum arquivo de lançamentos em nenhum lugar .
  • Eu acidentalmente mudei o código de atualização para o meu pacote WiX várias vezes durante o desenvolvimento e eu preciso encontrar todas as versões do Código de Atualização "in the wild". Eu não sabia que os códigos de atualização deveriam permanecer estáveis ​​entre as versões .

Esta é uma pergunta de estilo Q / A.

Esta questão surgiu antes em várias encarnações, mas isso não é uma duplicata . Eu estou postando uma maneira de fazer isso que usa a interface principal de automação MSI (ou estritamente falando WMI). Deve ser mais confiável do que abordagens baseadas em registros de respostas anteriores. Essas respostas também tentam resumir outras abordagens de recuperação.


Recuperação do Código de Atualização MSI (via PowerShell / WMI)

Desinstalando? : Via Upgrade Code, Via Product Code, Via Product Name, etc...

O script PowerShell abaixo deve recuperar todos os códigos de produtos relacionados, códigos de atualização e nomes de produtos instalados em sua máquina (saída de tabela).

Captura de tela da saída (script completo abaixo):

Esses são os valores ativos reais diretamente do banco de dados do Windows Installer na máquina em questão. Não há necessidade de conversão ou interpretação. Estamos passando pelas APIs adequadas.

Nota técnica! Observe que a verificação de propriedades diretamente no arquivo MSI original (tabela de propriedades) ou no arquivo de origem WiX pode não corresponder aos valores instalados reais, pois as propriedades podem ser substituídas no momento da instalação por meio de transforms (mais informações abaixo) ou valores de propriedade especificados no comando linha. A moral da história: recupere valores de propriedade diretamente do sistema quando puder.

Isenção de responsabilidade rápida : em casos raros, a execução do script pode acionar um reparo automático do Windows Installer. Leia mais na seção "disclaimer" abaixo. Apenas um incômodo potencial, mas leia o aviso por favor.

Como digressão, há também um comando PowerShell de uma linha, que recuperará códigos de produtos e códigos de atualização apenas, sem o nome do pacote incluído. Isso pode realmente ser suficiente para alguns usuários (no entanto, eu recomendaria o script completo abaixo). Há uma captura de tela da saída deste one-liner em uma seção abaixo. Nota : este comando parece muito mais rápido que o script maior (o campo "Valor" é o código de atualização). Além disso, observe que os códigos de produto sem códigos de atualização associados não aparecerão até onde eu posso dizer - eles serão no script maior:

gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value

Para executar o script completo do PowerShell abaixo:

  1. Inicie o PowerShell ( mantenha pressionada a tecla Windows, toque em R, solte a tecla Windows, digite "powershell" e pressione OK ou pressione enter ).
  2. Copie o script abaixo em sua totalidade e, em seguida, clique com o botão direito do mouse dentro da janela do PowerShell .
  3. Isso deve iniciar o script e levará um bom tempo para ser executado .
  4. Por favor relate quaisquer problemas. Não sou especialista em PowerShell - sou especialista em implantação e não codificador, mas o script deve fazer o trabalho.
  5. Nota de desempenho : Acabei de obter todo o objeto WMI Win32_Product
    • As propriedades do Cherry Picking pareciam realmente torná-lo marginalmente mais lento (teste VBScript).
    • Eu acho que nós precisamos pegar todas as linhas de qualquer maneira, e colunas de colheita de cereja são apenas extraíveis?
    • Para Win32_Property , filtramos as linhas e colunas (o código de atualização é apenas um dos vários tipos de linha). Esteja preparado para uma operação lenta, o WMI é muito lento.
$wmipackages = Get-WmiObject -Class win32_product
$wmiproperties = gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"
$packageinfo = New-Object System.Data.Datatable
[void]$packageinfo.Columns.Add("Name")
[void]$packageinfo.Columns.Add("ProductCode")
[void]$packageinfo.Columns.Add("UpgradeCode")

foreach ($package in $wmipackages) 
{
    $foundupgradecode = $false # Assume no upgrade code is found

    foreach ($property in $wmiproperties) {

        if ($package.IdentifyingNumber -eq $property.ProductCode) {
           [void]$packageinfo.Rows.Add($package.Name,$package.IdentifyingNumber, $property.Value)
           $foundupgradecode = $true
           break
        }
    }

    if(-Not ($foundupgradecode)) { 
         # No upgrade code found, add product code to list
         [void]$packageinfo.Rows.Add($package.Name,$package.IdentifyingNumber, "") 
    }

}

$packageinfo | Format-table ProductCode, UpgradeCode, Name

# Enable the following line to export to CSV (good for annotation). Set full path in quotes
# $packageinfo | Export-Csv "[YourFullWriteablePath]\MsiInfo.csv"

# copy this line as well

Rodando em máquinas remotas

  • Deve ser relativamente fácil estender o script acima para executar em máquinas remotas, mas não estou configurado para testá-lo corretamente no momento.
  • As informações abaixo ficaram um pouco confusas, deixe-me saber se não é compreensível ou não está claro.
  • Em um domínio real do Windows , deveria (em teoria) ser apenas uma questão de adicionar as máquinas remotas às próprias chamadas WMI (e fazer um loop sobre uma lista de máquinas - veja o modelo abaixo). E crucialmente: você deve usar uma conta de administrador de domínio real para executar a consulta . É possível que as alterações listadas abaixo para que o WMI funcione em ambientes de grupo de trabalho também possam ser necessárias para alguns domínios, não sei (regra de firewall e ajuste de registro do UAC). Eu diria que uma conta de administrador de domínio real deve ter os privilégios e acesso necessários embora.
  • As conexões remotas no WMI são afetadas pelo (pelo menos) Firewall do Windows , configurações do DCOM , Configurações do CIMOM e Controle de Conta de Usuário (UAC) (além de outros fatores que não sejam da Microsoft - por exemplo, firewalls reais, firewalls de software de terceiros, tipos, etc ...). Aqui estão alguns detalhes:
  • Em redes que não sejam de domínio (small office, home, etc ...) você provavelmente precisará adicionar credenciais de usuário diretamente às chamadas WMI para que funcione. E você provavelmente deve ter "direitos reais de administrador" nas máquinas em questão para fazer as consultas serem executadas remotamente em uma rede doméstica (grupo de trabalho). Ouvi dizer que a conta interna de Administrador não tem nenhum problema com o UAC, mas nunca tentei. Na minha opinião: não use essa conta.
    • Nos meus testes , tive de ( 1 ) atualizar as regras de firewall do Windows e ( 2 ) desativar a filtragem de token de acesso do UAC Remoto e usar uma conta de administrador local real no sistema remoto. Note que eu não recomendo nenhuma dessas mudanças , apenas relatando o que funcionou para mim.
    • Alterar 1 : Firewall do Windows, execute o comando (cmd.exe, execute como admin): netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes ( source - consulte este link para linha de comando para desabilitar este novo regra novamente se você está apenas testando Essencialmente apenas set enable = no). Veja a fonte vinculada para regras potencialmente mais restritivas que também podem funcionar.
    • Alteração 2 : Desabilitar a filtragem de token de acesso do UAC remoto: é necessário definir o seguinte valor do Registro: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ LocalAccountTokenFilterPolicy = 1 ( source - página intermediária, segunda metade). Eu defino um DWORD de 32 bits.

Com essas alterações no sistema remoto, também adicionei credenciais de usuário a cada chamada, solicitando ao usuário $Cred = Get-Credential . Há também opções mais avançadas para definir as credenciais do usuário, conforme explicado aqui: Transfira a senha para -credencial (e here ). Para testar a execução, aqui está um pequeno script de teste. Copie todas as linhas abaixo, modifique o nome da máquina remota e cole no PowerShell clicando com o botão direito do mouse (você será solicitado a fornecer credenciais):

$Cred = Get-Credential
gwmi -ComputerName RemoteMachineName -credential $Cred -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value
# copy this line too

Para o script PowerShell grande acima, as adições básicas para execução remota em várias máquinas em um domínio do Windows podem ser algo assim (não atualizarei o script acima, pois não posso realmente testar isso corretamente). Lembre-se de atualizar a lista de nomes de computadores remotos na parte superior do script e executá-los com uma conta de administrador de domínio:

# DOMAIN NETWORK: mock-up / pseudo snippet ONLY - lacks testing, provided "as is"
$ArrComputers = "Computer1", "Computer2", "Computer3"
foreach ($Computer in $ArrComputers) 
{
    # here we modify the WMI calls to add machine name
    $wmipackages = Get-WmiObject -Class win32_product -ComputerName $Computer
    $wmiproperties = gwmi  -ComputerName $Computer -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"

    # the rest of the above, large script here (minus the first 2 WMI lines)
}

Para adaptar o mesmo loop de máquina para uma rede sem domínio, você pode adicionar credenciais às chamadas do WMI. Algo como isso (você será solicitado para credenciais para cada máquina - o que pode ser confuso). Lembre-se de atualizar a lista de nomes de computadores remotos na parte superior do script e usar uma conta com direitos de administrador local na caixa de destino:

# WORKGROUP NETWORK: mock-up / pseudo snippet ONLY - lacks testing, provided "as is"
$ArrComputers = "Computer1", "Computer2", "Computer3"
foreach ($Computer in $ArrComputers) 
{
     $Cred = Get-Credential

     # here we modify the WMI calls to add machine name AND credentials
     $wmipackages = Get-WmiObject -Class win32_product -ComputerName $Computer -credential $cred
     $wmiproperties = gwmi  -ComputerName $Computer -credential $cred -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"

     # the rest of the above, large script here (minus the first 2 WMI lines) 
}

A resposta real termina aqui . Acredito que o script mais recente acima cubra a maioria dos casos de uso, mas também deixarei o conteúdo abaixo, já que ele não é obsoleto, provavelmente é menos eficiente que o script acima. A leitura provavelmente será repetitiva.

Os scripts abaixo para recuperação de códigos únicos de atualização, em vez de toda a lista, podem ser de interesse se você quiser recuperar um único código de atualização de dentro de seu próprio aplicativo em tempo de execução. Vou deixar esse conteúdo mais antigo.

Isenção de responsabilidade : O script acima usa o WMI e, quando você acessa a classe Win32_Product, ele dispara uma verificação de integridade dos pacotes instalados . Isso é bastante lento e pode, em casos muito especiais, acionar um auto-reparo do MSI. Isso não é bom se você estiver indo para uma reunião importante :-). Felizmente, você deve ser capaz de cancelar qualquer reparo automático acionado (mas sua consulta provavelmente não será concluída até que o reparo seja concluído). Link de contexto rápido (para custódia).

IMHO: não deixe que isso impeça você de usar o WMI - é apenas um aborrecimento. Nota: as abordagens PowerShell e VBScript descritas abaixo usam o WMI e podem acionar esse problema também.

Recuperando códigos de atualização para arquivos MSI que não estão instalados

Se você precisar do código de atualização para um pacote MSI que não está instalado em sua máquina, leia a seção " Recuperação manual de códigos de atualização " na parte inferior para várias opções (essencialmente procure no próprio arquivo MSI ou no arquivo de origem usado para compilar).

Não é seguro obter o código de atualização dos pacotes instalados do próprio arquivo de instalação MSI original ou das fontes (WiX) usadas para compilar o MSI, porque os códigos de atualização podem ser substituídos no momento da instalação usando transforms (detalhes no texto abaixo - transforma são pequenos fragmentos de banco de dados aplicados no momento da instalação, veja o link da Symantec para obter detalhes).

A recuperação programática de códigos de atualização depende do WMI e você pode usar o PowerShell ou o VBScript para chamar o WMI . Ambos os métodos são apresentados abaixo. Essencialmente, a seguinte consulta WMI é executada para recuperar o código de atualização para um código de produto especificado:

SELECT * FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='{YourProdGuid}'

É a mesma consulta usada para o VBScript e o PowerShell. Você também pode executá-lo como uma consulta WMI direta usando uma ferramenta como o WMIExplorer.exe . Uma ferramenta muito útil - altamente recomendada. Eu acredito que este é o site deles: https://github.com/vinaypamnani/wmie2/releases

Recuperar um único código de atualização via PowerShell / WMI

Em vez de gerar uma tabela inteira com todos os códigos de produto e códigos de atualização, você pode recuperar um único código de atualização para um código de produto especificado. Isso é bom se você estiver tentando fazer a recuperação de dentro do seu próprio código de aplicativo (então é apenas uma consulta WMI padrão e não tem nada a ver com o PowerShell).

Abaixo está a recuperação do código de atualização única feita pelo PowerShell (para iniciar o PowerShell: mantenha pressionada a tecla Windows, toque em R, solte a tecla Windows, digite "powershell" e pressione OK ou pressione Enter ):

gwmi -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='{YourGuid}'" | Format-Table Value

A saída deve ser algo assim (talvez um pouco difícil de ler, eu deveria ter usado fontes maiores):

O código do produto especificado na consulta acima é para " Windows SDK Intellidocs ". Você deve, obviamente, substituí-lo com o seu próprio código de produto guid. Para encontrar o código do produto que você precisa passar, também é possível usar uma consulta do PowerShell conforme descrito aqui: Como posso encontrar o GUID do produto de uma instalação do MSI instalada?

O código de atualização retornado está vindo diretamente do banco de dados de registro real do Windows Installer. Não requer mais processamento ou interpretação ou etapas de conversão manual . Ele também estará correto, mesmo se uma transformação tiver alterado o código de atualização original quando o MSI foi instalado (detalhes sobre os problemas de transformação abaixo).

Atualização, aviso especial : sem complicar as coisas desnecessariamente, acredito ter encontrado um bug no WMI que é muito específico. Quando um MSI original não tem um código de atualização definido e você adiciona um por meio de uma transformação, o WMI parece não informar o código de atualização. No entanto: se o MSI original tiver um código de atualização e você substituí-lo em uma transformação, o WMI relatará o código de atualização da transformação (o que é esperado). Eu definitivamente vi isso, mas preciso verificar com mais um pacote de teste para ter certeza. A moral da história : sempre defina um código de atualização no seu MSI! Então você evita todo o problema permanentemente. E não o gere automaticamente - codifique-o (leia "Recuperação manual de códigos de atualização" abaixo para obter uma explicação).

Recuperar um único código de atualização usando VBScript / WMI (Legacy Approach)

Não há nada errado com a solução VBScript encontrada abaixo - ela ainda tem alguns benefícios em relação ao PowerShell - apesar de o VBScript ser uma tecnologia legada até agora. Os benefícios são que ele deve funcionar em todas as máquinas, mesmo quando a estrutura .NET está ausente (ou bloqueada) e em máquinas onde o PowerShell está ausente (ou bloqueado). É uma solução datada, mas viável, que é bastante flexível (a menos que o VBScript também esteja bloqueado, mas todas as versões modernas do sistema operacional suportam totalmente o VBScript).

A fim de tornar o mais simples possível recuperar seu código de atualização, eu criei um " VBScript bare-bone " que deve fazer o truque. Ele não foi testado para segmentação de computadores remotos, mesmo que o WMI possa fazer isso por design. O script destina-se a ser executado no sistema em que seu mistério MSI com o código de atualização desconhecido está instalado.

Esse VBScript requer um código de produto de entrada (a caixa de diálogo de entrada mostrada quando o script é executado) e, em seguida, continuará procurando o código de atualização correspondente (se houver). Como dito acima, para localizar o código do produto para o seu MSI, você pode usar essa abordagem: Como posso encontrar o GUID do produto de uma instalação MSI instalada? . Depois de ter o código do produto (guid), você pode executar este VBScript na máquina de destino e obter o código de atualização retornado em poucos segundos. Recuperação WMI pode ser muito lenta.

'
' Purpose: Barebone / minimal VBScript implementation to allow retrieval of MSI UpgradeCodes via WMI.
'
' Version: 0.2, September.2017 - Stein Åsmul.
'
' Notes:
'
'  - As it stands, this script is intended to be run interactively (WScript).
'  - Conversion to run via CScript should be trivial (nothing ever is...)
'  - The script will ask the user to provide a valid product GUID for an installed MSI.
'  - To find a valid product GUID for your system, perhaps see this SO answer: https://.com/a/29937569/129130
'  - The script does not RegEx anything to check for valid GUID format (this is barebone - as terse as possible,
'    with as little as possible included that can break).
'
' UPDATE: for information on remote running, check "Running on remote machines" section here:
' https://.com/a/46637095/129130 (firewall and registry change seems to be needed).

strComputer = "."
' Remote connections was NOT tested for this script. In principle you should just add the machine name to "strComputer" above.
' AFAIK you must have "real" admin rights on the box you try to connect to. Many users report intermittent problems running remote WMI.
' Remote connections in WMI are affected by the Windows Firewall, DCOM settings, and User Account Control (UAC).
'    - Setting up a Remote WMI Connection: https://msdn.microsoft.com/en-us/library/aa822854(v=vs.85).aspx
'    - Connecting to WMI on a Remote Computer: https://msdn.microsoft.com/en-us/library/aa389290(v=vs.85).aspx
'    - Perhaps useful: https://social.technet.microsoft.com/Forums/lync/en-US/05205b52-0e43-4ce3-a8b8-58ec4c2edea5/wmi-generic-failure-when-accessing-win32product-remotely?forum=winserverManagement
'    - Maybe it is also worth noting that I think WMI queries can be slow enough to trigger timeouts,
'      and then you have the old favorite: intermittent bugs.

Set owmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

' User interaction
productcode = InputBox("Please paste or type in the product code for the product whose upgrade code you want " + _
                       "to retrieve (not case sensitive, a blank product code will abort the script)." + vbNewLine + vbNewLine + _
                       "Please note that the script can take up to a minute to run due to WMI's slowness.", "UpgradeCode retrieval:")
If productcode = vbCancel Or Trim(productcode) = "" Then
   WScript.Quit(0)
End If

' Run WMI call and verify that it completes successfully.
On Error Resume Next
Set upgradecode = owmi.ExecQuery("SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='" & productcode & "'")
If (Err.number <> 0) Then
   MsgBox "The WMI query failed, this is a critical error - aborting.", vbCritical, "Fatal error."
   WScript.Quit(2) ' Following exit code "standard" from MSI SDK automation samples
End If
On Error GoTo 0

' Report results.
Select Case upgradecode.count

   Case 0
       ' We have to provide a separate message for this state, since some packages may not have an UpgradeCode.
       ' However, the product GUID could also have been misspelled.
       MsgBox "No UpgradeCode was found, are you sure you entered the correct product GUID?" & vbNewLine & vbNewLine & _
              "Note: It is possible for a product to NOT have an UpgradeCode.", vbInformation, "No UpgradeCode found."

   Case 1
      ' The "default state" - should cover almost all normal packages.

      ' Only one upgrade code should have been retrieved, and it can be referenced by upgradecode.ItemIndex(0).Value on newer systems 
      ' (Vista and later), but on XP this apparently does not work (never tested by me), for compatibility we use a standard For Each 
      ' enumeration instead. Source: https://.com/questions/2378723/get-first-record-from-wmi-execquery

      For Each u in upgradecode
        Msgbox "The Upgrade Code is: " & u.Value & vbNewLine & vbNewLine & _
              "Just press CTRL + C to copy all text in this dialog (then paste to notepad or similar to extract the GUID).", _
              vbInformation, "UpgradeCode found."
          ' Exit For
      Next

   Case Else
       ' Should never get here - let us know if you do get this message.
       MsgBox "An error occurred, the query returned more than one result. There can only be one UpgradeCode. " & _ 
              "Please report this error on ", vbInformation, "Error while retrieving UpgradeCode."
End Select

Recuperando todos os códigos de atualização e código de produto em uma máquina

Devo mencionar que tenho um grande VBScript que gerará um relatório HTML abrangente para todos os pacotes MSI instalados na máquina em que ele é executado . Isso inclui todo o código de atualização e uma lista de códigos de produto relacionados (códigos de produto que compartilham o mesmo código de atualização). No entanto, não estou muito feliz com o código (sou um especialista em implantação, não um codificador). O script é muito grande, muito lento e muito não testado para uso , então eu crio o VBScript descoberto acima para recuperar apenas um único pacote. Este script é muito mais fácil de testar e modificar para seu próprio uso. Eu posso fornecer este grande VBScript para testar se de interesse. É somente leitura para além de uma única saída de arquivo HTML para "Meus documentos". Deve ser possível adaptar esse script para uso em computadores remotos também.

Existe um comando PowerShell de uma linha para recuperar todos os códigos de produto e códigos de atualização relacionados, mas esse preenchimento de saída não possui o nome dos produtos. Eu incluo aqui para completar:

gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value

A saída será semelhante a esta (o campo "Valor" é o código de atualização - códigos de produto sem códigos de atualização associados não serão mostrados até onde eu sei):

Recuperação Manual de Códigos de Upgrade

Esta seção lista algumas "maneiras manuais" para recuperar códigos de atualização que não precisam de nenhuma codificação ou linhas de comando. Essas abordagens manuais não são as recomendadas. Eu os incluo apenas porque isso tenta ser uma " resposta de referência ". Várias opções diferentes devem ser fornecidas. Minha recomendação é usar o PowerShell ou VBScript fornecido acima.

Dito isto, os códigos de atualização geralmente nunca devem mudar nas versões do seu produto, então é provável que você tente o que encontrar no próprio arquivo MSI ou na fonte usada para compilá-lo, conforme descrito abaixo. O problema que já foi mencionado várias vezes é que uma transformação pode alterar os códigos de atualização no momento da instalação, portanto, você precisa recuperar o código de atualização programaticamente, se quiser ter certeza de encontrar o código correto. A menos que você esteja tentando obter o código de atualização de um MSI que não esteja instalado em seu sistema. Então você só precisa de um visualizador de arquivos MSI, conforme descrito abaixo no ponto 1.

Uma transformação é apenas um fragmento de banco de dados com alterações aplicadas ao MSI original no momento da instalação . É uma ferramenta usada principalmente para empacotamento de aplicativos corporativos para modificar instaladores sem modificar os arquivos MSI diretamente. As transformações têm a extensão .mst . Alterar o código de atualização por meio de uma transformação é incomum, mas não inédito - especialmente para o reempacotamento corporativo. Em casos raros, os empacotadores de aplicativos podem alterar intencionalmente o guid de atualização para permitir que eles entreguem suas próprias atualizações aos pacotes instalados (em vez de confiar nas atualizações do fornecedor diretamente). Raro, mas eu já vi isso feito. Se isso é bom ou não é altamente discutível.

Maneiras fáceis e manuais para encontrar códigos de atualização do MSI:

  1. Embora ofensivamente óbvio, a maneira mais fácil de encontrar o código de atualização é abrir o MSI original usado para instalar o produto e localizar o código de atualização na tabela de propriedades . Tudo o que você precisa é de uma ferramenta capaz de abrir arquivos MSI. Aqui estão algumas ferramentas: Que produto de instalação usar? InstallShield, WiX, Wise, Instalador Avançado, etc. Sua aposta mais rápida é provavelmente Orca se você tiver o Visual Studio instalado (procure por Orca-x86_en-us.msi e instale-o - este é o visualizador e editor oficial da MSI da Microsoft), ou Super Orca se você não tiver o Visual Studio instalado (siga o link acima para encontrá-lo).

  2. Se você é um desenvolvedor usando WiX (ou qualquer outra ferramenta de implantação), obviamente pode encontrar facilmente o código de atualização no seu arquivo de origem WiX que você usou para compilar sua MSI (ou fonte Installshield, fonte Advanced Installer ou qualquer ferramenta de implantação usando).

    • Não vamos sair do assunto com conselhos muito bem entendidos que entopem o assunto principal, mas você deve obviamente codificar o código de atualização em sua fonte e nunca gerar automaticamente o código !
    • Os códigos de atualização definem " famílias de produtos relacionados " e devem permanecer estáveis ​​nos releases (versões). Na maioria dos casos, ele deve permanecer estável entre as versões de idiomas também. A configuração exata depende dos requisitos de implantação.
    • Se os produtos puderem existir lado a lado, você normalmente terá códigos de atualização diferentes para os produtos que precisam coexistir.
    • Regra geral : mantenha os códigos de atualização estáveis ​​pelo maior tempo possível, sempre que possível. Altere-os quando os requisitos exigirem.
    • Para finalizar: nunca use o mesmo código de atualização para produtos diferentes que tenham seu próprio " ciclo de vida " e nenhuma relação real entre si. Eles não estão relacionados. Isso é tão importante quanto manter seu código de atualização estável para produtos relacionados. Pense nos requisitos de " ciclo de vida " e " relação familiar " e " coexistência ".
    • Essa foi uma grande digressão, voltando ao assunto em questão: encontrando códigos de atualização.
  3. Mesmo se você não tiver o MSI original, é possível localizar o MSI em cache da instalação original na %SystemRoot%\Installer . Os arquivos MSI aqui têm um nome hexadecimal misterioso, mas são apenas cópias dos arquivos MSI originais usados ​​para instalar os diferentes produtos - armazenados em cache em um local seguro para estarem disponíveis para operações de modificação, reparo e desinstalação. Faça o que fizer, não mexa nessa pasta. Nunca, jamais delete nada . Você pode encontrar o MSI que instalou seu produto selecionando o primeiro arquivo MSI e verificando na barra de status do Windows Explorer qual é o nome do produto para a versão mais antiga do Windows. No Windows 10, parece que você pode passar o mouse sobre um MSI com o ponteiro e obter um pop-up com alguns detalhes do MSI. Em seguida, basta clicar na lista até encontrar o produto certo e abrir o MSI e encontrar o código de atualização na tabela de propriedades .

  4. Algumas pessoas usam o registro para ler os códigos de atualização: Como posso encontrar o código de atualização para um aplicativo instalado em c #? . Na minha opinião, essa não é uma boa abordagem, existem maneiras melhores - como apenas usar o PowerShell, conforme explicado acima. Não há necessidade de toda essa conversão e interpretação de GUIDs compactados (que é o formato GUID usado no banco de dados de registro do Windows Installer).

Isso deve completar os "métodos manuais" primários para recuperar rapidamente um código de atualização. Apenas alguns métodos para o arsenal que às vezes são bons o suficiente. Existem provavelmente várias outras maneiras que eu esqueci.

Preferir as abordagens programáticas , mas se você está com pressa e trabalhando sem todas as suas ferramentas disponíveis, algumas opções manuais são boas. No entanto, alguns desses métodos manuais exigem mais ferramentas do que a linha de comando do PowerShell (você precisa de um visualizador de arquivos MSI que nem sempre está disponível na caixa se estiver em uma "missão de suporte" para a máquina de alguém). Chegou a hora de usar o PowerShell (sim, me sinto desatualizado também).

Incidentalmente, os arquivos MSI são essencialmente retirados dos bancos de dados SQL Server armazenados como arquivos de armazenamento estruturados em COM (formato de arquivo MS Office). Essencialmente, um sistema de arquivos dentro de um arquivo com fluxos de armazenamento de vários tipos.

Se você estiver preso em uma máquina sem um visualizador MSI, poderá consultar bancos de dados MSI em cache diretamente do PowerShell:


Para satisfazer seus requisitos de uso do WMI diretamente ou para aqueles momentos em que você precisa apenas de um único recurso sem o Powershell (ou precisa usar o .bat ou qualquer outro), use o wmic:

C:\WINDOWS\system32>wmic product list brief
Caption                                                                                              IdentifyingNumber                       Name                                                                                                 Vendor                          Version
    Sourcetree                                                                                           {1B05DFFD-1DB9-48CD-9265-F3976512A579}  Sourcetree                                                                                           Atlassian                       2.6.10.0
    Microsoft Office Access database engine 2007 (English)                                               {90120000-00D1-0409-0000-0000000FF1CE}  Microsoft Office Access database engine 2007 (English)                                               Microsoft Corporation           12.0.4518.1031
    Office 16 Click-to-Run Extensibility Component                                                       {90160000-008C-0000-0000-0000000FF1CE}  Office 16 Click-to-Run Extensibility Component    

Existem várias opções de formatação e saída.





wmi