Search code examples
windowswindows-installergithub-actionspowershell-cmdlet

How to execute MSI file on Github Actions (windows-latest runner)


Context

I created a Github Actions workflow that generates a .msi file that I wan't to execute afterwards to test if the application is working as expected.

The workflow implementation is as below

build-windows:
    runs-on: windows-latest
    steps:
      - uses: actions/[email protected]
      - name: Create binary from branch
        run: |
          choco install make
          make build-windows
      - name: Generate msi
        shell: powershell
        run: .\.github\scripts\windows\gen-win.ps1
      - name: Install msi
        run: |
          echo "Start Msiexec"
          msiexec /qn /i "file.msi" /L*vx!
          echo "End Msiexec"

Basically this workflow creates the .exe file (Create binary from branch step), then use a script in powershell that generates the .msi file (Generate msi step), and finally try to install the .msi file (Install msi step).


Issue

The problem occurs on the Install msi step, the runner logs only returns:

Start Msiexec
End Msiexec

... without showing any log, or creating the directories and files as the installation should do on the $HOME directory.


What I tried

Using the default shell for windows-latest runner (which is cmdlet), I tried to run those commands in the workflow without success, using "file.msi" or "path/to/file.msi":

msiexec /i "file.msi"
msiexec /qn /i "file.msi"
msiexec /qn /i "file.msi" /L*vx!

I'm not very familiar with the windows operating system, but for what I searched online, this msiexec command should work.

I also tried to install the .msi file generated manually on a windows 10 computer using those commands with success (so the generated .msi file is valid and working locally). However, it opens another prompt window automatically showing the installation and setup logs (it's not in the same terminal window) and I imagine this may not happen on Github Actions.


Question

➡️ How can I install this application from the .msi file through a command line on the windows-latest runner?


Solution

  • After asking the same thing on the Github Community forum, I got the following answer from @Simran-B (Github Advisory Council Member):

    msiexec doesn’t seem to log anything to a terminal. If your MSI does (even if in a separate window), then it must be something that is specific to that MSI…

    What msiexec supports is to log to a file. Based on Is there anyway to get msiexec to echo to stdout instead of logging to a file - Server Fault, I successfully ran the following PowerShell script (using a Blender MSI as a test):

    $file = "file.msi" 
    $log = "install.log" 
    $procMain = Start-Process "msiexec" "/i `"$file`" /qn /l*! `"$log`"" -NoNewWindow -PassThru
    $procLog = Start-Process "powershell" "Get-Content -Path `"$log`" -Wait" -NoNewWindow -PassThru 
    $procMain.WaitForExit() 
    $procLog.Kill()
    

    I can’t recommend /l*vx!, because the forced flush for every log line makes things slow and the verbose output with additional debugging information can produce thousands of lines. Alternatively, you could log everything to a file without flushing, wait for msiexec to exit, and then print the file contents to the console in one go, which should be significantly faster (but you lose live logging).

    If I remember correctly, GitHub-hosted runners use elevated permissions by default. In my local test, I had to run the above script from an elevated PowerShell because the MSI tried to install to C:\Program Files\, which is not writable unless you have elevated permissions, and that made the installation fail without obvious log entry. If there’s something wrong with the .msi path, you may get an exit code of 1619 ($procMain.ExitCode), which is also not very intuitive. Another possible reason for nothing getting installed (at least apparently) can be that you don’t actually wait for msiexec to finish - the command immediately returns and the installation process runs in the background. You can use Start-Process with the -Wait option or get the handle with -PassThru and call .WaitForExit() on it to wait until it is done.

    It worked for me! With those commands, I could execute the .msi file to install the software, then use it afterwards in my github actions workflow to perform my tests!