powershell vbscript wix windows-installer wmi

powershell - ¿Cómo puedo encontrar el código de actualización para un archivo MSI instalado?



vbscript wix (2)

Recuperación del código de actualización de MSI (a través de PowerShell / WMI)

¿Desinstalar? : Via Upgrade Code, Via Product Code, Via Product Name, etc...

El siguiente script de PowerShell debe recuperar todos los códigos de productos relacionados , códigos de actualización y nombres de productos instalados en su máquina (salida de la tabla).

Captura de pantalla de salida (script completo a continuación):

Estos son los valores reales en vivo directamente de la base de datos de Windows Installer en la máquina en cuestión. No hay necesidad de ninguna conversión o interpretación. Estamos pasando por las API adecuadas.

¡Nota tecnica! : Tenga en cuenta que la comprobación de las propiedades directamente en su archivo MSI original (tabla de propiedades) o en el archivo fuente de WiX, puede no coincidir con los valores instalados reales, ya que las propiedades pueden anularse en el momento de la instalación mediante transforms (más información a continuación), o valores de propiedades especificados en el comando línea. La moraleja de la historia: recupere los valores de propiedad directamente del sistema cuando pueda.

Descargo de responsabilidad rápido : en casos excepcionales, ejecutar el script puede desencadenar una reparación automática del instalador de Windows. Lea más en la "sección de descargo de responsabilidad" a continuación. Solo una molestia potencial, pero lea el descargo de responsabilidad por favor.

Como una digresión, también hay un comando PowerShell de una línea que recuperará códigos de productos y códigos de actualización únicamente, sin incluir el nombre del paquete. Esto podría ser suficiente para algunos usuarios (sin embargo, recomendaría el script completo a continuación). Hay una captura de pantalla de la salida de este one-liner en una sección a continuación. Nota : este comando aparece mucho más rápido que el script más grande (el campo "Valor" es el código de actualización). También tenga en cuenta: los códigos de producto sin códigos de actualización asociados no se mostrarán hasta donde puedo decir, lo harán en la secuencia de comandos más grande:

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

Para ejecutar el script completo de PowerShell a continuación:

  1. Inicie PowerShell ( mantenga presionada la tecla de Windows, toque R, suelte la tecla de Windows, escriba "powershell" y presione OK o presione enter ).
  2. Copie el script a continuación en su totalidad, y luego haga clic derecho dentro de la ventana de PowerShell .
  3. Esto debería iniciar el script, y tomará bastante tiempo ejecutarlo .
  4. Por favor reporte cualquier problema. No soy un experto en PowerShell: soy un especialista en implementación, no un codificador, pero el script debería hacer el trabajo.
  5. Nota de rendimiento : acabo de obtener todo el objeto Win32_Product WMI
    • Las propiedades de recolección de cerezas parecían en realidad hacerlo marginalmente más lento (prueba VBScript).
    • Supongo que necesitamos obtener todas las filas de todos modos, y las columnas de recolección de cerezas son solo un levantamiento adicional.
    • Para Win32_Property filtramos tanto las filas como las columnas (el código de actualización es solo uno de los muchos tipos de filas). Esté preparado para una operación lenta, WMI es muy 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

