WiX bootstrapper UI not compiling from TFS build definition - tfs

I have a WiX bundle installer in my solution. It consists of several MSI projects and the bootstrapper UI project. When built all at once everything works fine.
With a new requirement to authenticode sign everything, I am trying to split the assembly compilation from the installer compilation, so I can sign in between.
I am trying to do this with two separate build configurations. One that builds only the application assemblies, and another that builds only the installer projects. They both are working properly when I run them by hand from visual studio.
The problem is when I try to call them from separate tasks in a TFS build definition. The assemblies, including the bootstrapper UI, all compile successfully in the first task. But in the second installer only task, the WiX project will try to recompile the referenced bootstrapper UI project and fail with missing type or namespace errors.
I've tried including and removing the boostrapper UI project from the installer only build configuration. I get the same errors in either case. It's the wixproj itself that is kicking off the underlying bootstrapper UI build.

Ok, I think this is what you're trying to do, please correct me in the comments and I can refine the answer accordingly.
It sounds like you have a single solution that when built in one Configuration (say, CODE) it will only compile the .net projects and in another configuration (say, PACKAGE), it builds only the WIX projects. I think this separation is part of the problem.
From your description it also sounds like the wix projects have project references to the other code projects (for payload harvesting most likely - but at the very least, establishing build dependency order).
Any project (wix or code) that references another project will automatically cause that project to build - in the absence of solution configuration it will default to using the same configuration as the primary project. This means that if project A has a configuration called CODE and project B references with a configuration called PACKAGE references it, then building project B will cause A to try to build with configuration PACKAGE - if it doesn't have this configuration then it (successfully) won't build and project A will then fail to find the dependencies it expects.
In your solution, you should have two configurations, one of which is a superset of the other. So your CODE configuration for building only code is a subset of the PACKAGE configuration for building your wix projects. When you set this up in configuration manager and build the solution then you guarantee that the projects build with the correct configuration instead of inferring a configuration from the primary.
Then instead of two build steps in your TFS build you can do it as one. If you still need to split it (because you digitally sign the assemblies in between), then know that msbuild does incremental builds by comparing timestamps of inputs to outputs. This means that if you build project A then digitally sign it, building project B (that references A) will attempt to build project A but it will determine that the output of A is newer than the input and not replace the assembly. Ultimately this means it's safe for you to build your solution under configuration CODE, sign the assemblies then build the solution again under configuration PACKAGE (which is a superset of CODE) without the signed assemblies being replaced.
On a related note, the wix targets file has hook points to sign the bundle as part of the wix project build. That may be better than trying to use PowerShell to sign it after the fact.

Related

Using TFS to output build definitions bin folder on CI build

I just started using TFS not to long ago and I ran into a slight issue. I have a class library project called EplanInterface.Addin. This class library project is used as a way to load functionality into a 3rd party program through their API. All of this is working fine but the issue comes into play here:
The Issue:
So the problem I am running into is that this Addin library is not referenced by any other projects but still needs to be output to my Drop folder within my TFS build. Typically to load the Addin into the 3rd party program I would copy the debug/release folder to the server and select/load the dll accordingly. My TFS build does not seem to grab the anything from the Addin though?
App.Config
Along with that I am using SlowCheetah to try and transform my app.config file resources correctly. Whatever solution provided I need to also figure out how to select a transform when doing the build configuration and output the dlls with the correct build configuration config file.
Build Definition
My build definition is the basic asp.net template they provide which works great for my web api and MVC projects. I guess I am unsure how to force it to also build the addin / output the dll files for my addin to reference?
Other Info:
TFS Version: 16.122.27102.1
Addin Project .Net Framework 4.5.2
Slow Cheetah Version: 3.2.26
You can simply add another build task to your pipeline to build the specific addin project and then have it output to the artifacts directory (as the default "Build Solution" task should already be doing).
The other option is to edit the solution file in Visual Studio and include the addin as a project dependency. You may still need to manage the binary output though.

Linked file in WCF RIA service does not build in TFS Build server

I've just setup a TFS (2012) server and now I'm trying to build the complete code (written in .NET 4.0 in VS 2010) via the TFS Build server. But in my solutions I have also a WCF RIA project which contains linked files because they are used somewhere else also and there is no possibility to add a reference to a general .NET binary in WCF/Silverlight.
Everything builds without any problem on my development machine but when I check it all in, create a standard build definition and run that build definition I get the following problem. The linked files have usings (UsingNamespace for example) to other projects that are also build by us and build before the WCF/Silverlight but the following error pops up while building through TFS Build server:
The type or namespace 'UsingNamespace' could not be found (are you
missing a using directive or an assembly reference?)'
Is there any solution for this problem that I looked over?
EDIT 1
Just tried to set the Copy to Output Directory propertie of the linked files to Copy Always but this still gives me the same error as I was expecting. The problem is that the linked file is placed somewhere that it can use the usings but the WCF RIA service cannot access/find that using.
EDIT 2
Just tried out my local test TFS where I can do what I want and there I made a build definition with just the solutions needed to make that the project with the linked files builds. This worked without any problem. Then I tried the same on our TFS server with a new build definition that has the same solutions as on my test TFS and here it did not work. The only difference that I know for sure is that my test TFS is TFS 2012 Update 1 and that my production TFS does not have the update 1 yet. I'll try to install it next week.
EDIT 3
I've just updated our production TFS to Update 1 but it is still not working with my temporary build definition which only contains the projects that are needed to build the silverlight application with the linked files. The 2 workspaces are the same on both server and the projects to build are also the same.
You need to specify the workspace information in the Build Definition for the build to use. The workspaces are what the build process copies from source control to the build server. If you don't have everything in the build server's workspace, it can't build properly.
The Source Control Folder in the workspace tab is the location of the files you need from TFS. The Build Agent Folder is a relative path from the build server's pre-defined base location. You'll usually use $(SourceDir)\Folder to specify the "Folder" that your build process needs.
This sounds like an $(Outdir) problem. A build definition in TFS automatically overrides the Bin folder. All Binaries are redirected to the bin folder upon compile. Sounds to me that you are using a mixture of project references and file references. The file references are probably what is causing your build failures.
Example if you compile in the same build the following solutions
Solution1.sln (TFS Build Pass)
project1.csproj
project2.csproj (references project 1)
Solution2.sln (TFS Build Failure)
project3.csproj (references binary output of project 1)
Expectations from TFS out of the box without customizing your workflow is that this simple build will fail. The reason is that in your development box all projects produce output to one destination while in a tfs build your projects will build to $(Outdir).
Some Things to try
Simple (best practice in my view)
Create 1 solution and use project references instead of file references.
Complex
Build using MSBuild project files
Modify your windows workflow to not override the $(Outdir)
Copy the binaries after a build is complete.
Best practice on Automating Builds
Build from command line
Build from cmd a NON vs2010 command line.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe FullpathtoSolutionFile.sln
Cheers!
Apparently there was just missing the WCF RIA services V1.0 SP2 on the TFS server. If that was installed the problem was solved.

