I'm creating an installer for a client at the moment but I know that I'll have to create another in a couple of weeks for a different client. What techniques do people use to keep things tidy? The only differences will be whether to include certain dlls with the installer and which initial config file to include.
I was thinking of creating a main wxs file which has most of the share installation information on it and a secondary file which would be customised to the client which would control which components should be included.
Either that or rewrite the main wxs file for each client but that means maintaining a full wxs file for each client with lots of duplicated information.
I assume many other people have come across this situation and I would like to know if I'm on the right path or if there are other much better solutions.
Thanks for any help, Neil.
The solution you choose will depend on how extensive the differences are going to be between the different client installers and how many different clients you'll have to support.
If you only have to maintain 2-3 client installers with max of 10 variables files between them just create a single shared .wxs file that brings in a client-specific .wxi based on build-time parameters. It's easy enough to manually create and maintain 2-3 client-specific .wxi files.
If you have to maintain more clients, or there are 50 different possible dll/config file permutations I'd make use of WiX's heat.exe "harvester" tool. You would create a staging directory for every client you had to support that contained the dlls/config files required for each installer, use heat to harvest each directory into separate .wxs files, and then create a single shared .wxs file that would compile against each of the different harvested .wxs files to create the client installers. This solution requires the build process to be a little more complicated, but it's easier than trying to maintain 20 different client-specific wix files.
Related
We have a product with more than 100 'pieces' most of which are optional 'plug-ins'. We would like a non-programmer to be able to make a "customized" installer on a per-customer/sale basis. Our ideal would be simply a single executable/msi with a folder structure from which files/folders could be deleted, then when run the installer would simply not offer features corresponding to the deleted bits.
A separate, but similar issue is that the developers of these plug-ins are not installation experts and we would prefer not to have to edit shared installer source to add/remove one from our build-set. We've been using the "synchronized folders" feature of Advanced Installer for this, but we would like a separately selectable feature for each plug-in.
Is there an installer tool-chain that can support such(or similar) behavior?
If so does anyone have tips on how to actually implement it using said tool?
I created such a tool stack at my last job. We did product line development with dozens of service families, hundreds of features, thousands of merge modules and tens of thousands of files in a typical installer.
Each merge module was authored using IsWiX and compiled using WiX. We then used WiX XML as an input to our build automation system to generate InstallShield installers. A service family would have an XML file to describe it's portion of the feature tree and it would all get emitted into an empty InstallShield project.
Finally a product XML file would describe the INSTALLDIR, UpgradeCode and other meta along with which features to consume. We built dozens and dozens of installers off this common base code.
It would take days to explain everything but that gives you the idea. For a simpler environment you could create a UI to generate WiX code and then compile it into an MSI.
But I don't know that I'd ever give this to a non-programmer. Creating installers is programming.
There is no tool that creates features at runtime in the MSI package, at least no MSI based tool. This complicates too much the installer logic, as you would need a very complex custom action that reads the contents of the folders found next to the installer and then generate entries in the following MSI tables: Files, Directory, Component, Feature, FeatureComponents. And then inter-connect all of this.
That is not something easy to do at all, and very error prone is tried by something how does not have extensive experience in building MSI packages.
have you considered/tried any non-MSI package builders?
I have created three different solutions for three different clients, but those solutions are for an app that have the same features, classes, methods, resolution, except for the images, XML resource files, and a web service reference, that are specific for each one.
I would like to have just one solution for all those apps, that I could open in VS2010 IDE for edition, without errors. So, when I need to build or publish an specific app, I just set the client which one I need to, and go ahead to building or publishing.
It is important to consider that XML file names will be the same, as classes and images names too. The difference will be the content, but the name will always be the same.
My intention is to reduce my effort to maintain many solutions, having just one solution to work with.
In my company, we will have more than those three clients soon, so I am worried about how to maintain that. The best way will be have just one solution and when I need to generate a new app for a new client, I have just to change/include a few things (like some resources and images) and compile to a new client folder.
Is it possible? If so how?
One option would be to have a master solution which had the following
A "Template" project that contained your actual application and all of the shared code
Projects for all of your clients
In the projects for your clients, you could have links to the files in your files that come from your shared project. Then, in each of those projects, you could add the files that are only specific to them.
With this kind of structure, whenever you made a change to your Template project, all of the client projects would be updated as well because they just have pointers back to the Template project.
A good reference for this kind of setup would be the Json.Net Code Base. There he has a solution and project for all of the different configurations, but they all share the same files.
In terms of ensuring that the xml files are named properly, you might just want to put some checks into your main application to ensure that it has all of the files needed or potentially add a check into your build process.
There are many ways you could look to tackle this.
My favorite would be to run some sort of pre-build step - probably outside of Visual Studio - which simply replaces the files with the correct ones before you do a build. This would be easy to automate and easy to scale.
If you are going to be building for many more than three customers, then I think you should look to switch from Visual Studio building to some other automated build system - e.g. MSBuild from the command line or from something like TeamCity or CruiseControl. You'll find it much easier to scale if your build is automated (and robust)
If you don't like the file idea, then there are plenty of other things you could try:
You could try doing a similar step to above, but could do it inside VS using a pre-Build step.
You could use Conditional nodes within the .csproj file to switch files via a project configuration
You could look to shift the client-specific resources into another assembly - and then use GetResourceStream (or similar) at runtime to extract the resources.
But none of these feel as nice to me!
We have a VS2010 Solution which contains one windows form application and 4 Class Library (DLL) projects. (The class libraries are things like BusinessTier, DataTier, CommonCode, ControlLibrary) The whole thing is targeted for framework 2.0. Its been like this for three years.
Ok
So our application has grown to the point where we want to add a large new feature and marketing wants to deploy it as a separate product. Our product is used to fill in tax forms and the second product will fill in other tax forms.
We want to end up with two exe's (two install MSIs) which will be sold/installed/updated independently and could both be run at the same time on the same computer. Most of the code is in common between the two apps.
I am trying to figure out the best way to structure the solution to create the desired outcome.
1) Option one could be to create a new EXE project and several new DLL projects in the same original solution (Say in a solution folder) which have unique names,versions, guids, etc. with most of the code files as links back to the code files in the original similar DLLS. This allows us to have two completly separate systems with unique names for all the files, version numbers, etc., but allow any customization to be made to each project/dll. Is this a good idea or overkill?
2) Option two would be to create a new exe project in the solution and link to the same dlls as the first exe project. This seems simple enough, but i do not know if it is a good idea to have two projects which use the same DLLs. I do not really want to use the GAC. If we have two exe's which use the same Dll's ( even though they will be in separate application folders) with there be a problem if the DLLS have the same/different version numbers, name or GUID?
What are your ideas?
How should i restructure the solution to accommodate the new product?
Go for Option 2
There is no problem with the same Dlls with the same names. If you deploy the exes to separate folders or keep them in separate folders it will work either way.
I would even go further and look how you can break the application up further into more assemblies/dlls as it will give you even more flexibility. I would also have a single File for AssemblyInfo, and Add it as a linked file to all your projects. This means you have have a single version across all your dlls/exes.
http://vsh.infozerk.net/options/add-an-existing-file-to-a-project-without-copying-it/
I have a few merge modules (MSM files) from a third party. Unfortunately, I think the drones who made the MSMs just clicked through InstallShield and didn't make a nice, compact MSM. I opened the MSMs and deleted some InstallShield custom actions that were absolutely not needed - they popped up a console window and severely bloated my setup.
These InstallShield custom action binaries were stored in the Binary table. I deleted these entries using Orca and saved the MSM. As a result, my compiled MSI file decreased by a significant amount. (I use WiX to compile).
Unfortunately, the MSM files did not decrease in size after deleting the Binary table rows in Orca. I tried using "Save As" and saving to an MSM file, but the result was only 36 KB - it eliminated the actual files needed by the MSM, too! Examining the before and after MSM files in 7-Zip (to view the internal OLE structured storage that MSI uses) shows that the offending data streams were indeed deleted - but the overall file did not shrink.
I suspect I need to somehow compact the MSM file to reclaim space needed by deleted custom actions. How do I do this?
(Why am I asking? Would like to get this taken care of before committing anything to distributed source control system.)
Editing merge module files is not simple, especially since they contain a CAB archive with their files. I don't think Orca is enough.
The easiest and safest approach is to use a setup authoring tool to import them, modify their settings and content and then generate new MSM files.
Regarding the custom actions, please note that setup authoring tools (including InstallShield) rarely add custom actions automatically. So my bet is that those custom actions were added with a purpose.
Make sure that you really don't need them before removing their information.
As I create more applications, my /code/shared/* increases.
this creates a problem: zipping and sending a project is no longer trivial. it looks like my options are:
in Xcode set shared files to use absolute path. Then every time I zip and send, I must also zip and send /code/shared/* and give instructions, and hope the recipient doesn't have anything already at that location.
this is really not practical; it makes the zip file too big
maintain a separate copy of my library files for each project
this is not really acceptable as a modification/improvements would have to be implemented everywhere separately. this makes maintenance unreasonably cumbersome.
some utility to go through every file in the Xcode project, figure out the lowest common folder, and create a zipped file structure that only contains the necessary files, but in their correct relative folder locations, so that the code will still build
(3) is what I'm looking for, but I have a feeling it doesn't as yet exist.
Anyone?
You should rethink your current process. The workflow you're describing in (3) is not normal. This all sounds very complicated and all basically handled with relative ease if you were using source control. (3) just doesn't exist and likely never will.
A properly configured SCM will allow you to manage multiple versions of multiple libraries (packages) and allow you to share projects (in branches) without ever requiring zipping up anything.