Ejecutando en máquinas remotas

  • Debería ser relativamente fácil extender el script anterior para ejecutarlo en máquinas remotas, pero no estoy configurado para probarlo correctamente en este momento.
  • La información a continuación se ha vuelto un poco desordenada, avíseme si no es comprensible o no está clara.
  • En un dominio real de Windows , debería (en teoría) solo ser cuestión de agregar las máquinas remotas a las llamadas WMI (y recorrer una lista de máquinas; consulte la maqueta a continuación). Y de manera crucial: debe usar una cuenta de administrador de dominio real para ejecutar la consulta . Es posible que los cambios que enumero a continuación para hacer que WMI funcione en entornos de grupos de trabajo también puedan ser necesarios para algunos dominios, no lo sé (regla de firewall y ajuste del registro UAC). Sin embargo, supongo que una cuenta de administrador de dominio real debería tener los privilegios y el acceso necesarios.
  • Las conexiones remotas en WMI se ven afectadas (al menos) por el Firewall de Windows , la configuración de DCOM , la Configuración de CIMOM y el Control de cuentas de usuario (UAC) (más cualquier factor adicional que no sea de Microsoft, por ejemplo, firewalls reales, firewall de software de terceros, software de seguridad de varios tipos, etc ...). Aquí hay algunos detalles:
  • En redes que no sean de dominio (oficina pequeña, hogar, etc.), probablemente tenga que agregar credenciales de usuario directamente a las llamadas de WMI para que funcione. Y probablemente debe tener "derechos de administrador reales" en las máquinas en cuestión para que las consultas se ejecuten de forma remota en una red doméstica (grupo de trabajo). He oído que la cuenta de administrador integrada no tiene ningún problema de UAC, pero nunca la he probado. En mi opinión: no use esta cuenta.
    • En mis pruebas tuve que ( 1 ) actualizar las reglas del firewall de Windows y ( 2 ) deshabilitar el filtro de token de acceso UAC remoto y usar una cuenta de administrador local real en el sistema remoto. Tenga en cuenta que no recomiendo ninguno de estos cambios , solo informe lo que funcionó para mí.
    • Cambio 1 : Firewall de Windows, ejecute el comando (cmd.exe, ejecute como administrador): netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes ( fuente - vea este enlace para ver la línea de comandos para deshabilitar este nuevo vuelva a gobernar si solo está probando. Esencialmente solo configure enable = no). Consulte la fuente vinculada para conocer reglas potencialmente más restrictivas que también podrían funcionar.
    • Cambio 2 : Deshabilite el filtrado de token de acceso UAC remoto: debe establecer el siguiente valor de registro: HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System/ LocalAccountTokenFilterPolicy = 1 ( source - página media, última mitad). Configuré un DWORD de 32 bits.

Con esos cambios en el sistema remoto, también agregué credenciales de usuario a cada llamada solicitando al usuario $Cred = Get-Credential . También hay opciones más avanzadas para definir las credenciales de usuario, como se explica aquí: Pase la contraseña a -credential (y here ). Para probar la ejecución, aquí hay un pequeño script de prueba. Copie todas las líneas a continuación, modifique el nombre de la máquina remota y péguelo en PowerShell haciendo clic derecho (se le solicitarán las credenciales):

$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 el gran script de PowerShell anterior, las adiciones básicas para la ejecución remota en varias máquinas en un dominio de Windows podrían ser algo como esto (no actualizaré el script anterior ya que realmente no puedo probar esto correctamente). Recuerde actualizar la lista de nombres de computadoras remotas en la parte superior del script y ejecutar con una cuenta de administrador de dominio:

# 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 el mismo bucle de máquina para una red que no sea de dominio , puede agregar credenciales a las llamadas WMI. Algo como esto (se le solicitarán credenciales para cada máquina, lo que puede ser confuso). Recuerde actualizar la lista de nombres de computadoras remotas en la parte superior del script y use una cuenta con derechos de administrador local en el cuadro 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) }

La verdadera respuesta termina aquí . Creo que el script más nuevo anterior debería cubrir la mayoría de los casos de uso, pero también dejaré el contenido a continuación, ya que no es obsoleto, probablemente sea menos eficiente que el script anterior. Leerlo probablemente será repetitivo.

Los scripts a continuación para recuperar códigos de actualización únicos en lugar de la lista completa, podrían ser de interés si desea recuperar un código de actualización único desde su propia aplicación en tiempo de ejecución. Dejaré ese contenido anterior.

Descargo de responsabilidad : el script anterior usa WMI, y cuando accede a la clase Win32_Product , activa una verificación de integridad de los paquetes instalados . Esto es bastante lento y, en casos muy especiales, puede desencadenar una reparación automática de MSI. Esto no es bueno si se dirige a una reunión importante :-). Afortunadamente, debería poder cancelar las reparaciones automáticas activadas (pero su consulta probablemente no se completará hasta que deje que finalice la reparación). Enlace de contexto rápido (para custodia).

En mi humilde opinión: no dejes que esto te impida usar WMI, es solo una molestia. Nota: los enfoques de PowerShell y VBScript que se describen a continuación usan WMI y también pueden desencadenar este problema.

Recuperación de códigos de actualización para archivos MSI que no están instalados

Si necesita el código de actualización para un paquete MSI que no está instalado en su máquina, lea la sección " Recuperación manual de códigos de actualización " en la parte inferior para ver varias opciones (esencialmente busque en el archivo MSI o en el archivo fuente utilizado para compilarlo).

No es seguro obtener el código de actualización para los paquetes instalados del archivo de instalación original de MSI o de las fuentes (WiX) utilizadas para compilar el MSI, porque los códigos de actualización pueden anularse en el momento de la instalación utilizando transforms (detalles en el texto a continuación - transformaciones son pequeños fragmentos de bases de datos aplicados en el momento de la instalación, consulte el enlace de Symantec para obtener más detalles).

