How to catch the OnBuildCompleted event to sign my setup file?

Dec 1, 2015 at 9:49 AM
Edited Dec 1, 2015 at 10:21 AM
I need to sign (by certificate) my setup.msi file after it has been built.
In Setup.cs I have next code:
 static void Main()
        {
            ManagedProject project = CreateSetupProject();

            ValidateAssemblyCompatibility();

            project.BuildMsi(); 
            
            SignSetupFile(project); // after "Clean, Rebuild" no all files are made by BuildMSI, so the setup.msi doesn't exist at the moment when I want to sign it with signtool.exe. Only  setup.wix file exists in output folder.
        }
The problem appears only on "Clean" build (after Clean, and Rebuild commands)
I thought that method BuildMsi will return path (looking into the source code), but it returns null.
if I delete sign file logic or to second build after the first one - all is OK. Looks like the creation of msi is async process.
So, is there any buildComplete event to be sure, that BuildMsi has finished own work and all files have been created?

Or what is you suggestion for this?
Dec 1, 2015 at 11:54 PM
The creation of msi is not an async process. It doesn't return until the build succeeds or fails. An empty return value indicates that your build fails. Your comment "setup.msi doesn't exist" confirms that. Meaning that on a first attempt some input files are not ready/found and this is the problem that you need top fix.

Have a look at the BuildMsi output of analyse Compiler.ToolsOutputReceived event data to see what exactly upsets WiX compilers.

BTW you may want to have a look at Signing sample, which demonstrates how to sign MSI with Wix#:
string msi = Compiler.BuildMsi(project);
        
int exitCode = Tasks.DigitalySign(msi,
                                  "wixsharp.pfx",
                                  "http://timestamp.verisign.com/scripts/timstamp.dll",
                                  "my_password");

if (exitCode != 0)
    Console.WriteLine("Could not sign the MSI file.");
else
    Console.WriteLine("the MSI file was signed successfully.");
Dec 2, 2015 at 8:58 AM
Edited Dec 2, 2015 at 8:58 AM
An empty return value indicates that your build fails. Your comment "setup.msi doesn't exist" confirms that.
But how could it be, that build doesn't fail, if the last line of my code is project.BuildMsi(), but fails, if after that string there will be even your Tasks.DigitalySign() method?
Each time and only on clean build. It means, that some files during the first build are creating (writing) too long and msi is not ready to be created and the process is fininshing in a background (direct async writing to the files for example).
Dec 2, 2015 at 9:13 AM
> But how could it be, that build doesn't fail, if the last line of my code is project.BuildMsi(),
I cannot explain that. But you've seen the Wix# source code, It always wait fro WiX compiler to finish with Process.WaitForExit().

The easiest way to solve the problem would be to create a "Hello World" style project that exhibits the problem and send it to me.

If it cannot be done you can test your asynch build assumption. You can modify the code as below:
var msi = project.BuildMsi();
Console.WriteLine("MSI: " + msi);
//have here whatever code that fails the build
This should produce the following output:
ProductName: MyProduct
Version    : 1.0.0.0
ProductId  : {6fe30b47-2577-43ad-9095-1861ca25889c}
UpgradeCode: {6fe30b47-2577-43ad-9095-1861ba25889b}
 
Auto-generated InstallDir ID:
  INSTALLDIR=%ProgramFiles%\My Company\My Product
MSI: c:\users\<user>\documents\visual studio 2015\Projects\WixSharp Setup15\WixSharp Setup15\MyProduct.msi
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
The output above was produced by the default Wix# project template. The placement of the "MSI: c..." below the "INSTALLDIR..." line indicates that execution in my case was synchronous. Let's see what it does in your case.
Dec 3, 2015 at 9:42 AM
Ok, I'll try and continue to test. Thanks