If you want to rely on the native MSI UI then indeed you need to use injection. The sample below shows the technique. It works just fine:
//css_dir ..\..\;//css_ref System.Core.dll;//css_ref Wix_bin\SDK\Microsoft.Deployment.WindowsInstaller.dll;using System; using System.Linq; using System.Xml.Linq; using System.Xml; using System.Windows.Forms; using Microsoft.Deployment.WindowsInstaller; using WixSharp; class Script { staticpublicvoid Main(string[] args) { var project = new Project("CustomActionTest", new ManagedAction(new Id("MyAction"), "MyAction", Return.check, When.After, Step.InstallInitialize, Condition.NOT_Installed)); project.WixSourceGenerated += project_WixSourceGenerated; project.BuildMsiCmd(); } staticvoid project_WixSourceGenerated(XDocument document) { document.FindSingle("Product") .Add(new XElement("UI", new XElement("ProgressText", "Running Server...").AddAttributes("Action=MyAction"))); } } publicclass CustomActions { [CustomAction] publicstatic ActionResult MyAction(Session session) { MessageBox.Show("Hello World!"); session.Log("Begin MyAction Hello World"); return ActionResult.Success; } }