3

How can I author a WiX custom action that

  1. Is always called at the end of an installation, at least if there's an install error
  2. Copies the current MSI log file from its current local to the user's APPDATA folder

I have this managed custom action code. Not sure how to author its invocation in my Wix script. Should the custom action be scheduled for after InstallFinalize? Can it be scheduled OnExit="error"?

    [CustomAction]
    public static void CopyLogFile(Session session)
    {
        const string company = "MyCompany";
        const string product = "MyProduct";
        try
        {
            session.Log("CustomAction.CopyLogFile entry");

            var msiLogFilePath = session.CustomActionData["LOGFILEPATH"];
            if (msiLogFilePath != null)
            {
                session.Log("CustomAction.CopyLogFile MSI log filename: {0}", msiLogFilePath);

                var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                var destDirPath = Path.Combine(localAppDataPath, company, product);

                var destDir = Directory.CreateDirectory(destDirPath);
                session.Log("CustomAction.CopyLogFile Destination directory: {0}", destDir.FullName);

                var destFilePath = Path.Combine(destDir.FullName, Path.GetFileName(msiLogFilePath));
                File.Copy(msiLogFilePath, destFilePath, true);

                session.Log("CustomAction.CopyLogFile Log file copied to: {0}", destFilePath);
            }
            else
            {
                session.Log("CustomAction.CopyLogFile File path not found");
            }
        }
        catch (Exception exception)
        {
            session.Log("CustomAction.CopyLogFile exception {0}", exception);
        }
        finally
        {
            if (session != null)
            {
                session.Log("CustomAction.CopyLogFile exit");
                session.Close();
            }
        }
    }
amo
  • 315
  • 4
  • 14

2 Answers2

2

Yes, you can schedule it after InstallFinalize (so did I, but I copy it every time if it is not a complete removal of the package):

<InstallExecuteSequence>
    <Custom Action="CopyLogfile" After="InstallFinalize">NOT (REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE)</Custom>
</InstallExecuteSequence>

Remember to also add it to the UI sequence if you have any. I added it as event to the PushButton in the SetupCompleteSuccess- and SetupCompleteError-dialogs (maybe you need to add it only to the latter one?) like in the following:

<Dialog Id="SetupCompleteSuccess" X="50" Y="50" Width="374" Height="266" Title="[ProductName]" NoMinimize="yes">
     <Control Id="OK" Type="PushButton" X="230" Y="243" Width="66" Height="17" Text="&amp;Finish" TabSkip="no" Default="yes" Cancel="yes">
           <Publish Event="EndDialog" Value="Exit">1</Publish>
           <!-- ### Invoking copying the logfile if the Finish-button is pressed -->
           <Publish Event="DoAction" Value="CopyLogfile">MsiLogFileLocation AND NOT (REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE)</Publish>
    </Control>
 <!-- ... rest of the dialog ... -->
</Dialog>

Regarding showing it only in case of an error: Maybe checking for the ProductState-properrty? Searched the web for this but didn't find anything useful.

Edit: Maybe a proper way to execute it only in case of an error is the usage of Custom Action flags that execute it only during rollback. In WiX it would be the Execute="rollback"-attribute for the CustomAction-tag.

taffit
  • 1,979
  • 22
  • 23
  • How are you launching the MSI? It might be better to create the log in the user's appdata folder to start with and then remove it if the install is successful. Actually, I wouldn't remove it anyway. You're assuming that success is the same as "no issues". If files don't get updated, CAs don't run etc you will need the log! – PhilDW Mar 26 '14 at 17:28
  • @PhilDW We don't have a bootstrapper that launches the MSI - so we can't launch it with the 'msiexec /l*vx install.log /i myprogram.msi' invocation. The installer reboots the machine on completion. This often results in the %TEMP% folder getting cleared. Since we can't change the log location, I want to copy the log file into a persistent folder. Will try the solutions suggested here. – amo Mar 26 '14 at 19:04
  • What about the MsiLogging property?: http://msdn.microsoft.com/en-us/library/aa370322(v=vs.85).aspx . I have never tried it though. – Stein Åsmul Mar 27 '14 at 18:01
  • 1
    I suppose that he is using this property as I couldn't imagine how to do it otherwise. The logfile is then written to the file specified in the MsiLogFileLocation-property. However the latter one is read only and, if not given a location on the commandline, written to the %TEMP% directory with MSIxxxx.log as name (where xxxx are random characters). So at the end of the installation we can copy exactly the file specified in the MsiLogFileLocation-property. – taffit Mar 28 '14 at 22:16
1

Don't mess with custom actions after InstallFinalize if you can help it. They are often skipped entirely when deploying via tools such as SCCM, Unicenter, etc...

A custom dialog with a button to open the log file at the end of the install could work ok though.

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • [Here](http://stackoverflow.com/a/1801438/1785391) you can find instructions to do it this way. – taffit Mar 26 '14 at 17:09
  • It's not clear to me that you can make a CA work on UAC systems. If you put the CA after InstallFinalize then it has to be immediate, so it won't be elevated, it will run with the installing user's credentials as limited user, and may not be able to access the locations you want to use. – PhilDW Mar 27 '14 at 16:36
  • True Phil, but I assume he just wants to open the log file and I assume he will put that in a position with at least read capability. The whole notion that immediate mode custom actions can change the system should be eliminated from MSI altogether in my opinion - they should run with read-only rights even as administrator. – Stein Åsmul Mar 27 '14 at 17:58
  • Sometimes a not so good solution is better than no solution at all. In my use case at the customer I'm happy to have the logfiles in 99% of installations / repairs / upgrades available in a predefined folder where some other scripts can get them. Not a nice solutions, maybe it smells, but it works. – taffit Mar 28 '14 at 22:08