How to create Docker build agent image with SDK installed from MSI

· Read in about 3 min · (470 words) ·

When creating build agent docker image usually you need to install SDKs from MSI (like Infragistic, DevExpress, Active Reports etc.).

There are couple of challenges here:

  • Windows Docker doesn’t support UI.
  • Also very often you have to populate UI with values.

For this purpose MSI supports so called unattended installs.

For input values you can pass those as parameters to MSI on command line.

Let’s assume that we want to install SDK like Infragistic.

How to find out MSI command line

Use MSI logging

First run the SDK MSI from command line on a sandbox PC so it produced installation log:

msiexec /i NetAdvantage_WinForms_20112.msi /L*V infragistic.log

Now follow the installation

Now looks into generated infragistic.log file and look for values you entered.

Piece of log file:

...
Action 20:16:29: ExecuteAction.
Action start 20:16:29: ExecuteAction.
MSI (c) (A4:F0) [20:16:29:526]: PROPERTY CHANGE: Adding SECONDSEQUENCE property. Its value is '1'.
MSI (c) (A4:F0) [20:16:29:535]: Grabbed execution mutex.
MSI (c) (A4:F0) [20:16:29:535]: Incrementing counter to disable shutdown. Counter after increment: 0
MSI (c) (A4:F0) [20:16:29:535]: Switching to server: COMMON_DOCUMENTS_LOC="C:\Users\Public\Documents" USER_DOCUMENTS_LOC="C:\Users\voloda\Documents" INSTALLDIR="C:\Program Files (x86)\Infragistics\" AGREE_AND_INSTALL_OFFICE_2007_UI="No" INSTALL_SERIALNUM="1234" COMMONDOCUMENTS="C:\CommonDocuments\" TARGETDIR="C:\Program Files (x86)\Infragistics\" ALLUSERS="1" DOTNETV4="1" IGSHORTCUTDIR="C:\Users\voloda\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Infragistics\" INSTALLDIR.B2768727_084D_4283_A045_7A86BAF639DC="C:\Windows\SysWOW64\GAC\" INSTALLDIR.4ED14E0A_AECA_4FCD_BEF6_35F299C4270E="C:\Windows\SysWOW64\UltimateKeys\" _INSTALL_PROD_CODE="48" INSTALLDIR.D348289C_580E_44C6_A617_A90FC315DB7D="C:\Windows\SysWOW64\UltimateKeys\" INSTALLDIR.52DB8F59_5C03_491A_99D2_1A0565A67FD2="C:\Windows\SysWOW64\UltimateKeys\" INSTALLDIR.96F9412E_4A28_4BF2_B6B7_66F921C4BE3C="C:\Windows\SysWOW64\UltimateKeys\" INSTALLDIR.7295D7F7_BBA6_41D4_8E45_780AD1F07B46="C:\Windows\SysWOW64\UltimateKeys\" CURRENTDIRECTORY="C:\Users\voloda\docker-tests\windows-nbo" CLIENTUILEVEL="0" CLIENTPROCESS
MSI (s) (F0:94) [20:16:29:547]: Running installation inside multi-package transaction C:\Users\voloda\docker-tests\windows-nbo\NetAdvantage_WinForms_20112.msi
MSI (s) (F0:94) [20:16:29:547]: Grabbed execution mutex.
MSI (s) (F0:C8) [20:16:29:579]: Resetting cached policy values
MSI (s) (F0:C8) [20:16:29:579]: Machine policy value 'Debug' is 0
MSI (s) (F0:C8) [20:16:29:579]: ******* RunEngine:
           ******* Product: C:\Users\voloda\docker-tests\windows-nbo\NetAdvantage_WinForms_20112.msi
...

Keep in mind that for example passwords, serial numbers etc. might be in the log masked so you need to be a bit inventive to find all important values.

General suggestion for MSI is that any properties which have upper-case names should be available on command line.

MSI properties seems to be specified here:

MSI (c) (A4:F0) [20:16:29:535]: Switching to server: COMMON_DOCUMENTS_LOC="C:\Users\Public\Documents" USER_DOCUMENTS_LOC="C:\Users\voloda\Documents" INSTALLDIR="C:\Program Files (x86)\Infragistics\" AGREE_AND_INSTALL_OFFICE_2007_UI="No" INSTALL_SERIALNUM="1234" COMMONDOCUMENTS="C:\CommonDocuments\" TARGETDIR="C:\Program Files (x86)\Infragistics\" ALLUSERS="1" DOTNETV4="1" IGSHORTCUTDIR="C:\Users\voloda\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Infragistics\"

For Infragistic and my build agent I am interested in following entries:

  • INSTALL_SERIALNUM
  • AGREE_AND_INSTALL_OFFICE_2007_UI

Use Orca editor

Microsoft provides as a part of MSI SDK Orca.exe which allows to edit MSI database.

Following the above rule about upper-case names you can find properties which can be specified on command line.

This can be actually easier but requires MSI SDK with Orca.exe installed.

Dockerfile

Once we know parameters we can just update the Dockerfile so it copies SDK to the image and then executes unattended installation the SDK including the license (or whatever details you need).

In this case we specify the license number (INSTALL_SERIALNUM=1234) and bunch of other properties.

The example below ensures that during building the image we wait until the installation process finishes.

COPY NetAdvantage_WinForms_20112.msi "C:\\"

RUN $ErrorActionPreference = 'Stop'; \
    $VerbosePreference = 'Continue'; \
    Start-Process -Wait -PassThru -FilePath c:\windows\system32\msiexec.exe -ArgumentList '/i c:\\NetAdvantage_WinForms_20112.msi  /q /l* c:\\infragistic.log INSTALL_SERIALNUM=1234 ALLUSERS=1 AGREE_AND_INSTALL_OFFICE_2007_UI=No'