I probably have a strange request.
I have develop a msi to install two softwares. After the EULA a screen with two checkboxes must come and on selection of either or both of these checkboxes the corresponding softwares have to be installed.
I have used to install a single software earlier never for two.
I would be obliged for any leads.
Cohesion & Coupling: Bundling applications together in a single MSI file, may seem like a
good idea. It seems intuitively nice and simple. However, speaking
from real world experience I almost always end up splitting
applications to install via their own MSI files, and I don't like
multi-lingual setups either (true multi-lingual setups are difficult because translated content is typically not ready when marketing and sales push to release the native language version quickly - typically the English version).
The only time it is really safe to deploy applications together is when they are guaranteed to:
Always be used together by end users
Always get updated at the same time
Won't grow substantially in size over time (Localization, New Prerequisites, etc...)
And normally it is impossible to predict any of this. Typically you will get new requirements quickly.
Central Challenge: What will likely take on a release-cycle of its own? (split it right now). Things tend to happen suddenly! Here are some common challenges:
Bug fixes: if only one application has a bug, management will want to deliver only one new MSI and leave application 2 untouched and without the need to do a whole new QA-run for both applications after install. This is to reduce risk and to deliver a smaller update that is also quicker to test and verify. Patching is very complicated, and generally safer for MSI files that are as simple as possible without too many languages, custom actions or GUI constructs.
Localization: suddenly you get a requirement to make application 1 available in Italian, application 2 does not need to be translated. Language support tends to greatly increase the complexity of a setup, not to mention the size of it. Your "nice and simple" MSI has now suddenly gotten complicated to maintain, and sluggish to build. It is also a real pain if you need a single setup, and you translate it in many languages - you won't be able to compile the RTM version until all the language updates are in. I can tell you right now that marketing / sales people will have no concept of holding back the English version until all localized versions are ready.
QA / UAT: if the applications are large, delivering 2 separate MSI files will make it easier to split the testing effort between different QA teams and to deliver new updates via nightly builds etc...
Release schedule: suddenly the release schedule for the applications change - application 1 is now updated every month, whilst application 2 is updated only every six months. If different users use the applications, how do you deliver updates? Build it all in one MSI and give it a new version number only to have application 2 users install the same application over again?
Apply the overall developer principles of cohesion and coupling to deployment packages, and you will save yourself a lot of trouble. If the applications now OR in the future may take on their own life cycle - split their deployment right away. And who can see into the future?
Please note that you generally will wrap multiple MSI files in a bootstrapper so that users still have only one file to relate to, even if the products are installed via separate MSI files.
Wix update: With the advent of Wix to create complex setups it has become easier to build Wix include files that can be compiled into several MSI files. This effectively becomes a more flexible type of merge module. This may simplify the splitting or merging of MSI files in the future. See a discussion of this feature here. One more link.
Sheer setup size: There are some limitations with regards to how many components and files you can have in a single MSI. Some details:
What are the limits for a large MSI package?
Limitations of a Large MSI package
Authoring a Large Package
UPDATE: WiX allows preprocessor constructs and Burn bundles that can be used to split large setups.
Long description here: Wix Installer : Setting component condition property when doing a MSIEXEC admin install at command line (markup towards bottom)
And about different "variable types" in WiX: WiX (Windows Installer Xml), Create universal variables (there are many: precompiler, localization, burn, etc...)
It can be helpful to "decompose" a huge MSI into several related MSI for this reason and other reasons listed above - in order to make maintenance easier (build and compile speed, rebuild of just one of many MSI files, etc...). Finally you should stick to using a single file per component to make upgrading and patching work properly. Several MSI files can be installed in sequence using bootstrappers or launcher applications such as Burn from WiX, or features in commercial tools such as Installshield and Advanced Installer. Here is an answer which touches on this topic. And just trowing in another answer which is a little bit similar.
Links:
Installing SQL Server 2014 Express as a prerequisite in boostrapper
Windows installer has a concept of "features" which can be selected for installation or omitted. If you have already created a working installer, then you have at least one <Feature> element in your WIX files.
Simply create multiple <Feature> elements and then use <UIRef Id="WixUI_Mondo" /> or <UIRef Id="WixUI_FeatureTree" /> to allow the user to choose which features he wants to install.
You cannot install multiple applications from a single MSI. Even if you figure out a way to do this you really should not.
Instead have separate MSIs for each app and use a bootstrapper to install both. E.g. you can use Inno Setup to generate a self-contained bootstrapper exe which installs both MSIs (and any pre-requisites as well).
BTW, Wix does not handle creating bootstrappers so you need to use it in conjunction with another tool.
You can do nested msi pre windows installer 4.
But you shouldnt anyway it was deprecated for a reason.
The replacement api is to call msiembeddedui and create a transaction chainer.
You can create multiple MSI's then bundle them into 1 containing MSI. The "parent" MSI allows you to choose which application to install then just runs that MSI.
If you really want 2 applications then there are non-MSI installer builders (like NSIS) that let you do that, but you have to do all the work yourself.
Related
I have a requirement to create an installer that will allow users to install multiple named instances of our services and application (i.e. Sql Server style).
I have seen that a product called AdvancedInstaller does this and from what I have read this would be achieved through a Bootstrapper capturing the information and streaming it to the MSI. I am assuming here that a Custom UI Burn implementation should be able to do the same, however I cannot find any samples of doing this exactly or on how to do the 'stream' to the MSI.
If I wanted to go this route would I still need to specify instances in my MSI's?
Currently there are separate MSI's for the Windows Services, Application and then a Bundle Bootstrapper EXE that allows the selection of the services to install.
Thanks
MSI has the concept of multiple instance installations using product code changing transforms. These transforms can (but don't have to be) embedded in the MSI. Here's some background reading.
http://blog.iswix.com/search?q=multiple+instance
Read the IS12 then the IS2009. Expect many broken links as Microsoft destroyed their sites. Here are 2020 links.
https://learn.microsoft.com/en-us/windows/win32/msi/installing-multiple-instances-of-products-and-patches
https://learn.microsoft.com/en-us/windows/win32/msi/authoring-multiple-instances-with-instance-transforms
https://learn.microsoft.com/en-us/windows/win32/msi/installing-multiple-instances-with-instance-transforms
When using embedded transforms you are limited to whatever ProductNames you choose when you built them. You could also dynamically generate transforms and apply them.
WiX's standard bootstrapper application doesn't really have much in the way of supporting all the scenarios I talked about in my blog articles. Other tools such as InstallShield and AdvancedInstaller have more.
As much as I like WiX, and MSI for that matter, this is really advanced stuff that takes a long time to understand, develop and test solutions for. You might want to look at using a tool such as InstallShield or Advanced Installer or simply creating a normal straight up MSI that installs a template of an application and then create your own custom instance management tool that allows the user to spin up multiple instances of your application.
I'm an WiX/MSI/InstallShield/DevOps consultant. To be honest, this would not be an inexpensive project if I was to quote it out for a customer.
We are having a System.BadImageFormatException in our MSI installers. I have already read about the target frameworks, but we already checked and it's targeting the correct framework (.NET Framework 4.5 same with our QA machines).
We have exactly the same source codes, but the results of the msi installer compiled by our 'build team' fails, but the msi installer compiled by us 'dev' works. Question is, does the environment where an application was built and compiled affects the output (example: msi installers)?
There are basically two reasons for this error:
A cross-architecture call from 32-bit code to 64-bit (or vice versa). Different architectures require different MSI setups Heath Stewarts blog and so everything in a 32-bit setup (especially managed custom action code) should be explicitly 32-bit and explicitly 64-bit in a 64-bit install. For example, when an x64 system encounters AnyCpu code it might load the X64 runtime, and then a reference to a 32-bit assembly will fail and get this error.
A .NET framework runtime attempt to load the "wrong" framework. The NET 4 runtime is somewhat backwards compatible, so you are most likely to get this error when code expecting the NET 2 runtime encounters a NET 4 engine. The devil is in the details here, but again, this is much like the architecture issue. If anything loads the NET 2 runtime and the calling sequence tries to call a NET 4 assembly to run in the 2.0 FW it will fail with this message.
Having said that, it's not clear exactly how you are calling the managed code, whether through DTF or something else (such as the Visual Studio InstallUtilLib mechanism). And finally the machine you build on makes no difference to the eventual runtime environment. It's no different from a code file which will work on one machine but fail on another because (for example) it can't find the C++ runtime. The issue isn't the build machine, it's the environment of the target machine.
Some Suggested Debugging Steps
So it is the actual MSI file which triggers these errors, or the application after installation?
Below are some thoughts and questions to consider when trying to debug issues such as these (in no particular order). My bet is on issue 3 in this first list:
Does this exception occur as you run the MSI itself (or is it a setup.exe?), or as you try to launch the application after installation? Just to verify - I assume the MSI.
Do you have custom actions in the setup? If you have managed code custom actions in your MSI, what platforms do you target in your build? Any CPU I would presume? Please verify. I think there are some issues with COM-interop here, but I am fuzzy on the details. Sometimes you may have to pick a specific platform. In this case you can get such error messages (bad image). See section "Managed Code" below for a whole "rant" about managed code and deployment - and some problems that may result.
Regardless of the above, in your WiX source file, what is the value of the Platform attribute in the Product element? Possible values: x86, x64, intel64, intel, arm, ia64. Please report (and try to test with other values as well - x86, x64 for example). This affects the MSI's platform setting. If you don't use WiX - open the compiled MSI file, and check the summary stream for the Platform setting. Using Orca this is View => Summary Information... - look for Platform.
Do you have any malware scanners, security software or other "potential blockers" for MSI compilation and / or installation on your build computer? Or on the test system where you try to install? (We must always mention these issues - people can waste days if we don't - even if it rarely seems to be the only issue).
Is this a localized MSI using Asian characters? (or Arabic, or any other complex character sets?). This I just mention - frankly I don't see how this is 100% relevant, but I want to clarify this "variable" for your scenario (i.e can we eliminate this as a potential error source). It would generally cause runtime errors, not System.BadImageFormatException issues - I believe.
I assume a compare of the different MSI files may not work because one of the files is a "bad image"? Did you try? Maybe it is still a valid COM structured storage file - but the msiexec.exe engine can't handle it? If it is, then tools may be able to read the content inside the file just fine - I don't know, give it a try.
For your scenario: I initially thought a single, compiled MSI behaved differently in different locations (environments) - and hence suggested to check for any damage in transit (network issues, samba issues, storage issues, malware issue, etc...) by doing a binary diff on the copies in the different locations (bit-level comparison). Since you seem to compile two (or more) MSI files from the same sources, such a binary compare is obviously meaningless. Differences are certain.
However, a "content compare" could tell you something - this compares actual content in the tables / streams inside the MSIs. I think I will add a Q/A on how to compare MSI files that I can link to from here (added: How can I compare the content of two (or more) MSI files?). This presumes that the MSI is readable - even if it is not runnable. Only way to know is to try.
I hope and believe that the above list should help you sort out your problem.
I wrote myself off a cliff below on the subject of managed code issues. The idea was to describe a couple of issues to check, but it became a long discussion. I may delete all the stuff below and perhaps resurrect it elsewhere. It may not be relevant for you at all. The overall topic is managed code and how it can crash in new and "interesting" ways:
Managed Code
This is another one of those sprawling answers that got out of hand. I
think it still has value, leaving it in.
A couple of further issues with regards to .NET custom actions (managed code). I am far from an expert on this topic, since I shun them like the plague (for now - this may change over time).
Some of this veered quite a bit off topic - for your purpose - but I will leave it in as general comments on managed code for MSI use.
MSI expert Chris Painter is the man for this topic - he has taken on this potential "world of pain" and seem to benefit from such custom actions too, but these managed custom actions seem generally accepted to be problematic - if you approach them in a naive way. Be pragmatic and weigh benefits against potential problems listed below.
A friendly piece of advice: for worldwide distribution I would never use managed code as of now - though it is "getting safer" - we have to admit that. There are too many potential error sources for a large scale distribution MSI package using such custom actions (home users may uninstall .NET, corporate users may see versions of .NET disabled, and the whole list of problems below, and I fear "catch 22" uninstall problems more than anything - a whole section on this below, etc...).
As I said, I am not an expert, but there are many, and serious problems. Maybe Chris can correct me if they are "sorted" by now. The DTF framework (distributed along with WiX) features support for embedding a managed code custom action dll inside a regular win32 dll wrapper. This helps reliability. I will dig up a few links here for reference. Chris has been a pioneer and early-adopter here.
Partial list of managed code problems for custom action use:
The .NET framework may be missing, disabled or corrupted (entirely or in the version requested / needed for your code). Now, what if all your 3000 corporate packages have a .NET dll with managed code embedded in them? They can't even uninstall in this case - much less upgrade. More below in issue #5.
When targeting different versions of the .NET runtime with different custom actions, all will load the same CLR version. So they tell me (I could not believe it whilst reading it - please read it!). Enough for me to run for the hills :-). "This can blow up in any number of ways" is what I hear myself think. Apply suitable paranoia accordingly! The resident evil of all things rears its ugly head again - etc... Seriously, don't listen to paranoia, but be on alert for serious problems. Is this problem managable? I guess - I would have to say yes, but it is not a problem to ignore. Serious UAT / QA needed on many different OS and .NET versions. Would a native dll do better? I think so.
Components installed to the GAC can not be used as dependencies for your managed custom actions in the setup (chicken or the egg - I suppose). This has to do with the commit models of Fusion / MSI.
Bob Arnson has commented on this - check it out (he is on the core WiX team). I don't know if this still is his top issue with managed code - along with rollback.
Small digression: I have read Arnson stating that VBScript actions are worse than managed code (Painter certainly agrees, and definitely the WiX boss himself Rob Mensching - blog). I think this is true for just about all cases, but not for corporate application package scenarios (which I have experience with) - or ad-hoc testing that will never be used in production (quick and easy).
I describe the reasoning behind this here (pragmatic issue): Windows Installer fails on Win 10 but not Win 7 using WIX (essentially anything compiled adds a source control problem in the real, chaotic world - and corporate packagers have to pick up each other's work on the fly and a fully embedded, transparent source file in the MSI saves the day - all the time, and there is a skill set issue as well, and there is more...).
I do not recommend VBScript for anything but corporate use in controlled environments (standardized workstations). VBScript is not good enough for public, worldwide MSI releases in any shape or form. They can work for read-only custom actions returning no error codes and set to ignore all runtime errors, but no - there are better ways.
UPDATE: I can add that in a snag I would use VBScript in read-only custom actions in the GUI sequence (just a property setter script) in order to get rid of the .NET framework as a dependency altogether. The time will come when the .NET framework is on all target machines, but it is not quite there yet (and even if it is there it could be broken. Windows now actively fixes ActiveScript to always be running - and MSI hosts its own ActiveScripting runtime - scripts will run, but you could easily mess up the code yourself to make the custom actions horrendous still).
I should add that my recommendation to use Javascript over VBScript in the link above will be removed soon. Javascript has proved just as bad as VBScript in practical use, with some added snags that are too detailed to go into. The enhanced exception handling offered by Javascript does not make up for the fact that the MSI API seems to have been tested with VBScript during its development. Javascript was probably not, and hence has a few clunky issues when working with the MSI API that are not immediately apparent. I have wasted costly time on this - I would recommend you don't waste yours.
I also use scripting for testing, prototyping and debugging my MSI packages (to debug property settings, app searches, override command lines for testing, etc...). I find this the quickest way (who wants to compile something ad-hoc for this?). Just don't roll with your script test code for release! If using Installshield I use Installscript for such "scripting".
And for the future: one good use for managed code would be embedded
directly in the MSI, in inspectable (and reusable) form - making custom actions white box - with full source embedded and with full code access security too, making them unable to run with freebasing elevated rights. Just thinking about what could come - let us see what you are doing in this custom action of yours?
To elaborate issue 1, managed code may hard-code a certain .NET runtime version that is not available. I guess this is probably the easier problem to deal with? Correct me if I am wrong Chris. I am just a dabbler with this. Setting "lastest version" could still cause issues though...
Let me add a pet peeve of mine as well: if a managed custom action fails during uninstall due to a corrupt .NET framework (or for any other reason - focused on managed code issues - for example a design / security change in Windows itself from Windows Update) - you can't uninstall and thereby not (major)-upgrade your existing installation. A serious catch 22 in my opinion. Try this if you have 3000 live packages and thousands of desktops to manage and the dll is embedded in each MSI...
Creating custom action code of any kind that trigger errors on uninstall / upgrade was my big fear when making a C++ custom action dll as well - so it is not unique to managed code. A classic error is to set custom actions after InstallFinalize or in the UI sequence to "check exit code" - and a trivial error returned causes full rollback of a major upgrade. A classic "catch 22" - now you can not upgrade without fixing the problem in the old product's uninstall sequence.
Despite this being a general problem for all custom action code, I feel the risk is heightened quite a bit with managed code. What if some weird policy change to the .NET framework makes all packages in a large corporation un-uninstallable and un-upgradeable since they all have embedded the same problematic custom action dll? Or worse yet, it is a Windows design change that you can't roll-back?
A contingency should be available in such cases. This is the core reason I stay away from managed code entirely - I like down to the wire better - fewer layers to depend upon. Minimal dependencies, minimal entanglements (no imperial entanglements). If a minimal dependency C++ dll does not run, then the core of Windows is generally broken and the system needs a rebuild in most cases anyway. For .NET custom actions you would minimally have to fix the .NET framework (which might be easier than I think - for all I know - don't think so though).
I was looking at ways to make the DLL external to all corporate packages in a pre-requisite package (ideally with a minimal, baseline, embedded DLL in the setup itself as well - if the external DLL is missing / not found). The idea being that an external DLL is preferred once available, and upgradable for all packages by a single, updated "prerequisite package". All 3000 packages fixed - all at once?
I never got around to determining the technical feasibility of this. Bear with me, I am getting off topic for your purpose. If the WiX guys are reading - what are the technical possibilities here off the top off your head? Essentially I am expecting to hear "impossible" - and then I am done with it. When thinking about this I was preparing for potential problems with the embedded DLL in Asian and Arabic locations (potentially serious and unexpected and fatal runtime failures due to Unicode / code page issues), and also for any unexpected security changes in Windows (that we keep seeing - Windows 10 ransomware protection which currently intermittently triggers runtime failure for files installed to userprofile folders, or the sudden need for admin rights for MSI repair - kb2918614 which appeared out of the blue on Vista, and whatever else they keep changing unexpectedly...). I did not want to sit with thousands of un-upgradable, un-uninstallable packages - already deployed to tens of thousands of machine.
My "last resort" contingency for corporate use was to "hack patch" all cached MSI files in the local, super-hidden MSI cache folder using a "home grown" patcher EXE deployed by a hotfix package. Generally insane in every way, but it looked technically possible (until digital signatures shuts off the possibility?). And for me the only acceptable "last resort" I could think of if tens of thousands of trading floor machines were hit by disaster suddenly.
I can think of at least two other options - one of which is to minor upgrade affected packages (lots of work, cleaner, guaranteed to work). The last option will not be mentioned :-) - (Voldemort, "those we do not speak of", etc...).
An auto generation feature for minor upgrade patches to patch the embedded custom action dll's was also on my list of contingencies - the minor upgrade would only patch the dll - no other changes. Then problems could be handled on a package-by-package basis. This patch should be available at the click of a button when pointing to a live MSI package in need of patching. An "embedded custom action dll hotfixer". A thing that should not ever be used if at all possible. Contingency "solutions" are rarely pretty.
My two cents: I can think of few scenarios where minimal dependencies are more important than for an embedded custom action in an MSI. It must work on any machine, in any state, in any language, in any location in any installation mode (and uninstall is the catch 22 here) ideally without any non-standard dependencies at all. I statically link C++ code for this very reason. For worldwide distribution I feel this is the only thing that is currently good enough - statically linked C++ code - (with the possible exception of Installscript - from Installshield - which is now running without dependencies apparently - embedded runtime? I don't know how they do it - in the olden days there were legendary problems with the required runtime pre-requisite for the Installscript language. It should be fixed since version 12 of Installshield).
This is not a complete list. It is my "run for the hills list" :-).
No fear though - just be aware of it all - and use the benefits of managed code if they are substantial enough for you, but don't expect entirely smooth sailing is my take on it. I would be upfront with my manager about these potential bear traps, without sounding like a total, paranoid lunatic. A good manager will be able to "sell" any contingency plans as necessities, that you can get time to work on and even demonstrate quickly (believe me, attention span here is short - it has to be the quickest demo ever). The big question is whether you have one package to deal with, or thousands like we do in corporate deployment. Things change a lot for the latter. Risk must be minimized for all features that are embedded in all deployed packages.
If I am 100% honest, it is not as bad with managed code as it used to be. Using DTF and other frameworks have helped. But the potential runtime issues for uninstall problems are worrying. A global change to the .NET framework in the company - and all your packages can no longer uninstall? Or a newer version of the .NET framework reveals unknown bugs in the custom action not found when it was deployed? It may suddenly "manifest itself" on attempted uninstall / upgrade. Managable, but you will curse yourself...
I would prepare your support guys for the above managed code issues - they should know about the issues and really understand what .NET is about.
"We have never seen any problems with our managed code custom actions" - famous last words - to be honest.
If your target computers are uniform and standardized (SOE environment) - which is normal for corporations - then your packages may appear better than they really are (now this is true for packages with scripts too). Just wait for the next SOE version based on a new operating system... I would pilot test early with all packages in the package estate.
You could still face the irony that all target computers start failing in exactly the same way (Windows design changes in Windows Updates, security software updates that trigger interference, SOE updates that fail for some locations, etc...).
For worldwide distribution things are quite different and things tend to fail in any number of ways that are hard to debug and fix or even work out at all. You normally have no access to the problem system at all - for starters. Maybe read some further comments in "The Complexity of Deployment"-section here: Windows Installer and the creation of WiX.
So I would never use managed code for global distribution of a complex package - unless you are delivering a very specific product and know the nature of your target machines in more detail than normal. Cost / benefit.
I would have a contingency for what to do if many machines are affected by unforeseen triggers of "deadlocks" such as not being able to uninstall / upgrade. Some paranoia in this scenario, but not impossible. Silly "war games". Risk is for your manager to manage, and for you to handle technically.
Adding a link to an aging, but still valid FAQ entry from installsite.org on the topic of managed custom actions and their problems: How can I create Custom Actions in Managed Languages, like C#?.
And be skeptical of any custom actions in the first place!
Managed code just adds to custom action volatility. Custom actions are complex and difficult to get right in the first place. They run impersonated or in the wrong context unintentionally, they run twice unexpectedly, they don't run at all when expected to, they run in the wrong installation mode, they crash due to missing dependencies, they cause exceptions due to bad coding that fail upgrades and uninstalls alike by triggering rollback, you hard code references to localized folders so your setup crashes in non-English machines, you name it...
Built-in constructs in MSI itself, or pre-written custom actions (with rollback support) in frameworks such as WiX or commercial tools such as Installshield and Advanced Installer have been tested by thousands, millions or even billions (!) of users - and they are written by the best deployment experts available. Even for these components, bugs are still found - which says it all. Do you think you could do it better on your own? Always prefer ready-made, tested and maintained solutions - if available.
A whole rant about the problems with custom actions in general: Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?
"Sources"
Some further links (some of this content may be showing its age by now, but these are trustworthy sources - not to be ignored - Mensching is the WiX benevolent dictator):
Don’t use managed code to write your custom actions!
Link to more details about the dangers of managed code custom actions in an MSI.
Managed Code CustomActions, no support on the way and here's why.
Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?
Deployment is a crucial part of most development. Please give this content a chance. It is my firm belief that software quality can be dramatically improved by small changes in application design to make deployment more logical and more reliable - that is what this "answer" is all about - software development.
This is a Q/A-style question split from an answer that became too long: How do I avoid common design flaws in my WiX / MSI deployment solution?.
Core: Essentially custom actions are complex to get right because of complexity arising from:
Sequencing-, Conditioning- (when it runs - in what installation mode: install, repair, modify, uninstall, etc...) and Impersonation-issues (security context it runs in).
It results in overall poor debugability - very hard hard work to test in all permutations.
Application Launch: Solution? Prefer application launch code. You get a familiar debugging context and can usually keep the code in the main application source - very important. The issue is the same for: licensing in setups (take it out if you can).
Custom Action Debugging: With all warnings in (you will read the short "folksy" version below - yes you will - Jedi trick) - do use built-in constructs when available - here is how you can improve debugging custom actions though:
Common Causes for Custom Action runtime failures
Debugging Custom Actions
For native code / C++ just attach debugger to msiexec.exe
Advanced Installer's Debug C# Custom Actions video tutorial
Short "Folksy" Version:
Overall: a modern setup should be "declared", not coded. "think SQL queries, not scripting". Apply well-tested logic that you just invoke to do the work. More on that later.
Avoid custom actions if you can.
They will screw with your head (and do murder to your girly figure)!
Seriously: they are the number one cause of deployment failure.
They feature a "conspiratory complexity" whereby things often break unexpectedly and without warning after you have deployed your setup for some time and it is "in the wild".
Deployment is a process - you will have to deal with "past sins" for every new release. It can become a real nightmare to clean things up after broken deployments. Each iteration adds new, potential error sources (my fix for my failed fix, failed, etc...).
Runtime requirements for managed code and scripting custom actions are very error prone (.NET in particular in my opinion). A setup - if anything - should feature "minimum dependencies" - since it is used to install dependencies outright and should run on "any machine" in "any state" in "any language".
Apart from using built-in MSI constructs or WiX custom features, custom actions can often be avoided by minor changes to the application design so that complex custom actions are no longer needed (samples below).
Spend the time to find and review built-in MSI features and extensions from WiX, Installshield, Advanced Installer (and other vendor tools).
These extensions are made by the best deployment experts available, and have in most cases been tested by thousands of people (millions and billions in the case of built-in MSI features).
How can you conceivably match this with your own proprietary code? If the existing solution is good enough - which it normally is - then your own code is entirely added risk for no gain whatsoever. The ready-made solutions even support rollback - a notoriously neglected and hard-to-implement feature - that is actually required by design.
In other words: when you use the existing solutions, you borrow not just the implementation, but crucially also the QA, UAT and testing of the extensions when you use them. This can save weeks of work and contribute greatly to deployment stability.
All that is needed is to spend some time searching and reading up on what is already available, rather than jump-starting things with your own code. Heck, even your own manager could get involved searching... In a dream world.
A setup should generally not be coded, it should be declared! (think SQL). This is what Windows Installer is all about: you declare what to be installed, and the sequence is taken care of by the installer engine itself. Benefits result - when done right.
That's about it really. Read on if you dare! Here be dragons in the midst of serious ranting. And crucially: real-life experience from dealing with both setup development, and also large scale deployment of such setups in corporate environments. Common problems become clearer - they are more identifiable. And you may get burned with problems you really have to answer for - that you feel you could never have foreseen (doing corporate packaging and repackaging you get to see just how much can be wrong with a single package - it can take days to beat them into shape at times).
Please remember, and this is not meant as bad as it sounds: deployment is generally a low status technology endeavor, but a high profile failure. Errors really show. And someone will get to answer for it, and support will really feel it.
Debugging during development is hard, but for deployment it is sometimes nearly impossible since you generally have no access to the problem systems, and each problem system will be in a totally different state.
In all honesty: failing to get software deployed correctly to end users may be close to being the most expensive error to make in software development - nobody can witness the greatness of your solution - and it affects sales, support, marketing and further solution development.
Poor deployment can definitely sink a product. Unfortunately good deployment isn't enough to save a product.
Fleshed Out Ranting Version :-)
As stated above this section was split from an existing answer with broader scope: How do I avoid common design flaws in my WiX / MSI deployment solution? (an answer intended to help developers make better deployment decisions).
Erroneous or unnecessary use of custom actions.
A plethora of deployment problems can be caused by custom action use - most of them very serious. If your setup fails to complete or crashes, it is a fair bet that a erroneous custom action is at fault.
Accordingly the obvious solution is to limit your use of custom actions whenever possible. Custom actions are (often) "black box" (hidden code) whereas most of MSI features a lot of transparency. The MSI format can be viewed easily (COM-structured storage file), and everything that an MSI file does can essentially be deduced from its MSI database file - with the exception of compiled custom actions (script custom actions are still white box - you can see what is going on, unless they are obfuscated).
In this age of malware, these black box custom actions - that run with elevated rights - may become frowned upon in more ways than one. They are not just stability and reliability issues, but a full-blown security issue.
6.1 The Overuse of Custom Actions
Pardon the "trifles" listed below. A lot of this may be banality, but maybe use the arguments listed to make a case for yourself to avoid custom actions and to work on better solutions - usually involving smarter application launch sequence and application self-configuration. Trust us, application coding will be more interesting than dealing with Windows's Installer's complex conditioning, sequencing and impersonation for custom actions.
The below has been updated so many times that sections are a little bit out of sequence or repetitive here and there. Will be cleaned up as time allows.
Developers are good at coding - so with all due respect - you tend to overuse custom actions to do things that are better done using built-in MSI features or ready-made MSI extension solutions such as those available in WiX for advanced things such as XML file updates, IIS, COM+, firewall rules, driver installation, custom permissioning for disk and registry entries, modify NT privileges, etc... Such support is also found in commercial tools such as Installshield and Advanced Installer.
It is also possible to do a lot of what is done in custom action as part of an application's launch sequence. The prime example is initializing user data and copying settings file to each user profile. There is a little summary of this issue here: Create folder and file on Current user profile, from Admin Profile.
It is obvious, but very often custom actions are used out of ignorance of what is already available "out of the box" by means of ready-made solutions. This happens to all of us all the time, doesn't it? There is always some smarter way to do things that would have saved you lots of grief? In general anyway - though sometimes you are breaking new ground. Don't break new ground in your setup - unless you absolutely have to! Save it for your application.
I want to emphasize that these built-in Windows Installer solutions and extensions from WiX and commercial tools have been written by the best deployment specialists available. And moreover, and even more importantly, they have been used and tested by thousands, millions - heck even billions of people for built-in MSI features. Do you really think you can do any better? Moral of the story: pick your battles and use your great coding skills to solve new problems, and let deployment be as dumb as possible. Use what already works, and don't reinvent the wheel. There are too many unknowns in deployment, too many variables that can't be controlled - you are dealing with "any machine" in "any state" and in "any language". See the Complexity of Deployment section here if you want examples - a bit down the page - just a short dump of all the ways your target systems may differ in their states when your package hits it. Each variable is a new bear trap for custom code - from OS version, to application estate to malware situation. The list goes on and on. As the conclusion reads in the linked content: "Deployment is a simple concept, with a complicated mix of variables that can cause the most mysterious errors - including the developer favorite: the intermittent bug. As we all know the seriousness of such bugs can not be overstated as they are often impossible to debug properly."
Certain advanced things must be done in your setup - since they require elevated rights and your application should not request this whilst running. This is what a setup is for, advanced, elevated system configuration - so embrace this complexity, but use ready made solutions! Don't roll your own script and solutions, use built-in, well tested stuff. Will your script run correctly in Korea? Will your custom action be blocked by a major anti-malware solution of caliber that you never had the time to test your script with? Do you have time to write your own check for whether a certain prerequisite runtime is installed on the computer - which works in all locales and across all OS versions? The potential for bugs here is staggering - and sometimes impossible to test properly. Do you have test machines in Arabic, Chinese, Korean or Japanese? Maybe you do. But do you have a terminal server to test on? How about a Korean terminal server? Did you test your setup with MSI advertisement? For advanced system management features to work, you have to make your setup as dumb and standard as possible. Spend several days looking for ready-made solutions before you write anything on your own I'd say. Remember, with ready-made solutions you are not just borrowing their code, but crucially their creator's QA, testing and UAT - which you can almost never hope to repeat.
Real-world testing is the only yardstick that matters - there is no substitute. Don't take on this world of pain! A slight change in Windows deployed via a Windows Update and your custom action breaks in any number of ways. Choose a better battle to make use of your skills. If you fight the design, then Windows installer fights back.
And there is a lot going on with deployment that makes it complex - and not dumb like we want it (just copy some darn files), your fight is to make it as simple as possible, but no simpler. Here is a list of deployment tasks showing why it is hard to get your package "dumb enough": What is the benefit and real purpose of program installation? Use only ready-made constructs whenever you can - it is the first easy win. All you need to do is to read and search a little.
Finally I will add that all custom actions are supposed to support rollback to put the system back to the original state if the install fails. In the real-world this is almost never done in an ad-hoc custom action (in my experience). Believe me it is complicated to deal with - I fear the word "rollback" as a Siberian husky fears the word "bath" after I implemented MSI rollback in C++. Not the most fun I ever had, but it eventually worked properly. If you want your setup to be without too many dependencies, C++ is the way to go, and as we all know it is not trivial to deal with. The ready-made solutions support rollback out of the box - it is an easy-win for only a bit of reading and searching to enable them. Complexity yes, but you are on more solid ground. And crucially: once an obscure error happens on a Japanese machine we can work for a community fix, or a third party vendor needs to sort it.
After all those "general observations", on a purely technical level, custom actions in Windows Installer are very complex with regards to implementation, scheduling, conditioning and rollback, and should hence be used when absolutely necessary (often for early-adopter stuff). A further complexity is runtime requirements - for example dependencies on specific versions of the .NET runtime, or PowerShell, or Installscript runtimes (scripting language of Installshield - it had a runtime dependency, but this is largely solved now, it used to be a problem).
Errors from missing runtime requirements can be a enormous hairball to deal with - for zero gain. For this reason I only use minimal dependency C++ dll's or Installscript when making custom actions. It happens that I use VBScript or JavaScript for read-only custom actions in the user interface sequence. These just retrieve data, and make no system changes. These are the only types of custom actions that are not that error prone. They should however be set to run without checking exit codes (to prevent them from triggering rollback or abort in a setup that is being run - often in major upgrade mode).
Also: Windows Installer hosts its own scripting runtime engine, so you know your active scripts (VBScript, Javascript, etc...) can run unless your target system is actually broken (there is no missing runtime on a normal system). This is in contrast to managed code custom actions - it is entirely possible for target systems to have no .NET runtime at this point (Jan 2018). Now this will change in the future, as .NET becomes a really built-in and required feature in Windows (or some minimal version of it hosted by Windows Installer itself). There are still problems with managed custom action code failing for strange reasons - such as the wrong .NET version being used to run it, or the wrong version of the CLR being loaded and being used, etc... I have limited experience here, but the problems are serious in my opinion. Eventually, though, we will all write managed code custom actions I think. I would still use C++ for worldwide distribution scenarios though.
Powershell scripts are particularly hairy for custom actions as they apparently run out of process and can't access the MSI's session object (source: MSI expert Chris Painter). Powershell also requires the .NET framework to be installed. I would never use Powershell script for custom actions - not even for internal, corporate deployment. Your call. Just as a "sample", here is an expert in the field stating his opinion (aging blog item, but still relevant if you ask me): Don’t use managed code to write your custom actions!
I tried to write a summary of pros and cons of different custom action types. Frankly I am not too happy with it, but here it is: Windows Installer fails on Win 10 but not Win 7 using WIX. What I am not happy with? The recommendation of JavaScript for one thing - I have used it seldomly, and although it is a better language than VBScript - particularly for error handling - I have had lots of problems using Javascript with MSI. It may be a case of the problem existing between the keyboard and the chair :-), but I think there are some real gotchas with JavaScript as well. Try to avoid complex use of scripts. For simple things like retrieving properties they seem to work OK for me. However, the experts in the field are merciless on script custom actions: Don’t use vbscript/jscript to write your custom actions! (Aaron Stebner), VBScript (and Jscript) MSI CustomActions suck (Rob Mensching - WiX benevolency).
Let me also add that custom action complexity is "silly, conspiratory complexity" not fun-to-deal-with stuff. It bites you. Gotchas. You will discover all the mistakes you have made in due course - as you move along (and then you have some explaining to do) - they will often not be immediately obvious (problems suddenly arise when upgrading, patching, uninstalling, your custom action runs erroneously during repair because it is not conditioned properly and wipes out certain registry settings, silent install doesn't work properly - it leaves the install incomplete because the custom action only exists in the user interface sequence, there are runtime errors on Windows XP that you never tested your custom action code with, there are broken things on target systems that you didn't shield yourself from, someone calls you and tells you your package doesn't work with active directory, your package can't be advertised, it fails on all Korean and Japanese systems, self-repair triggers runtime warnings and access denied for normal users, etc...). You will have no time to fix this properly once it hits you, and you will likely have to proceed with sub-standard solutions to get yourself ahead over the next hurdle. And no, I didn't experience all of this myself. In fact I discovered most of these problems when fixing up third party vendor MSI files for corporate deployment. You really discover a lot of potential error sources when you see, compare, review and adapt hundreds of packages to a corporate standard for large scale deployment. In all honesty there are serious shortcomings and errors in all but the simplest of packages. And obviously you get to see what you did wrongly when you made such vendor setups a few years earlier. And guess what tops the list? Overuse of custom actions when built-in constructs were available.
And to add to it all, the inherent complexity of deployment with its requirement to work on any machine, anywhere in any state, there is the issue of MSI technology borderline anti-patterns. Parts of the MSI technology that are causing repeated deployment problems because they are poorly understood, and sometimes fragile in real-world use. There is a brief summary of this in this answer (towards the bottom): How to make better use of MSI files (along with a list of the very important corporate benefits of MSI - and a random dump of common technical problems seen in real-world packages). Particularly the latter link has struck me as less than ideal after I wrote it. Take it for what it is: messy, real-world advice without much else going for it. It identifies too many problems without showing much in the line of fixes in places.
A substantial proportion of a software's support calls tend to come from problems seen during the deployment process. As the story goes: "...failing to properly install your great software may be close to being the most expensive error to make in software development. You can never hope to sell a software that was never possible to test" (from one of the linked answers above). A bad custom action is very often behind such problems.
The most common unnecessary custom action uses we see are in my opinion:
You install Windows Services via custom actions. This is much better done in the MSI itself using built-in constructs.
You install .NET assemblies to the GAC via a custom action. This is fully supported by Windows Installer itself without a line of (risky) code.
You run custom .NET assembly installer classes. These are to be used for development and testing only. They should never be run as part of deployment. Rather your MSI should use built-in constructs to deploy and register your assembly.
You run prerequisite setups and runtime installers via a custom action in your own MSI. This should be done entirely differently. What you need is a bootstrapper that can launch your setup and its prerequisites in a sequence. Commercial deployment tools such as Advanced Installer and Installshield have features for this, but free frameworks such as WiX has support via its Burn feature, and there are also free GUI applications such as DOTNetInstaller (untested by me) with these kind of features.
Please take my word for it in this particular case: running embedded setups via a custom action will fail eventually - usually rather immediately. MSI is too complicated in its scheduling, impersonation, transaction, rollback and overall runtime architecture to make this possible. Only one MSI transaction can run at a time by design, and this makes things very complicated. It used to be you could run embedded MSI files as a concept in MSI, but this was deprecated - it didn't work properly. You must run each setup in sequence. The correct sequence. There are bootstrappers / chainers available that will allow you to define such an installation sequence. Here is an answer which describes some of them (don't let the question title throw you off - it is about bootstrappers / chainers and other deployment considerations): Wix - How to run/install application without UI.
6.2 Custom Action Alternatives
The ready-made solutions found in WiX and other tools such as Installshield and Advanced Installer, are tried and tested, and crucially also implement proper rollback support - a feature almost always missing from custom action implementations - even in otherwise good vendor MSI setups. Rollback is a very important MSI feature. You cannot compete with the quality delivered from a large user community with active use and testing in all kinds of environments. Make use of these features.
Apart from using built-in MSI constructs or WiX custom features, custom actions can often be avoided by minor changes to the application design so that complex custom actions are no longer needed. I see licensing as an example of how deployment can be simplified to improve reliability.
This is a very important point, and one that is very often ignored. Sometimes some quality hours or days of coding and some quality UAT / QA time can prevent long term deployment problems from ever existing. No amount of support time can solve the worst deployment problems you can create.
This answer provides a blurb about the overall complexity of deployment: Windows Installer and the creation of WiX (towards the bottom). Deployment is a complicated "delivery process" with several serious challenges: 1) the cumulative nature of deployment errors, 2) the difficulty of proper debugging, and 3) the virtually unlimited range of external factors and variables affecting target machines world-wide - the conclusion is that deployment must be made as simple as possible to be reliable. There are so many intervening factors leaving you with the developer favorite: the intermittent bug. The link above is recommended for a more fleshed out explanation.
6.3 Advanced Custom Action Problems (beyond runtime failures)
A very common custom action issue is their incorrect scheduling and attempting to modify the system from "non elevated" immediate mode actions. These are advanced MSI design flaws not immediately recognizable for people who see an otherwise working setup.
Never insert immediate mode custom actions after InstallFinalize in the InstallExecuteSequence of your MSI that attempt to modify the system (read/write). These actions will never run if your setup is deployed in silent mode via deployment systems such as SCCM (again, last time I checked).
Never try to change the system using immediate mode custom actions activated from the setup GUI. This will appear to work for admin users, but immediate mode custom actions are not elevated and hence regular users will not be able to run them without error. In addition any changes to the system done from the MSI GUI will never be done when the setup is run in silent mode (then the whole GUI sequence is skipped). This is a very serious MSI design flaw: installing silently and interactively causes different results. This issue is mentioned in section 10 on silent install as well in this answer: How do I avoid common design flaws in my WiX / MSI deployment solution?. Silent install is a crucial feature for corporate deployment of your software. In corporations with control of their deployment, ALL deployment is done silently. Your setup GUI is simply never seen. There are only a few exceptions I can think of, such as certain server deployments that may be done interactively, but all desktop and client software is deployed silently. Not supporting silent install properly is hence a horrendous deficiency and design flaw of your MSI setup. Please heed this advice. It is crucial for corporate acceptance of your software - I have recommended certain software to be thrown out from the standard system because its deployment is so dangerous for the system that we just don't want to deal with it. Virtualization and sandboxing (APP-V - virtual packages - or full on virtual machines) are big today precisely because of these issues (misbehaving applications and setups).
All custom actions that make changes to the system must be inserted in the "transacted section" of the installation sequence. This Windows Installer Transaction (think database transaction commit) runs between the standard actions InstallInitialize and InstallFinalize in the InstallExecuteSequence and runs with elevated rights. All changes to the system are to take place in this transaction - anything else is erroneous (but unfortunately quite common). All custom actions inserted here should have a corresponding rollback custom action implemented as well, and this should undo any changes done to the system in case the install fails and gets rolled back.
The idea that custom actions should be limited comes from the fact that it is easy to write a poorly implemented custom action. A poorly implemented custom action is one that, in the event of installation failure, cannot roll back changes already made to the system (i.e. installing a windows service, for example).
That being said, if a custom action is written such that it has a complimentary rollback custom action in place, then I don't think its a problem.
The pattern I like to follow is that for every "custom action" that I think I might need (for example, FoobarCustomAction), its actually 3 consists custom actions:
FoobarCustomActionImmediate - This is an immediate custom action that prepares 2 payloads:
First, a payload to pass to FoobarCustomActionDeferred, which dictates the system altering changes to make.
Second, a payload to pass to FoobarCustomActionRollback, which dictates how to rollback the system altering changes.
FoobarCustomActionRollback - This is a rollback custom action that is scheduled before FoobarCustomActionDeferred in sequence, that uses the payload provided by FoobarCustomActionImmediate to rollback the changes made by FoobarCustomActionDeferred in the event of a critical failure.
FoobarCustomActionDeferred - This is a deferred custom action that makes all of the system altering changes to the system.
Like many other technologies, I think there is always a way to write poorly maintainable code in WiX. Take the example above, if this is a custom action that I want to use in many different installers, I should provide the developers a .wxs file containing a fragment that ensures all needed custom actions are referenced and sequenced correctly. If instead, the WiX code is simply copy pasted carelessly across many different installers, the chance of the custom action being implemented incorrectly increases. Its our job as developers to help consumers of our code fall into the pit of success, and I think WiX provides that through careful use of fragment and wixlibs.
But the developer of the installer has to care about such things, WiX does not enforce it!
There are several resources around the web (including here) for migrating InstallShield projects to WiX Toolset, and it's understandable (move from costly product to a free one).
However, I couldn't find anything about the opposite direction - suppose there are several WiX Toolset projects which we want to move into InstallShield (due to issues with WiX licensing). True, we can go ahead and rewrite the projects, but the risk of losing or misinterpreting something is high.
Before we start to develop some sort of automated migration script, I was wondering if it has done before, have anyone ever heard of such a thing?
InstallShield does not have a .wxs importer. However hidden in the File > Open dialog, in the drop down part of the Open button, is the option to Open with Wizard (or, I believe, Open As > Wizard in earlier versions). You can use this to convert a built .msi file into a project file. However if you want it to be a good project file, you will likely still have to perform significant clean up. And be aware that minor upgrades or patches are likely to be difficult or impossible across this tool change.
I don't recall whether this option is available in the InstallShield automation interface, but I think I would prefer to convert and vet each project by hand anyway.
I'm currently learning how to create msi installers using WiX and it seems I've hit a wall.
All is well when I create an MSI containing everything needed for a single environment.
I have features, and components, and can install my MSI.
Now I'm at the stage where I want to convert this in a SQL Server-style installer, where you have multiple instances support.
At the start I want to user to get a screen which allows him to create a new instance, or manage already existing instances. (to update/remove them)
I've spend 2 full days looking everywhere for a solution, without much luck.
I've found the following resources with some info on it, but either they're limited in the number of instances, or don't describe how to such a bootstrapper which gives a user the option described above.
Multiple Instance MSI's and InstallShield 12
Multiple Instance Transforms Walkthrough
Multiple instance installations and patching
Has anyone achieved this already using WiX? Or can anyone point me towards some working examples on how this is achieved?
I know Installshield 2009 can do this, but since this is just a hobby, I don't have the money to buy that. Also I'd like to do it in WiX, since the upcoming Visual Studio 2010 will improve support for it.
Creating multiple instances is pretty easy with WiX v3. You just use the InstanceTransform and Instance elements to create everything. Now, the bootstrapper problem requires something outside of the WiX toolset since we don't have burn, yet. I'm not sure we'll get this functionality in WiX v3.5 (with burn) but it is on our list for burn post v3.5.
Although I've never created a multi-instance setup, I also noticed that Acresso announced MI support in IS 2009. We have IS 2009 but didnt use this feature.
However, Installshield often simply makes use of new MSI features by offering an "intuitive" frontend to them (like for chaining multiple MSIs together into one). So you might want to look for general information on how to achieve that by using the MSI SDK.
Here are some useful links that might point you to the right direction:
Authoring Multiple Instances with Instance Transforms
Multiple Instance Transforms Walkthrough, Proposed Simple Addition to WiX to Make Them Easier