Adding extension items

Mar 21, 2016 at 9:25 AM
I am wondering is there a way to add the "extended" wix elements, like util:XmlFile or util:RemoveFolderEx except of modifying the wix source by using WixSourceGenerated event handler?
Mar 22, 2016 at 5:01 AM
The main Wix# idea is that most of the WiX extensions can be easily implemented with C# form managed custom actions or events. For example C# XDocument gives you way more power and ease to troubleshoot than uti:XmlFile extension. Though I am not so sure if C# is always better than util:RemoveFolderEx.

However in many cases WiX extensions represent a valuable opportunity to define a complicated runtime behavior in a declarative way. Thus many extensions eventually found their way to the Wix# codebase (e.g. ServiceInstall). But in order to be utilized from Wix# the extensions need to be integrated with the engine via the dedicated extension bindings. And I don't see any good way of adding them "automatically" without the triggering the core development. Except of course with XML-Injection.

Thus if you have a good next extension candidate for integration then nominate.
Mar 22, 2016 at 5:16 AM
Okay, TBH I thought that the main Wix# idea is simplyfing the development of the installer and it's really helpful in that.
Also I believe that the custom action is the last resort and there is no need to apply it if the built-in functionality like util:XmlFile exists.
Mar 22, 2016 at 7:11 AM
I understand where you are coming from. I honestly do. :)

I don't see much value in just providing only the binding (in this case C#) for WiX XML schema even if it has 100% coverage. This is not going to address the over-engineered WiX nature, which it inherited from MSI. Even MS recognized this with their MSI effort.

Wix# is an attempt to capitalize on the wonderful WiX tooling but provide a new better view of MSI model. That is why Wix# will never expose WiX components and some other schema elements that have limited relevance for the modern deployment approaches. It's also consistent with the Wix# attitude of extending default WiX functionality with the brand new opportunities provided by .NET runtime. That is why managed actions are in not way "the last resort". They are a first-class citizens among with other new concepts like debugging, ManagedUI and setup events.

I talk about this in more details in my interview for InfoQ: http://www.infoq.com/articles/WixSharp

But don't get me wrong. WiX has an enormous set of functionality that can be integrated with Wix# naively (as opposite to being XML-Injected). And the fact that I may under appreciate certain features doesn't mean they have no place in Wix#. Log the feature request. If I am immediately convinced it's already enough to trigger the development. If "dislike it with passion" but it gets up-voted by the users it will still go ahead. Unless of course it destroys the Earth :)

Cheers,
Oleg
Mar 23, 2016 at 6:26 AM
Prompted by your post I have implemented a generic interface for integrating WiX extensions not supported natively in Wix# via user defined entities (classes).

It is a pre-release and it's probably a week (or so) from being properly released. The documentation and samples are done but not integrated with the rest of the wiki yet (with the pre-release only). You can access the documentation here: https://wixsharp.codeplex.com/wikipage?title=WixSharp%20extensions.

This opens the door for users extending Wix# without modifying the Wix# core. This way one can even create the library of Wix# extensions and reuse it in house or share with others.

When implementing the interfaceI decided to use your proposed util:RemoveFolderEx as a sample (and I thank you for this).

This specific WiX extension is the best highlight of the mind bending nature of MSI/WiX API model. Oh man! this is exactly why I wrote Wix# :)
All info is taken from the official WiX documentation and common knowledge based sources. http://wixtoolset.org/documentation/manual/v3/xsd/util/removefolderex.html
https://www.hass.de/content/wix-how-use-removefolderex-your-xml-scripts

WiX extensions
These are the key points of how the extension works:
  • The extension creates a custom action for adding temporary rows to the RemoveFile table at runtime for each subfolder of the root folder you specify.
  • The temporary rows must be written before the CostInitialize standard action because MSI doesn't create properties for the Directory hierarchy in your package until later, in the CostFinalize action. Thus you cannot use directory IDs as folder identifiers.
  • A workaround for this limitation is to write the directory path to the registry.
  • For proper invoking util:RemoveFolderEx you must schedule another action for creating and reading property from the registry search.
  • After you are done you may need to clear the registry.
Wix# events
And this is how the task of removing the folder (e.g. InsatllDir) looks with project events:
project.AfterInstall += (e) =>
                        {
                            if (e.IsUninstalling)
                                 System.IO.Directory.Delete(e.InstallDir, recursive:true);
                        };
