¿Hay alguna forma de hacer que msiexec haga eco en stdout en lugar de iniciar sesión en un archivo

8

Como parte de una tubería de entrega continua, me gustaría instalar un msi en una máquina determinada. msiexec plus psexec hace esto perfectamente, pero parece que msiexec solo puede iniciar sesión en un archivo y lo necesito para iniciar sesión en stdout / stderr.

En este momento, para volver a obtener la salida en nuestro software CI, tendré que agregar un segundo paso para hacer eco del contenido del registro, lo que parece un poco inútil.

¿Alguien ha enfrentado este problema antes (y superarlo)?

Gracias de antemano por cualquier ayuda aquí.

marca

mrmrcoleman
fuente
Utilice el registro de archivos integrado de msiexec y lea de nuevo desde el disco. Se pueden iniciar varios procesos msiexec.exe durante la instalación, y creo que sería difícil redirigir la salida de todos ellos. Es posible que vea procesos msiexec.exe generados automáticamente que se ejecutan en diferentes contextos de seguridad y también para ejecutar acciones personalizadas. Una lata de gusanos con los que debería tratar.
Stein Åsmul

Respuestas:

5

Revisé esto nuevamente, y aquí hay información actualizada :

Es posible suprimir la GUI de MSI y establecer una GUI externa implementada por un tercero. Esta GUI externa puede recibir mensajes de msiexec.exe mientras realiza la instalación. Esto es principalmente para implementar una barra de progreso personalizada , pero parece que también puede interceptar la mayoría de los otros mensajes de error y mensajes de estado: función MsiSetExternalUI .

El parámetro interesante es el dwMessageFilter . Al configurar esto, puede, por ejemplo, recibir solo los mensajes de error que ocurren durante la instalación, o eso parece. Supongo que esto puede ser suficiente para la mayoría de los propósitos.

INSTALLUI_HANDLER MsiSetExternalUI(
  _In_  INSTALLUI_HANDLER puiHandler,
  _In_  DWORD dwMessageFilter,
  _In_  LPVOID pvContext
);

Lamentablemente, no tengo un código de muestra para esto en este momento. Probaré esto más tarde, cuando configure mi sistema correctamente. La función MsiEnableLog es una llamada de función relacionada que permitirá el registro en el archivo. Actualización: esto es lo que parece un ejemplo de SDK en funcionamiento .

En el nivel de interfaz de línea de comando , también puede configurar el registro para vaciar su búfer inmediatamente al archivo agregando el ! parámetro:

msiexec.exe /I "IsWiX.msi" /QN /L*V! "C:\msilog.log" 

Esto significa que el archivo de registro se escribe continuamente, por lo que no se pierde el búfer de registro si msiexec.exe falla. El costo es un instalador significativamente más lento debido a la sobrecarga de E / S.

Stein Åsmul
fuente
3

MsiExec solo puede iniciar sesión en un archivo, por lo que tendrá que seguir haciendo eco del contenido de ese archivo una vez que finalice el instalador.

Ansgar Wiechers
fuente
1

Prefiero almacenar en caché el archivo de registro MSI en el sistema local de forma permanente en una ubicación común para cada instalación, y luego simplemente registrar el código de salida de toda la configuración. Si la configuración informa de éxito, ¿el archivo de registro es bastante poco interesante? ¿Solo más "ruido"?

Aparte de eso, hay varios sistemas de entrega de software que capturarán la información de registro para una instalación de MSI y la almacenarán centralmente. Un ejemplo es SCCM (Microsofts renombrado Systems Management Server - SMS).

Para configurar el registro de todos los archivos MSI, consulte la sección "Globalmente para todas las configuraciones en una máquina": http://www.installsite.org/pages/en/msifaq/a/1022.htm

Stein Åsmul
fuente
0

Yo uso el siguiente script de PowerShell. Todavía requiere escribir el registro en un archivo, pero también escribe el contenido en vivo en stdout:

$main_process = Start-Process -FilePath ".\installer.exe" -ArgumentList "/S /V`"/qn /l*! output.log`"" -NoNewWindow -PassThru
$log_process = Start-Process "powershell" "Get-Content -Path output.log -Wait" -NoNewWindow -PassThru
$main_process.WaitForExit()
$log_process.Kill()
exit $main_process.ExitCode
inkychris
fuente