La recuperación programática de los códigos de actualización se basa en WMI , y puede usar PowerShell o VBScript para invocar WMI . Ambos métodos se presentan a continuación. Esencialmente, la siguiente consulta WMI se ejecuta para recuperar el código de actualización para un código de producto específico:

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

Es la misma consulta utilizada para VBScript y PowerShell. También puede ejecutarlo como una consulta WMI directa utilizando una herramienta como WMIExplorer.exe . Una herramienta muy útil, muy recomendable. Creo que este es su sitio: https://github.com/vinaypamnani/wmie2/releases

Recupere el código de actualización individual a través de PowerShell / WMI

En lugar de generar una tabla completa con todos los códigos de productos y códigos de actualización, puede recuperar un único código de actualización para un código de producto específico. Esto es bueno si está intentando hacer la recuperación desde el interior de su propio código de aplicación (entonces es solo una consulta WMI estándar y no tiene nada que ver con PowerShell).

A continuación se muestra la recuperación del código de actualización única realizada a través de PowerShell (para iniciar PowerShell: mantenga presionada la tecla de Windows, toque R, suelte la tecla de Windows, escriba "powershell" y presione OK o presione enter ):

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

La salida debería ser algo como esto (quizás un poco difícil de leer, debería haber usado fuentes más grandes):

El código de producto especificado en la consulta anterior es para " Windows SDK Intellidocs ". Obviamente, debe reemplazarlo con su propio código de producto guid. Para encontrar el código del producto que necesita pasar, también puede usar una consulta de PowerShell como se describe aquí: ¿Cómo puedo encontrar el GUID del producto de una configuración de MSI instalada?

El código de actualización devuelto proviene directamente de la base de datos de registro real de Windows Installer. No requiere más procesamiento o interpretación o pasos de conversión manual . También será correcto, incluso si una transformación cambió el código de actualización original cuando se instaló el MSI (detalles sobre los problemas de transformación a continuación).

Actualización, aviso especial : sin complicar las cosas innecesariamente, creo que he encontrado un error en WMI que es muy específico. Cuando un MSI original no tiene un código de actualización establecido, y agrega uno a través de una transformación, entonces WMI no parece informar el código de actualización en absoluto. Sin embargo: si el MSI original tiene un código de actualización, y lo anula en una transformación, WMI informa el código de actualización de la transformación (que se espera). Definitivamente vi esto, pero necesitaré verificar con un paquete de prueba más para estar seguro. La moraleja de la historia : ¡siempre establece un código de actualización en tu MSI! Entonces evitas todo el problema permanentemente. Y no lo genere automáticamente: codifíquelo (lea "Recuperación manual de códigos de actualización" a continuación para obtener una explicación).

Recupere el código de actualización individual utilizando VBScript / WMI (enfoque heredado)

No hay nada malo con la solución VBScript que se encuentra a continuación, incluso tiene algunos beneficios sobre PowerShell , a pesar de que VBScript es una tecnología heredada por ahora. Los beneficios son que debería funcionar en todas las máquinas, incluso cuando falta .NET Framework (o está bloqueado), y en máquinas donde falta PowerShell (o está bloqueado). Es una solución anticuada pero viable que es bastante flexible (a menos que VBScript también esté bloqueado, pero todas las versiones modernas del sistema operativo son totalmente compatibles con VBScript).

Para que sea lo más simple posible recuperar su código de actualización, he creado un " VBScript básico " que debería ser el truco. No ha sido probado para apuntar a computadoras remotas, incluso si WMI debería poder hacerlo por diseño. El script está destinado a ejecutarse en el sistema donde está instalado su MSI misterioso con el código de actualización desconocido.

Este VBScript requiere un código de producto de entrada (el diálogo de entrada se muestra cuando se ejecuta el script), y luego procederá a buscar el código de actualización correspondiente (si corresponde). Como se indicó anteriormente, para ubicar el código del producto para su MSI, puede utilizar este enfoque: ¿Cómo puedo encontrar el GUID del producto de una configuración de MSI instalada? . Una vez que tenga el código de producto (guid), puede ejecutar este VBScript en la máquina de destino y debería recibir el código de actualización en unos segundos. La recuperación de WMI puede ser muy 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://stackoverflow.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://stackoverflow.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://stackoverflow.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 StackOverflow", vbInformation, "Error while retrieving UpgradeCode." End Select