It speaks for itself. The only possible reason for not using events in this use-case is the constrain for .NET as a deployment dependency.
Mar 23, 2016 at 6:52 AM
Wow, that was fast! I will check it out as soon as I can. In the meantime my customers rejected the Burn Standard Application UI I mentioned in another thread and insist on using the traditional installer interface(
Mar 23, 2016 at 7:02 AM
That is strange. As you mentioned "Burn Standard Application UI" is native (not managed) application. Meaning that MSI+Burn is as traditional as it gets.
Mind you that you can indicate for BA to show the MSI package UI but BA UI will also be visible.

I feel for you. If you need to install who MSIs than you can either install them manually one after another or automate it with any sort of bootstrapper (e.g. Burn). But there is no other way. MSI does not support for embedding MSI in MSI. My native booutstrapper was a hack and I cannot call it a proper solution.

The only thing to consider can be a MergeModule. But even my MS it is no longer considered as a recommended technique.




Oleg Shilo
--------------------------------------------------------------------------------------------
Website: http://www.csscript.net
E-Mail: [email removed]

Mar 23, 2016 at 7:21 AM
That is strange. As you mentioned "Burn Standard Application UI" is native (not managed) application. Meaning that MSI+Burn is as traditional as it gets.

Actually I was using the Burn Std App + UI themes, the code that generates it look like:
new Bundle("MyApp"){
                                Application = new LicenseBootstrapperApplication()
                                {
                                    LicensePath = @"res\license.rtf", LogoFile = @"res\Logo.png",
                                };
                Compiler.WixSourceGenerated += (document) =>
                {
                    var bundle = document.Root.Select("Bundle");
                    if (bundle != null)
                    {
                        XNamespace balNs = "http://schemas.microsoft.com/wix/BalExtension";
                        var wixApp = bundle.Descendants(balNs + "WixStandardBootstrapperApplication").FirstOrDefault();
                        if (wixApp != null)
                        {
                            wixApp.SetAttributeValue("ThemeFile", @"res\RtfLargeTheme.xml");
                        }
                    }
                };

                var bootstapperFile = Compiler.Build(bootstrapper);
I downloaded RtfLargeTheme from https://github.com/wixtoolset/wix3/tree/develop/src/ext/BalExtension/wixstdba/Resources
If you open it by using Wix's ThmViewer then you can notice the diff between the traditional UI and the Burn UI.

It's probably feasible to adjust the theme so that the UI looks more traditionally, but I already faced a ton of issues with it, for example the file name for logo should be "Logo.png", otherwise the package generation will fail.

Now I am trying silent bootstrap app provided by WixSharp...
Mar 23, 2016 at 7:34 AM
Edited Mar 23, 2016 at 7:38 AM
SilentBA has some constrains imposed by Burn flaws: https://wixsharp.codeplex.com/discussions/645838

You may also have a look at Wix# External_UI samples.
These are a few points:
  • ManagedUI provides completely custom (no limits) managed UI as a plugin assembly for Burn native bootstrapper.
  • ExternalUI is a completely custom (no limits as well) managed UI without an intermediate bootstrapper.
Any bootstrapper is an external UI for the MSI file (WiX Burn or Wix# ExternalUI). Meaning that inside of your External_UI you can start as many MSIs as you want. An atractive part of the ExternalUI is that is has no dependency on MSI runtime. It is 100% independent external process that communicates with MSI runtime (via remote messaging). Read more here: https://wixsharp.codeplex.com/wikipage?title=Deployment%20scenarios#_external_ui

Image
Mar 23, 2016 at 10:51 AM
Edited Mar 23, 2016 at 10:52 AM
On a completely unrelated note, you can simplify your WixSourceGenerated if you use Wix# XML Fluent extensions:
project.WixSourceGenerated += (document) =>
{
    document.Select("Wix/Bundle")
            .FindSingle("WixStandardBootstrapperApplication")
            .SetAttribute("ThemeFile", @"res\RtfLargeTheme.xml");          
}
And starting with the next release I enabled support for AttributeDefinition in LicenseBootstrapperApplication. Thus you will be able to set the attribute even without using WixSourceGenerated:
Application = new LicenseBootstrapperApplication()
              {
                  LicensePath = @"res\license.rtf", 
                  LogoFile = @"res\Logo.png",
                  AttributesDefinition = @"ThemeFile=res\RtfLargeTheme.xml"
              };