Search code examples
visual-studioinno-setupsetup-projectuser-account-control

Can I run a command before the setup.msi?


I have a desktop application and its installer project produces two files in the Release folder: let's call them setup.exe and setup.msi.

In the post build event I sign the setup.msi with a self signed certificate. Then my final installation batch is composed of three steps

  1. Adding user store certificate with a start.cmd (or start.exe)
  2. Running the setup.exe. Notice that the important thing is that it shows a user account control for a verified author with my name and surname.
  3. Removing (with a stop.cmd or stop.exe) the certificate at point 1 for security reasons/best practices since it is self signed

Now I'm perfectly fine with this solution, I only wished to include the commands 1 and 3 inside the setup.exe if it was possible in a standard way.

What I have tried to do is to define the start.exe and stop.exe as custom actions. In that case I only have the two files setup.exe and setup.msi but unfortunately I get an unkown publisher. I guess it is obviously because the custom actions go inside the .msi and not in the setup.exe. But I'm not an expert of installer projects so someone might suggest a better and standard solution.

Alternative approach

Is that something that I could much more easily do by switching to Inno Setup and maybe as suggested in this comment?

References


Solution

  • Updated answer

    Sorry, I've tested my original answer below and it is "wrong" in a sense:

    actually I get a single click installer but then the Windows operating system anticipates the user account control before such single click installer and it shows an unknown publisher, which defeats the purpose of point 1 (and 3).

    So, short, updated answer: it is impossible(*) to do that in a standard single-click exe, like the ones produced by the SFX module mention below.

    (Note *): though it is doable by compiling a custom C# code and by adding files to the Resources.resx, for example _7zr.exe, etc... like in this example:

    using System.IO;
    using System.Diagnostics;
    namespace selfextractinstaller
    {
        class Program
        {
            static void Main(string[] args)
            {
                string file_path_7zr = @"_7zr.exe";
                using (FileStream fs = new FileStream(file_path_7zr, FileMode.Create))
                {
                    byte[] pgm_bytes = Properties.Resources._7zr;
                    fs.Write(pgm_bytes, 0, (int)pgm_bytes.Length);
                }
                string file_path_config = @"config.txt";
                using (StreamWriter sw = new StreamWriter(file_path_config, false))
                {
                    sw.Write(Properties.Resources.config);
                }
                string file_path_7zSD = @"_7zSD.sfx";
                using (FileStream fs = new FileStream(file_path_7zSD, FileMode.Create))
                {
                    byte[] pgm_bytes = Properties.Resources._7zSD;
                    fs.Write(pgm_bytes, 0, (int)pgm_bytes.Length);
                }
                Process.Start(file_path_7zr, "b");
            }
        }
    }
    

    A similar code can be actually used as a self extracting installer that is not elevated and does not require the UAC!

    Further Readings

    Original answer

    In absence of other answers, I'll proceed with a SFX module for installers, by packaging all the three .exe at points 1-3 (plus an install_all.bat running them in sequence) into a self extracting installer, that will automatically extract all the needed files (certificate included) and finally run the install_all.bat