TFS custom build process activity assemblies per branch - tfs

What do I do if I want one TFS 2012 build controller to have access to two versions of the same custom build process assembly (one for each of my branches)?
I have one build process template per branch, and one build definition per branch. Each branch has it's own custom build process assembly, but they all have the same assembly name and namespace (e.g. Company.Build.Activities.dll). (I realize I could make all of this go away by having different names for each branch's assembly, e.g. Company.Build.Activities.Dev.dll and Company.Build.Activities.Com.dll)
My build controller points to one location for "Version control path to custom assemblies" ($/Build/ForTFS). I tried putting the two assemblies under different subfolders, but the build process causes an error:
TF215097: An error occurred while initializing a build for build definition \Company\Dev_BuildDef:
Exception Message: Cannot set unknown member 'Company.Build.Activities.LastActivity.CustomFolderPath'. (type XamlObjectWriterException)
It seems that it's using the wrong copy of the assembly (CustomFolderPath is only defined in one assembly, not the other).
I think I could resolve this if I could specify the path or required assembly version in the template xaml, but I am not sure I can do that. I have read posts that suggest that you can add a reference to the specific assembly version in the Visual Studio project you are using to edit the template. But that didn't seem to work for me, and how would the build process definition know about that project's references... it only points to the template file itself, not the project.
Any suggestions? Am I approaching this wrong?

You cant have different assemblies loaded between different branches. You would need to run different controllers and use separate folders.

Related

Adding references search folder for MSBuild from Visual Studio Build definition UI

I am working on configuring a XAML build definition for a .net solution (of another company) stored in TFS2015.
The solution uses Dll references from a software X, installed on the developers computers, but not present in the Build server. (FTS and Build servers are shared among many clients).
I have option to add the required Dlls in a folder along with the source code, but I do not have option to modify the .csproj files.
In the Build definition, I tried to add the following in the MSBuild arguments field :
/p:AdditionalLibPaths=$/[long tfs path here]/CommonDlls
/p:AdditionalLibPaths=$(SourceDir)/CommonDlls
but it is not working.
Ideally, I would like to specify a relative folder from the root of the source code.
(a static path might work but only for one build server and agent, which is not the objective of shared build).
Any ideas on how I can define this parameter ?
There is also option to add a prebuild script path. I can store a script file along with source code. Any pointers for how to write such script file ?
You do not really need a script.
There are two things to make this work.
The first step is making sure that the DLLs are downloaded to the Agent working folder, the simplest way is have the $/[long tfs path here]/CommonDlls mapped in the Build Workspace; this is specified in the Source Settings tab of the Build Definition. Be careful to use the $(SourceDir) token in the mapping (see here).
The second point is to use a proper reference to the downloaded folder: use the TF_BUILD_SOURCESDIRECTORY variable (see here for full list).
So, if you added a mapping like
$/[long tfs path here]/CommonDlls -> $(SourceDir)\CommonDlls
use $(TF_BUILD_SOURCESDIRECTORY)\CommonDlls.
It took me almost 20 trials to get the right one, it all started with how long it took that warning to consider all other directories, I could've ignored it but here's the warning first
C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): Warning MSB3245: Could not resolve this reference. Could not locate the assembly "nameOfDllFile". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
and this is the argument that got it working
/p:ReferencePath="$(build.sourcesdirectory)\Binaries"
where Binaries is the equivalent to CommonDlls from the question, and it is all because of the vague documentation and differences between versions of MSBuild, mine is 14.0 (VS2015).

"Access to the path is denied" to my custom activities assembly in temp when loading build definition Process parameters

Steps:
Open build definition "test1" which points to build controller "controller1" on "builder1" machine, then click "Process" tab
Open build definition "test2" which points to build controller "controller2" on "builder2" machine, then click "Process" tab
Error is: Team Foundation Error Access to the path {path}is denied:
Noteworthy: I also get errors in output window, for example:
Summary: There were 0 failures, 6 errors and 0 warnings loading custom activities and services.
Error: Could not load file or assembly 'Microsoft.TeamFoundation.VersionControl.Client, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Error: API restriction: The assembly 'file:///C:\Users\{!REDACTED!}\AppData\Local\Temp\VSTFSBuild\df2044d9-c8bb-4666-9c93-513e149cd3e0\Microsoft.TeamFoundation.Build.Client.dll' has already loaded from a different location. It cannot be loaded from a new location within the same appdomain.
I have not proven the two errors are associated (I also get similar API restriction errors ANY time I load process parameters), however they could be.
The reason I have this two-controller setup is because controller1 uses a path to my custom activities ie $/Process/Dev and controller2 uses path $/Process/Production. It helps me test my changes in isolation.
So the question is: Is there something I am missing with regards to Microsoft's support for using more than one build controller (on separate machines) pointing to the same TFS instance?
Or, I'm open to different ideas on how to test my changes to my custom activities without forcing all of my builds to point to the changes.
I would suggest that your BuildTasks.dll is different in both locations. i would either update the dll to the latest version in whatever location is wrong or point both controllers to the same dll, you could also ensure that the dll has different version numbers if you want to maintain different source locations. Multiple controllers are supported and work well normally.
As a short term fix, clear cache between opening different build definitions so the 2 different dll's don't clash with each other
The reason I have this two-controller setup is because controller1
uses a path to my custom activities ie $/Process/Dev and controller2
uses path $/Process/Production. It helps me test my changes in
isolation.
it's not clear which machine your opening the Build Definitions on but I'll assume it's your development machine, I always place my buildtasks.dll in the public folder of Visual Studio when I'm developing.

