📜 ⬆️ ⬇️

Using C # and Wix # to create msi packages

From the translator: English-speaking IT bloggers usually start such articles with the words I'm so excited. I learned about Wix # completely by chance and I hasten to share this discovery with the habrasoobschestvom, because everyone who has dealt with the “naked” WiX knows how unpleasant this process can be. And now you can make the msi-distribution, writing just a few lines in C #! In my opinion, this is cool! And relatively recently (December 4, 2014) the author of Wix # Oleg Shilo gave an interview to InfoQ. I present the translation of this interview to your attention. And I ask you not to judge strictly the tracing of some words - the same “deployment” is somehow closer to me than “deployment”.


InfoQ: For those of our readers who have not heard of Wix #: what is it?

Oleg : Wix # (WixSharp) is a framework for creating deployment (deployment authoring framework) based on the Windows Installer (MSI). Wix # allows you to build a full-fledged MSI distribution kit with a specification written in C #. A typical Wix # source file consists of regular C # code that uses C # classes to define WiX entities.
')
Wix # solves a lot of problems when creating MSI. In an elegant and original way, it circumvents the typical limitations of MSI / WiX. Wix # after other transcompilers of type Script #, CoffeeScript or GWT uses the source code in a syntactically more convenient language (in this case C #) to get the source code in a less convenient language (WiX). "Syntactically more convenient" in this case means less redundant and more readable code. Code in which there are more checks at compile time and for which more advanced tools are available.

Also, Wix # removes the need to create MSI (Custom Actions) submodules in a completely different language (for example, C ++), allowing both components and behavior to be described in the same language (C #). It also makes it possible to have a more uniform, simple and consistent source code structure.

But more importantly, Wix # provides a level of abstraction that hides all the complexity and non-intuitiveness of MSI / WiX and allows you to express the deployment algorithm in a more natural way. The code below is a typical example of Wix #, which shows a script for creating an MSI file for installing the My App application:

using System; using WixSharp; class Script { static public void Main() { var project = new Project("My App", new Dir(@"%ProgramFiles%\My Company\My App", new File(@"\\BuildServer\LatestRelease\Bin\MyApp.exe"), new File(@"\\BuildServer\LatestRelease\Bin\MyApp.exe.config"), new File(@"\\BuildServer\LatestRelease\Docs\readme.txt"))); project.GUID = new Guid("6f330b47-2577-43ad-9095-1861ba25889b"); Compiler.BuildMsi(project); } } 

Of course, Wix # can also perform more complex scripts (Custom Actions or even its own UI on WPF or WinForms), but the code above is a great example of what its essence is.

Wix # is part of the CS-Script utility set: an open source script engine for executing C # scripts. InfoQ readers may already be familiar with it, since I already spoke about it in my previous interview about the CS-Script plugin for Notepad ++.

InfoQ: Why did you choose the API format for Wix #, and not the domain specific language (DSL) format?

Oleg : The purpose of Wix # is not to replace the XML syntax with something else. This would solve only one of the many practical limitations of the MSI + WiX bundle. With Wix #, I wanted to reduce the development of deployment to ordinary programming. I wanted the most common software developer to create a solution for deployment as quickly and comfortably. DSL would mean that developers need to learn the next syntax and suffer from the lack of auxiliary utilities like Intellisense. Also, DSL would most likely require a separate language to create Custom Actions. I wanted C # and your favorite development environment (IDE) to become a “one-stop-shop” service for developing deployment. And then your team does not need a separate WiX-specialist, it becomes enough common programming skills to implement almost any deployment scenario.