Recuperación de todos los códigos de actualización y código de producto en una máquina

Debo mencionar que tengo un gran VBScript que generará un informe HTML completo para todos los paquetes MSI instalados en la máquina en la que se ejecuta . Esto incluye todos los códigos de actualización y una lista de códigos de productos relacionados (códigos de productos que comparten el mismo código de actualización). Sin embargo, no estoy muy contento con el código (soy un especialista en implementación, no un codificador). El script es demasiado grande, demasiado lento y no se ha probado demasiado , por lo que creo el VBScript básico que se encuentra arriba para realizar la recuperación de un solo paquete. Este script es mucho más fácil de probar y modificar para su propio uso. Puedo proporcionar este gran VBScript para probar si es de interés. Es de solo lectura, aparte de la salida de un solo archivo HTML a "Mis documentos". También debería ser posible adaptar este script para usarlo en computadoras remotas.

Hay un comando PowerShell de una línea para recuperar todos los códigos de productos y códigos de actualización relacionados, pero este relleno de salida carece del nombre de los productos. Lo incluyo aquí para completar:

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

El resultado será similar a esto (el campo "Valor" es el código de actualización; los códigos de producto sin códigos de actualización asociados no aparecerán hasta donde puedo decir):

Recuperación manual de códigos de actualización

Esta sección enumera algunas "formas manuales" para recuperar códigos de actualización que no necesitan ninguna codificación o líneas de comando. Estos enfoques manuales no son los recomendados. Los incluyo solo porque esto intenta ser una " respuesta de referencia ". Se deben proporcionar varias opciones diferentes. Mi recomendación es usar el PowerShell o VBScript proporcionado anteriormente.

Dicho esto, los códigos de actualización generalmente nunca deberían cambiar en las versiones de su producto, por lo que es probable que pueda probar el que encuentre en el archivo MSI o en la fuente utilizada para compilarlo como se describe a continuación. El problema que ya se ha mencionado varias veces es que una transformación puede cambiar los códigos de actualización en el momento de la instalación, por lo que debe recuperar el código de actualización mediante programación si desea asegurarse de encontrar el correcto. A menos que esté intentando obtener el código de actualización de un MSI que no está instalado en su sistema. Entonces solo necesita un visor de archivos MSI como se describe a continuación en el punto 1.

Una transformación es solo un fragmento de base de datos con cambios que se aplican al MSI original en el momento de la instalación . Es una herramienta utilizada principalmente para el empaquetado de aplicaciones corporativas para modificar instaladores sin modificar archivos MSI directamente. Las transformaciones tienen la extensión .mst . Cambiar el código de actualización a través de una transformación es inusual, pero no desconocido, especialmente para el reempaquetado corporativo. En casos excepcionales , los empaquetadores de aplicaciones pueden cambiar intencionalmente la guía de actualización para permitirles entregar sus propias actualizaciones a los paquetes instalados (en lugar de depender directamente de las actualizaciones del proveedor). Raro, pero lo he visto hecho. Si esto es bueno o no es muy discutible.