Team Foundation Build Property for Build Folder

Using TFS 2010 I need to build a solution that depends on a couple of other solutions held in different team projects. I'm editing my build definition and I create a list of "Projects to Build'. When it comes to build the parent solution I get an error because it's unable to reference assemblies created by the other solutions. So I go back to edit build definition and add /p:ReferencePath="c:\builds\3\referencedproject\binaries\" to the "MSBuild Arguments" Build process parameters.
Problem is, I don't want to hard code the c:\build\3. I guess there may be a $() property I can use in its place - can anyone please advise?
The other problem I have is that the 'Main' project and the two other projects that it references live at the same level in the source code. As far as I can tell, I have to set the source control folder to be the level above this - which happens to be the root. This means that TFS Build does a get of all the projects on the root - which includes dozens of projects that are not required for my build. It's not a critical issue since it makes no attempt to compile these non-related projects but it does increase the time for the build cycle to complete. Is this only way to avoid this to "group" the projects that are required for my build into a different TFS source folder?
For the references issue there are a few options. The most common one taking an explicit dependency on a specific version by checking in the binary to TFS.
For example, if you have Team Project A that has a dependency on Team Project B, I would assume they are setup as separate projects because they evolve differently, probably have different teams working on them, and have different release cycles. The common approach to managing this dependency is to checkin B.dll into Team Project A (usually in a lib folder specifically for this purpose), then use a file reference from within Project A's solution/projects to the dll in the lib folder.
This approach lets the Project A team explicitly choose which version of B.dll they wish to depend on, and make an explicit decision to adopt newer versions of B.dll on their own timetable.
For the other question of how to have a build definition download only select source code paths, you can specify multiple lines in the Workspace mapping screen when setting up a build definition. For example you could have the following:
$\ProjectA -> $(SourceDir)\ProjectA
$\ProjectB -> $(SourceDir)\ProjectB
This would download Project A + B but not C.
I'll start with problem 2 as this should be easiest to solve.
You have 2 options both involve changing the workspace mapping of your Build Definition.
You don't have to map at the folder "above", you can map individual folders so if your source looks like this.
$/TP/SolutionA
$/TP/Folder1/SolutionB
$/TP/Folder1/SolutionC
$/TP/Folder2/SolutionD
and you only want to include SolutionA and SolutionC in your build, you could set the workspace up as follows.
This will get just the code you need and preserve the relative paths between them.
Another option is to use cloaking, you map the "Root" folder and then cloak any folders you want the build to ignore.
Both of these methods will restrict the amount of source being downloaded when the build runs, and also prevent "continuous" builds from starting when checkins occur in the folders that haven't been mapped / Cloaked.
Problem number 1.
As Dylan suggests, probably the best thing to do is to use Binary References between solutions. Especially solutions in seperate team projects.
Check out my answer to this question for a full description.

TFS Build hiding custom assemblies in build

I have my custom continous build that log an error for my tfs service host.
Service 'Default Agent - basv-tfs-001' had an exception: Exception
Message: Problem with loading custom assemblies: API restriction: The
assembly
'file:///C:\Windows\ServiceProfiles\NetworkService\AppData\Local\ProjectBranchDevelopment\BuildAgent\2\ReportViewer.ProcessingObjectModel\Microsoft.ReportViewer.ProcessingObjectModel.dll'
has already loaded from a different location. It cannot be loaded from
a new location within the same appdomain. (type Exception)
I have found i have the same dll saved in 2 locations in my repository.
can i hide it from build?
Edit the workspace in your build definition. Add a reference to the folder containing one of the dll's and change "active" to "cloaked" that will stop TFS getting that folder during the build
I've seen this in tests where it's defaulted to using **test.dll (or similar), to get round this I changed it to just test.dll, since it was (as the error suggests) finding it in multiple locations.
So whatever is attempting to resolve your DLL is probably doing something similar. Not a solution I know by may help you track down the offending code :)

TFSBuildServiceHost start error referencing Elmah SQLite.dll

Installed the TFS 2010 build service and when trying to start the tfsbuildservicehost I get the following errror (this is on a Windows Server 2008, patched and updated, and we are not using SQLite). This is happening twice for the build controller, the build agent and the build service.
TFSBuildServiceHost
Service 'MVC Build Agent' had an
exception: Exception Message: Problem
with loading custom assemblies: API
restriction: The assembly
'file:///C:\Users\Administrator\AppData\Local\Temp\BuildAgent\1\Utilities\Elmah\lib\x64\System.Data.SQLite.DLL'
has already loaded from a different
location. It cannot be loaded from a
new location within the same
appdomain. (type Exception)
I have had similar problem:)
Go to your controller definition in tfs and in build controller properties and set version control path to custom assemblies and add there location to your
"Elmah\lib\x64\System.Data.SQLite.DLL" from your tfs project.
in format of :
$/Elmah/lib
this should solve your problem
I don't know what the 'MVC Build Agent' is, but it's not a component of Team Foundation Server. Sounds like you have a custom assembly that's failing to load. Check the build controller properties to see where it's looking for its custom assemblies. You'll need to either (a) check-in the dependencies required by this custom assembly, or (b) change/remove the custom assembly path for the build controller so it no longer tries to load it.

Resources