However, there is a less obvious motive for rejecting the DSL approach. A typical DSL task is to translate one syntax to another, or to convert one software model to another. The translation task in the WiX context has very little practical meaning. Despite the ease of implementation, this will only translate the WiX syntax into simpler, but keep all the limitations of MSI. On the other hand, it is the transformation to a new, cleaner and more intuitive programming model that is exactly what WiX needs. Such a transformation is usually achieved using high-level general-purpose programming languages ​​(C # in the context of Wix #). And after that, a new programming model is usually tied to a new DSL syntax. However, in the case of Wix, the last step (syntax binding) will not be useful. The vast majority of Windows developers are quite familiar with or at least familiar with .Net languages. So the new DSL syntax would bring only extra overhead. So I decided to stop at C #.

Notwithstanding the foregoing, DSL over the Wix # software model can be meaningful and easy to implement. But that's another story ...

InfoQ: Besides the complexity of the format, what do you think is the biggest obstacle to adopting WiX?

Oleg : Very good question. Yes, WiX is really very complicated, but the real obstacle is not the complexity, but the close connection with MSI. WiX radically simplifies access to the MSI software model. However, this model itself, and not the difficulty of accessing it, is the root of the problem. So WiX users are still dealing with the inconvenience of MSI, only now using XML.

Here I would like to stop and say a few words in defense of WiX. The imperfect MSI software model is not WiX's fault. In fact, given that WiX has done for MSI, it’s almost impossible to expect him to fix the limitations of MSI. To truly appreciate WiX, we need to look back at the development of Microsoft deployment technologies.

When MSI was introduced, he tried to be "the answer to all questions." And, like many Microsoft technologies, it was overly complicated from the start. Since then, he has not changed. Microsoft implemented many complex functions in MSI that today have very little practical value (for example, components, MSM, advertising installation ...).

And there is nothing surprising in the fact that Microsoft realized the problem and got rid of all these functions in their last attempt - ClickOnce. ClickOnce is a very simple deployment framework. In fact, Microsoft completely abandoned the MSI concept and implemented ClickOnce from scratch as an alternative. He is light, smart and minimalistic (in a good way). True, it is more closed, not expandable and not customizable.

Due to internal flaws, MSI is not very development friendly. An MSI file is a database file. Deployment logic is defined via data in tables. Microsoft assumed that MSI would be created by manually filling out this data, field by field, using their Orca MSI table editor. This provided a huge income for InstallShield (by overcharging MSI support), but left developers with nothing. And then WiX happened. And stopped the "chaos of MSI." WiX absolutely deserves all the praise for making the order and turning the creation of MSI into the task of software development (and not driving data) - “building binary files from sources”. In this way, WiX allowed these MSI tables to be populated using an XML file, rather than manually. However, this did not change the essence of MSI development. With WiX, developers still had to (and should still) think in terms of “MSI-tables”.

Just a couple of weeks ago, one of the WiX users # shared his solution for a simple MSI script when you only need to edit the registry. The problem is that MSI / WiX requires you to set the installation folder ... even if you don’t put a single file, but only enter the keys in the registry. The solution is to specify a dummy folder and then ... the “delete folder” operation in order to avoid physically creating the folder during installation. All this is needed not because of deployment requirements, but because of MSI’s difficult to explain limitation: the folder table must have at least one entry.

WiX #, on the other hand, allows you to automatically create an entry for a stub folder and completely hides the complexity of MSI / WiX:
 var project = new Project("MyProduct", new RegValue(RegistryHive.LocalMachine, "Software\\My Company\\My Product", "Message", "Hello"), new RegValue(RegistryHive.LocalMachine, "Software\\My Company\\My Product", "Count", 777)); project.GUID = new Guid("6f330b47-2577-43ad-9095-1861ba25889b"); Compiler.BuildMsi(project); 


The WiX equivalent of the code above will be about 40 lines of very dense XML code plus a batch file for running the WiX compiler and linker.

“Dummy Folder” is not an isolated case. There are many other MSI / WiX syntax “obstacles” that are solved in Wix #.

Many WiX gurus believe that such proximity to the MSI architecture is the power of WiX, because it gives absolute access to MSI functionality. I disagree. I’m sure that this hinders the adoption of a whole technology, as it ignores the needs of the developer. Thus, WiX is completely MSI-oriented instead of being developer oriented. But we should not blame WiX for this. I'm not even sure that WiX should even think about it. In my opinion, another layer is needed here that would take requirements / specifications (for example, a Wix # file) and convert it into an MSI-DB specification (WiX file).

WiX plays the same role in the MSI environment as IL plays in .NET. IL gives you absolute access to the capabilities of the CLR, but no one uses it for development. We have all the high-level .NET languages ​​for this. So if I rephrase the question as “what is the biggest obstacle to adopting an IL?”, The answer will be simple. There is no need for acceptance. For development, we have much better options than IL (while IL is a vital part of the whole .NET technology). And Wix # is an attempt to bring at least one of these “best options” into the MSI domain. So Wix # or any similar solution is just the next step in development after WiX.

InfoQ: In addition to facilitating the creation of basic installation packages, what do you see as the most interesting feature of WiX #?

Oleg : There are several very important things worth mentioning.

1. First of all, it is the indestructible simplicity of managed (Custom) Actions, which derives from the power of the high-level programming language (C #):
 using System; using WixSharp; class Script { static void Main() { var project = new Project("CustomActionTest", new ManagedAction("MyAction", Return.check, When.After, Step.InstallInitialize, Condition.NOT_Installed)); Compiler.BuildMsi(project); } } public class CustomActions { [CustomAction] public static ActionResult MyAction(Session session) { MessageBox.Show("Hello World!", "Embedded Managed CA"); session.Log("Begin MyAction Hello World"); return ActionResult.Success; } } 


2. Its UI. Wix # not only allows you to insert a regular WinForms dialog into the UI sequence. It also gives you the opportunity to create your own GUI and slip it into the MSI engine runtime. This fantastic feature offered by the MSI API is completely overlooked by almost all the MSI creation frameworks, despite the fact that Microsoft uses it in many of its products (in particular, Office installers, Visual Studio).

I consider my own UI to be a very controversial deployment technique and I do not advise (for design reasons) developers to go this way. But I just could not ignore user requests and still implemented it. Below is a screenshot of a WPF example (from the Wix # distribution) for your own UI:
image

3. The last feature I would like to mention is the extensibility of Wix #. Deployment description is just a declaration of C # classes. It can be easily improved using its auxiliary classes to simplify or change the usual installation conditions. For example, instead of listing all the files, you can create a class (for example, AllFiles) that will run through the folder structure and do this for you dynamically. So the installation script will not need to be changed when you need to include a new dll in the distribution:
 var project = new Project("My App", new Dir(@"%ProgramFiles%\My Company\My App", new AllFiles(@"\\BuildServer\LatestRelease\*.*"))); 


In the case when Wix # capabilities are not enough, you can directly work with the generated XML (WiX) content using the Wix # compiler event handlers (just before the XML is passed to the MSI compiler). You can add or remove any element or attribute from the XML tree. The examples show how to install an ASP.NET site using built-in WiX functionality # and how to do the same by inserting the required XML right before compiling.

By the way, the number of examples in the Wix # distribution is so significant that it makes up ~ 95% of all Wix # code.

I believe that at this stage of the Wix # life cycle, its main functionality is almost complete. So new opportunities will provide more horizontal development than vertical. They will be mainly devoted to integration with development tools and greater convenience of the framework for developers. My plans are to publish Wix # in NuGet ( done , comment perev. ), Providing the full equivalent of the MSI user interface, but as an external set of WinForm dialogs, developing a separate plug-in for Notepad ++ and, possibly, an MSBuild task with a project template (currently Visual Studio treats Wix # like a normal C # project). And, of course, processing user requests.

Wix # is available on CodePlex under the MIT license.

Source: https://habr.com/ru/post/253819/


All Articles