Skip to main content

Jenkins, InstallShield and MSBuild configuration

My team and I have been using Jenkins as our continuos integration tool in our current project. The project is a .NET project with multiple components. One of these components is a Windows Service project. We wanted to enhance our build capability to include a Windows Service Installer so that this service can easily be distributed for installation purposes.

Our IDE was Visual Studio 2012 which out of the box integrates InstallShield 2013 LE edition which we needed to install in our local environments as well as on our build server. Once InstallShield 2013 LE was installed, we were able to use their project template to create a new installer project. This is fairly easy to accomplish as there is a basic wizard that you can follow. There are however few areas that you need to pay close attention while set up the project. Here is a quick list of items we used during our set up


  1. Add Project Outputs - This is to ensure that project dll and dependency dll are included in your installer. 
  2. Add Files - this is to ensure that content files such as (*.properties) are included in the build. If you use the "Add Files" button that shows up as part of the wizard, you will quickly notice that it uses your local environments path which is static. You want this to be dynamic so that when its received by your other team members or is received by the build server you won't run into PATH NOT FOUND errors. There are two ways to ensure that external files are dynamically added. One option is to modify the .isproj file. This is manually and can be error prone as its a large XML based file. Option two is to use the graphical user interface to include Project Content Files. The second option assumes that these external files have build action set to "Content". To set build action on file, in VS you can right click on the file and click the "Properties". On the "Properties" window you will see Build Action, set its value to "Content". Once this is done for all files, go back to Visual Studio and the Installer project and click on " 2 Specify Application Data" -> "Files". This will bring up a graphic interface with divided screens where you will see "Source Computer's Folders", "Source Computer's Files", "Destination Computer's Folders" and "Destination Computer's Files". Click on the project where your external files reside in the "Source Computer's Folder" section. This will update the "Source Computer's Files" section. There you will see an option called "Content Files for the Selected Folder/Project". You can drag and drop that into "Destination Computer's File" and save your project. This will ensure your files are now dynamically added to the Installer you are building. 
Once we ensured output dlls and external files were part of the built installer, we installed InstalShield 2013 in our build server Jenkins and checked in our changes. This obviously forced a new build. Our build failed with the following error:

[msbuild]   C:\Program Files (x86)\MSBuild\InstallShield\2013Limited\InstallShield.targets(21,3): error MSB4062: The "Microsoft.Build.Tasks.AssignProjectConfiguration" task could not be loaded from the assembly Microsoft.Build.Tasks.v3.5. Could not load file or assembly 'Microsoft.Build.Tasks.v3.5' or one of its dependencies. The system cannot find the file specified. Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.

I conducted a quick research and came across few posts on the net that talked about this problem. This http://w3facility.org/question/building-installshield-le-project-with-msbuild-error-msb4062/ link had few promising ideas about how to resolve this problem. I followed the suggestions in the link and copied the missing Tasks.v3.5.dll to the suggested location but ended up with the following error:

 [msbuild]   C:\Program Files (x86)\MSBuild\InstallShield\2013Limited\InstallShield.targets(108,3): error MSB4062: The "InstallShield.Tasks.InstallShield" task could not be loaded from the assembly C:\Program Files (x86)\MSBuild\InstallShield\2013Limited\InstallShield.Tasks.dll. Could not load file or assembly 'file:///C:\Program Files (x86)\MSBuild\InstallShield\2013Limited\InstallShield.Tasks.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format. Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask. 

In our project we were using a nant based build script that was internally using MSBuild tasks. Therefore, I decided to eliminate the usage of nant and decided to directly use MSBuild with Jenkins. Our Jenkins was already configured to use the 32bit version of MSBuild. I removed nant build steps from our project configuration and added a new MSBuild step. This failed with Jenkins not knowing where MSBuild executable was which I thought was interesting because Jenkins configuration did have a path to MSBuild executable. I went ahead and modified the PATH variable on the server to include the MSBuild executable. This finally did the trick for us. We still had the Tasks.v3.5.ddl in the suggested location. Hope this helps. 

Comments