Unable to create workspace due to a mapping conflict


It’s a small issue, you may encounter if you name your build definition with the same name as an old one.

Here is the error
Exception Message: Unable to create the workspace ’80_6_tfs2bld’ due to a mapping conflict. You may need to manually delete an old workspace. You can get a list of workspaces on a computer with the command ‘tf workspaces /computer:%COMPUTERNAME%’.  Details: The path C:\Builds\6\Windows\src is already mapped in workspace 77_6_tfs2bld. (type MappingConflictException) Exception Stack Trace: at Microsoft.TeamFoundation.Build.Workflow.Activities.TfCreateWorkspace.Execute(CodeActivityContext at System.Activities.CodeActivity`1.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
   at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager,

Unable to create the workspace due to a mapping conflict

You will need to go to the build machine, search for the old workspace that use the same build definition name, delete that one so the build can create new worksapce with the same name again.
Delete workspaace

Create One Main Build Process to Invoke Other Builds


The main question was….. How to start a build when another build succeeds in TFS, in other word.. how to invoke a TFS Build from another TFS Build?

I don’t need to use any third-party library to do so, all I had to do is to edit the default Lab Management process temple which is already did that (invoke a build from other build).

I copy the build process and remove most of the activities, variables and arguments and do some modifications, the following is an image of all the process and I will explain what happen in each section:
Master Build run other builds all the process

Here is the Build definition that use the process, it’s only has 4 arguments, we can see that build definitions arguments is a list of string so we can point to many build as needed, also we have option to run build in sequence if builds depend on each other or disable that in case no dependencies.
Master Build run other builds-build definition

In the following section, I just added a loop (For Each) that iterate over the list of given builds and invoke each one, note here that I check if we want run the build in sequence, see the next step.
Run other workflow TFSBuild for each build definitions

If we want to run the build in a sequence (the condition is true) to make each build depends on the previous build status and if one build fail then the main build will stop and fail.
To do so, I wait for the build untill finished and change the main build status (success or fail) and if it  fail then the main build stop and fail (ThrowOnError), if it success, it go to the next iteration in the loop (wait for the next build).
Run build in sequence wait for build and set build status

If we don’t want to run the build in sequence (condition is false) we just need to trigger all builds with no dependencies, that’s means the main build always success even other child builds fail because it’s not depends on them, even the main build may finish while other build still running, I made the main build wait for the last triggered build in the loop but if last build finished before the previous one, the main build will finished before all build finished, I also changed (ThrowOnError) to be false so the main build will not fail if the last build fail.
Wait for the last build and success the build whenever

Downlaod process template

Backup and Restore (Rollback) DB and Web Application during TFS Build


One of our TFS assignments needed to extend the current build and deployment process which includes (Creating and and Deploying Web package, Deploying Database, Versioning Assembly, Run Post Integration test after deployment, etc.) to include rollback which will perform backup and restore.

We agreed on performing the backup during the deployment and the restore will be a separate build definition.

For the backup during the deployment, I added the following section that backup the DB and the Web App.Backup DB and Web Squence

Command Text
———————–
“-verb:sync -source:iisapp='” + IISApplicationPath + “‘,computerName=” + ServerIP + “,userName=” + IISUserName + “,password=” + IISPassword + “, -dest:package='” + BuildDetail.BuildDefinition.Name + “_Backup.zip’,encryptPassword=password123”

The build definition for that part will be as the following:
Backup DB and Web Squence-parameters

For the rollback and restore, I added the following section that restore the backup for both DB and Web, for the DB I had to get exclusive access so I can restore the DB even there is active connection from other clients.

Restore DB and Web Squence

Command Text
———————–
“cmd.exe /k Sqlcmd -Q “”use master alter database “ + DBNameForBackup + ” set single_user with rollback immediate RESTORE DATABASE “ + DBNameForBackup + ” FROM DISK='” + DBNameForBackup + “_Bakup.bak’ WITH REPLACE alter database “ + DBNameForBackup + ” set multi_user”” -S “ + DBServerOrIP

Command Text
———————–
“-verb:sync -source:package=””C:\Windows\SysWOW64\” + BuildDefinitionDeploymentName + “_Backup.zip”” -dest:iisapp='” + IISApplicationPath + “‘,computerName=” + ServerIP + “,userName=” + IISUserName + “,password=” + IISPassword + “, -setParam:kind=ProviderPath,scope=iisApp,value='” + IISApplicationPath + “‘”

The build definition for that part will be as the following:
Restore DB and Web Squence-parameters

Some good commands that I end up with:

PowerShell
==========

sqlps (PowerShell for SQL)

PS SQLSERVER:\> Backup-SqlDatabase -ServerInstance .\ -Database database1 -BackupAction Database

PS SQLSERVER:\> Backup-SqlDatabase -ServerInstance 10.43.94.222 -Database database1 -BackupAction Database

PS SQLSERVER:\> Invoke-Sqlcmd -Query “BACKUP DATABASE DATABASE1 TO DISK=’BackupsMyDB.bak'” -ServerInstance 10.43.94.222 -U YourUserName -P YourPassword

PS SQLSERVER:\> Invoke-Sqlcmd -Query “RESTORE DATABASE DATABASE1 FROM DISK=’BackupsMyDB.bak’ WITH REPLACE” -ServerInstance 10.43.94.222 -U YourUserName -P YourPassword

PS SQLSERVER:\> Invoke-Sqlcmd -Query “use master alter database database1 set single_user with rollback immediate alter database database1 set multi_user” -ServerInstance 10.43.94.222 -U YourUserName -P YourPassword

PS SQLSERVER:\> Invoke-Sqlcmd -Query “use master alter database database1 set single_user with rollback immediate RESTORE DATABASE DATABASE1 FROM DISK=’BackupsMyDB.bak’ WITH REPLACE alter database database1 set multi_user” -ServerInstance 10.43.94.222 -U YourUserName -P YourPassword

sqlcmd
=======

sqlcmd -U YourUserName -P YourPassword -S 10.43.94.222

Sqlcmd -Q “BACKUP DATABASE DATABASE1 TO DISK=’BackupsMyDB.bak'” -S 10.43.94.222 -U YourUserName -P YourPassword

Sqlcmd -Q “use master alter database database1 set single_user with rollback immediate RESTORE DATABASE DATABASE1 FROM DISK=’BackupsMyDB.bak’ WITH REPLACE alter database database1 set multi_user” -S 10.43.94.222 -U YourUserName -P YourPassword

Delete DB Backup T-SQL
=========================

EXECUTE master.dbo.xp_delete_file 0,N’G:\Microsoft SQL Server\MSSQL11.BGAPIDB01Q\MSSQL\Backup\’,N’BAK’

Invoke Process by call .bat file
===========================

BuildDirectory + “\src\Scripts\BackDB_Test.bat”

Invoke Process by cmd.exe and arguments
=======================================

File:   “cmd.exe”
Arguemnts:  “cmd.exe /k Sqlcmd -Q “”BACKUP DATABASE DATABASE1 TO DISK=’BackupsMyDB.bak'”” -S 10.43.94.189 -U YourUserName-P YourPassword”

===================================================================================================================================================================================

Web
=====

msdeploy -verb:sync -source:iisapp=’Default web site/Lara’,computerName=Localhost -dest:package=’defaultWebsiteBackup.zip’,encryptPassword=password123

msdeploy -verb:sync -source:iisapp=’Default web site/Lara’,computerName=172.18.0.333,userName=YourUserName,password=YourPassword, -dest:package=’defaultWebsiteBackup.zip’,encryptPassword=password123
msdeploy -verb:sync -source:package=”C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\defaultWebsiteBackup.zip” -dest:auto -setParam:kind=ProviderPath,scope=iisApp,value=’Default web site/Lara’

msdeploy -verb:sync -source:package=”C:\Windows\SysWOW64\defaultWebsiteBackup.zip” -dest:iisapp=’Default web site/Lara’,computerName=172.18.0.333,userName=YourUserName,password=YourPassword, -setParam:kind=ProviderPath,scope=iisApp,value=’Default web site/Lara’

Install Missed Web Deployment Agent Service


When you install Web Deployment 3.5, you may missed to select the Web Deployment Agent Service, so If you couldn’t find it in the Windows service as the following.
Web Deployment Agent Service

You will need to install it by going to the Add and Remove programs and select Web Deployment, click on change and install Remote Agent Service.
Microsoft Web Deploy change
Select Remote Agent Service

TFS Counter Command Line Tool


I created a a coomand line tool that provide a CSV file that count all items for all projects in TFS collection, like Count of ChangeSets, Count of Changes, Count of Files, Count of WorkItems and Count of History of WorkItems

This tool might help you to estimate the size of the project in order to migrate or move the project between servers or collections.

Download the tool from Visual Studio Gallery

TFSCounter
The output of the CSV file will be like the following:TFSCountOutput

Estimating the time for migrating projects to VSO (Visual Studio Online)


I wrote in a previous post about how to migrate projects to VSO with different tools, but the most important question was what is the estimated time for each project???

This was really a hard question to answer, at the end I created a command line tool that help in estimating the size of the project so we can estimate the time needed for  migrating each project.

Here is the size for some projects and the actual time needed for migrating each one.
TFSCount Report

Changing the connection string during the TFS build for the Publish Profile of the SSDT (Sql Server Data Tool)


One of our customers needed to change that, they need to type the password for the SQL login inside the publish profile but of course they couldn’t do that in terms of security reasons, so we created that during the TFS  build as the following:

  • Create a PowerShell script that replace the connection string
  • Check-In the script into source control
  • Execute the PowerShell script during the build and before compiling the code

Create a PowerShell script that replace the connection string

The idea is to create a PowerShell script to search for the publish profile in the build directory on the build machine then, replace connection string with the one with the password, remember that we need to do that before compiling the SSDT so during running the SSDT deployment, it will use the modified file.

During the build I will send $pathToSearch which will be the build directory,$publishProfileString which will be set as argument in the build definition and so $sqlUserName and $sqlPassword.

Param(
 [string]$pathToSearch,
 [string]$publishProfileString,
 [string]$sqlUserName,
 [string]$sqlPassword

)

try
{
 #$pathToSearch="C:\Radwan"
 #$publishProfileString = "/p:SqlPublishProfilePath=../DAI.Infrastructure.DataAccess.Ef.Db\PublishProfiles/DAI.Infrastructure.DataAccess.Ef.Db.preprod.publish.xml"
 #$sqlUserName="vvvvvvvv"
 #$sqlPassword="00000000"

 $publishPostion = $publishProfileString.LastIndexOf("publish.");
 $publishStringWihoutPublish = $publishProfileString.Substring(0, $publishPostion - 1);
 $lastDotPostion = $publishStringWihoutPublish.LastIndexOf(".");
 $publishProfileStageName = $publishStringWihoutPublish.Substring($lastDotPostion+1, $publishStringWihoutPublish.Length - $lastDotPostion-1); 

 $searchFilter = "*." + $publishProfileStageName + ".publish.*"
 $replaceValue="User ID=" + $sqlUserName +";password="+$sqlPassword+";"

 gci -Path $pathToSearch -Filter $searchFilter -Recurse | %{
 Write-Host " -> Changing $($_.FullName)"

 # remove the read-only bit on the file
 sp $_.FullName IsReadOnly $false

 # read the file content
 $results = Get-Content $_.PSPath
 Write-Host " -> File content: $($results)"

 # run the regex replace
 #(gc $_.FullName) | % { $_ -replace 'ID=user;', "User ID=""$sqlUserName"";password=""$sqlPassword"";" }| sc $_.FullName
 (gc $_.FullName) | % { $_ -replace 'User ID=user;', $replaceValue }| sc $_.FullName

 Write-Host "Done!"

 }
}
catch {
 Write-Host $_
 exit 1
}

Check-In the script into source control

So the script can be downloaded during the build as I will need to run it from the build machine

Execute the PowerShell script during the build and before compiling the code

SSDT change connection string