How do I copy dll files for a build using team build

I have a bunch of external dlls I use in multiple projects. These dlls are referenced by these projects and everything compiles fine.
Now I am trying to get a Team Foundation Server build going for my projects. When I run the build, it complains that it can't find the needed files. How do I get TFS to find the needed files?
I was thinking I could use the copydirectory windows workflow function in a custom build template but I'm not sure if this is the right way to do things. Also, if I do use copydirectory, how do I reference directories that reside on TFS rather than on the file system? And where do I copy the files to?
Try this:(if using 2010)
At the Workspaces tab you can map the folder that has all the DLLs you want, just make sure you reference the assemblies in your project appropriately.
For instance, if your project is referring to the assemblies one level UP, before the project root folder, you may set the workspace like below:
$\Team Project\src -> $(BuildDirectory)\src
$\Team Project\dlls -> $(BuildDirectory)
Something like that should solve your issue.
There's also a way to do it in VS2010 build: You should add a copy command to the prebuild step for the project (select the project -> Properties -> Build Events).
If you want to use the windows workflow - template method, refer to this guide: http://blogs.msdn.com/b/buckh/archive/2010/01/21/deep-dive-on-windows-workflow-4-0-activities.aspx

TFSBuild 2010 Package only contains sources - not binaries

The packages created by a TFS 2010 Build only contain our Sources, not the binaries. When this is (automatically) deployed to IIS, the site does not run because it is missing DLLs that are created during the build process.
We have a Web Project created in VS2010. If I select "Build Deployment Package" from a right click in VS we get a zip file in the obj\Release\Package folder that contains the fully build site.
However, if ask our TFS build process to create the package by adding "/p:CreatePackageOnPublish=true /p:DeployOnBuild=true" to the MSBuild arguments (as advised in amongst other places here) we get an zip file in _PublishedWebsites\_Package\.zip that only contains the sources.
My best guess is that the CopyAllFilesToSingleFolderForPackage is picking up the files from the wrong place.
I notice a similar issue asked here - TFS 2010 and creating a package - although his workaround in not appropriate in many cases, I'd guess.
My concern is that this is using a built-in, but poorly documented feature of MSBuild/TFS so when it doesn't work you're a little in the wilderness.
It seems that deployOnBuild runs some "package"-like target on each of the projects. If you have built the projects into a separate directory (which the default TFS 2010 build does by default) the packaging won't pick up the compiled files.
One solution is to get rid of the custom output folder for the MSBuild Command within the TFS build workflow. This will cause the compiled files to be located in-situ and be included in the package.
Now the rest of the TFS workflow is require some changes because it'll be expecting to transfer the files from the output directory, and they won't be there.

Team build: Use same external targets for multiple build definitions

I want to use the same targets defined in an external file in multiple build definitions. This external target file should be stored on the source control.
The bootstrap phase explained in TFSBuild.proj and Importing External Targets does not seem to allow downloading the same file for multiple build definition as the build file is always named TFSBuild.proj and consequently sits in a separate folder for each build definition.
The question was somewhat aked in a comment of the previouly mentionned thread but it seems motre appropriate to create a new thread.
Quoting that comment by David Keaveny:
Is it possible to get TFS to download
from other folder paths during
bootstrap? I have a Common.targets
file that contains all the custom
tasks that my TFSBuild.proj should be
executing, but given that I several
build definitions (one folder per
definition), it sits in a separate
folder at the same level as the build
definitions. Without it, of course,
the builds fail immediately. – David
Keaveny Aug 17 '10 at 23:58
I'm not sure if there is an easy way to do this. You could have a master copy of the targets file, and branch that in to each of your build definition folders. When you update the targets file you'd need to remember to merge it to all of the folders. You could probably write a script that automates the merging, the script should be able to work out what the branching relationships are using tf branches and then iterate around them and call tf merge then tf checkin. This feels like a lot of work though.
You could just install the target on your build server(s). We have a number of custom targets that we use and we manage them as if they were a product, they have their own area for source control and are versioned independently of the software they are used to build. We package them using wix and once they have been tested they are installed on all of the build machines. This seems to work for us and it means we can control the rollout of new targets files, and the targets install is just part of a build server basline build.
I'd be very interested if someone has an easier way of managing this though.

Resources