Maneras fáciles y manuales de encontrar códigos de actualización de MSI:

  1. Aunque es ofensivamente obvio, la forma más fácil de encontrar el código de actualización es abrir el MSI original utilizado para instalar el producto y encontrar el código de actualización en la tabla de propiedades . Todo lo que necesitas es una herramienta capaz de abrir archivos MSI. Aquí hay algunas herramientas: ¿Qué producto de instalación usar? InstallShield, WiX, Wise, instalador avanzado, etc. Su apuesta más rápida es probablemente Orca si tiene instalado Visual Studio (busque Orca-x86_en-us.msi e instálelo; este es el propio visor y editor oficial de MSI de Microsoft), o Super Orca si no tiene instalado Visual Studio. (siga el enlace de arriba para encontrarlo).

  2. Si usted es un desarrollador que usa WiX (o cualquier otra herramienta de implementación), obviamente puede encontrar el código de actualización fácilmente en su archivo fuente WiX que utilizó para compilar su MSI (o fuente Installshield, fuente Advanced Installer, o cualquier herramienta de implementación que sea utilizando).

    • ¡No nos salgamos del control aquí con demasiados consejos bien intencionados que abarrotan el problema principal, pero obviamente debe codificar el código de actualización en su fuente y nunca generarlo automáticamente !
    • Los códigos de actualización definen " familias de productos relacionados " y deben permanecer estables en todas las versiones (versiones). En la mayoría de los casos, también debería permanecer estable en todas las versiones de idioma. La configuración exacta depende de los requisitos de implementación.
    • Si los productos pueden existir uno al lado del otro, generalmente tiene diferentes códigos de actualización para los productos que deben coexistir.
    • Regla general : mantenga los códigos de actualización estables el mayor tiempo posible, siempre que sea posible. Cámbielos cuando los requisitos lo exijan absolutamente.
    • Para concluir: nunca use el mismo código de actualización para diferentes productos que tienen su propio " ciclo de vida " y no tienen una relación real entre sí. No están relacionados Esto es tan importante como mantener estable el código de actualización para productos relacionados. Piense en los requisitos de " ciclo de vida " y " relación familiar " y " coexistencia ".
    • Esa fue una gran digresión, volviendo al tema en cuestión: encontrar códigos de actualización.
  3. Incluso si no tiene el MSI original, incluso es posible localizar el MSI en caché desde la instalación original en la %SystemRoot%/Installer . Los archivos MSI aquí tienen un misterioso nombre hexadecimal, pero son solo copias de los archivos MSI originales utilizados para instalar los diferentes productos, almacenados en caché en un lugar seguro para estar disponibles para operaciones de modificación, reparación y desinstalación. Hagas lo que hagas, no te metas en esta carpeta. Nunca, nunca borres nada . Puede encontrar el MSI que instaló su producto seleccionando el primer archivo MSI y verificando en la barra de estado del Explorador de Windows cuál es el nombre del producto para la versión anterior de Windows. En Windows 10, parece que puede desplazarse sobre un MSI con el puntero y aparece una ventana emergente con algunos detalles de MSI. Luego, simplemente haga clic en la lista hasta que encuentre el producto correcto y abra el MSI y encuentre el código de actualización en la tabla de propiedades .

  4. Algunas personas usan el registro para leer los códigos de actualización: ¿Cómo puedo encontrar el código de actualización para una aplicación instalada en C #? . En mi opinión, este no es un buen enfoque, hay mejores formas, como simplemente usar PowerShell como se explicó anteriormente. No es necesaria toda esta conversión e interpretación de los GUID empaquetados (que es el formato GUID utilizado en la base de datos de registro de Windows Installer).

Eso debería completar los "métodos manuales" primarios para recuperar un código de actualización rápidamente. Solo algunos métodos para el arsenal que a veces son lo suficientemente buenos. Probablemente hay varias formas más que he olvidado.

Prefiero los enfoques programáticos , pero si tiene prisa y trabaja sin todas las herramientas disponibles, algunas opciones manuales son buenas. Sin embargo, algunos de estos métodos manuales requieren más herramientas que la línea de comandos de PowerShell (necesita un visor de archivos MSI que no siempre está disponible en la caja si está en una "misión de soporte" para la máquina de alguien). Ha llegado el momento de usar PowerShell (sí, también me siento anticuado).

Por cierto, los archivos MSI se eliminan esencialmente de las bases de datos de SQL Server almacenadas como archivos de almacenamiento estructurados COM (formato de archivo MS Office). Esencialmente, un sistema de archivos dentro de un archivo con flujos de almacenamiento de varios tipos.

Si está atascado en una máquina sin un visor MSI, puede consultar bases de datos MSI en caché directamente desde PowerShell:

En ciertos casos , puede surgir la necesidad de recuperar códigos de actualización de MSI para paquetes implementados .

Escenarios comunes:

  • Me hice cargo del proyecto MSI de otra persona, y necesito determinar qué códigos de actualización se usaron para versiones anteriores que ya están en la naturaleza. Esto es necesario para manejar escenarios de actualización. No tengo archivo de lanzamientos en ningún lado .
  • Cambié accidentalmente el código de actualización para mi paquete WiX varias veces durante el desarrollo y necesito encontrar todas las versiones del Código de actualización "en la naturaleza". No sabía que los códigos de actualización deberían permanecer estables entre versiones .

Esta es una pregunta de estilo Q / A.

Esta pregunta ha surgido antes en varias encarnaciones, pero esto no es un duplicado . Estoy publicando una forma de hacerlo que utiliza la interfaz principal de automatización MSI (o estrictamente hablando WMI). Debería ser más confiable que los enfoques basados ​​en el registro de las respuestas anteriores. Esta respuesta también trata de resumir otros enfoques de recuperación.


Para satisfacer sus requisitos para usar WMI directamente, o para esos momentos solo necesita un uso único sin Powershell (o necesita usar .bat o lo que sea), use 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

Existen múltiples opciones de formato y salida.