I recently worked with a client to create a fairly comprehensive solution for implementing Continuous Integration and Delivery for SQL Server Databases using Visual Studio 2010 Database Projects. I had the opportunity to give a talk on the project at SQL Saturday in Omaha. The presentation is here if you want the slides. I think there is some context missing with the slides alone so I wanted to do this post to further explain the solution. Before talking about the solution, let me describe three different continuous processes. Continuous Integration (CI) is most familiar and is often used to describe all three of these processes. I think the differences between these three processes is more clear by using these terms.  Figure 1 – Continuous Processes Continuous Integration – Verifying code quality by compiling and running unit tests on the build server when a developer checks in changes. Often abbreviated as CI. Continuous Delivery – Adds the deployment of the application and database to an isolated test environment where additional integrated and UI automated tests can be run. Continuous Deployment – Includes automated deployment of the application through each environment through production. In this post I will primary review our solution for CI and Continuous Delivery. This works lays the foundation for the deployment into Staging and Production but I will discuss this in a future post. Database Projects Database tools in the past have been different than the tools used application code development. These database tools have been difficult to implement change management practices and Application Lifecycle Management (ALM) practices. Today there is an increasingly amount of application developers managing database changes. These are some of the reasons that have led to need for a tool like Visual Studio Database Projects (DBPro for short). This tool is part of Visual Studio 2010 (Premium and higher). To create a Visual Studio Database Project, select SQL Server from the process template menu and then choose SQL Server 2008 Wizard or SQL Server 2008 Database Project.  Figure 2 – SQL Server Database Project Templates in Visual Studio 2010 The primary purpose of the Database Projects are to manage the the version control of database objects in SQL Server databases. The solution we established utilizes this and many of the features of DBPro including TFS Build Integration, Data Generation, Database Unit Testing, Static Code Analysis, and Database and Data Deployments. In this post I’m not going to cover how to use all of these features but focus on how to implement the features for Continuous Integration, Delivery and Deployment processes. For more information, please take a look at the Visual Studio ALM Rangers Visual Studio Database Guide. This solution is complimentary to the guide and goes into more more specifics for CI.  Figure 3 – Visual Studio Database Guide Challenges Visual Studio Database Projects are a great tool and I highly recommend teams utilize these for managing version control for the SQL Server Databases. However, successfully using Database Projects can be challenging. I believe the benefits greatly out weigh the challenges but it is important for the team to be aware of these for a successful implementation. Visual Studio – Visual Studio probably seems like an odd challenge considering this is the tool to use for the solution, however Visual Studio is a beast. Visual Studio has become everything development. Developers are used to Visual Studio and I have seen DBAs and other database professions get frustrated using it when they first start. Stay with it. It will get easier and is the future direction of Microsoft in SQL Server 2012. From what I have seen SQL Server Management Studio 2012 is based on Visual Studio. “Truth Center” Shift – Development teams have been used to using a shared database server and making changes directly on server since the stone age. Managing source control of the database in DBPro essentially changes the “truth center” of the database project to DBPro. Changes to the schema should be made in DBPro and then executed or deployed from DBPro to the shared server. Development can also be done in local sandbox called offline schema development where the developer can make the changes locally and check them in. Changes made directly to the shared SQL Server database risk being overwritten by the next deployment from DBPro. Permissions – I have found DBPro does a great job managing almost all of the artifacts for databases. The biggest challenge and frustration has been permissions. The problem is that the database project holds the specific version of the database. For permissions this doesn’t work in most real world examples because permissions change in each environment. For examples, developers need different permissions in development versus what they need in production. In addition, many enterprises use a separate domain for each environment. As shown in Figure 4 below, Database Roles for the most part are consistent between environments and primarily the users and their role membership in those roles will vary. The best method I found for handling these permission differences is to exclude them altogether. Use the following steps to handle permissions when importing the schema and adding new objects to the project. One advantage of removing the users is that that they are normally connected to a login and the login lives outside of the database in the Master database. Including the users and logins in the project requires an additional project called SQL Server Server Project that contains the Master database. This solution does not require a SQL Server Server Project.  Figure 4 – Managing Permissions Across Environments Importing Databases When using the importing the schema and objects into your project, make sure you perform the following steps to first import all of the permissions and the remove those that will change in different events. -
Enable Import permissions in the Import Wizard to import all of the permissions including Roles, Users, and Role Membership. -
After Import has completed: -
Role permissions are to be kept in the .sqlpermissions file. -
Schema Users (without login) are to be kept. -
The other users must be removed -
from sqlpermissions -
From Security\Users -
From RoleMemberships Adding New Objects When adding new objects in the Database Project <PermissionStatement Action="GRANT">
<Permission>EXECUTE</Permission>
<Grantee>TestRole</Grantee>
<Object Name="spTestFromSSMS2" Schema="dbo" Type="OBJECT" />
<Grantor>dbo</Grantor>
</PermissionStatement>
Permission Scripts
By removing the permissions from the project, there needs to be a place to account for these. This solution accomplishes this by creating a script in the Scripts folder for environment that essentially creates the logins, users, and assigns the role membership for each user. This allows the flexibility to store any variations between the environments and still store these in the database project and in source control. Do not set the Build Action to PostDeploy because you can only have one for each project and it will be combined with the Deployment script. Instead set the “Copy to Output Directory” property on the script to “Copy Always”. This will create an Scripts folder and the permission files in the build output directory so it can be called by the deployment scripts.
Source Control
The primary benefit for using the Database Projects is that all of the database changes can be managed in source control. There are a lot of ways to organize your source control and with branching and merging this can become complex to manage. I like to take a pragmatic approach to source control and keep things simple but allow for complexity if needed in the future. The Visual Studio TFS Branching Build 2010 is a great reference for adopting branching and merging strategy. For this post I want to simply show the relationships between Production, Development, and Work Orders. The main points is that the database projects should be branched and merged along side the application source control with some sort of release branch that has the current production version. The Work Order branch is for production support changes that will be made into production. Development teams should do downward merges often to always have any work order changes incorporated early. When the application and database changes are deployed to production, the development branch should be merged up to the Production branch. The diagrams below show how this is organized from a logic view and physical view.
Logical View

Figure 5 – Logical View of the Database Project Source Control Branches
Physical view

Figure 6 – Physical View of the Database Project Source Control Branches
Continuous Integration (CI)
To setup the most basic CI process for your Database projects, you can simply add the Solutions containing the database projects to your CI build that is building your application code. The benefit of this is that it will build your database projects and validate that there are no schema errors and can validate any static code analysis rules.
Continuous Delivery
For Continuous Delivery, we want to expand the process to include deploying the database, insert any test data we need, and then run the database unit tests. This adds validation that the schema in source control can correctly build the database and that stored procedures can pass any number of validations with the unit tests. These steps would look like the following:

Figure 7 – Simple Continuous Delivery Process
Visual Studio Database projects make implementing this process very simple and only requires a couple simple settings. The dialog below shows the out of the box settings. To open this dialog, select Test > Test Configuration from the menu. The sections are slightly out of order. To start we want to set the Deployment database project to the project we want to deploy. Next choose the configuration. The configuration settings in the database project will specify the target connection string and other deployment properties. Next, the Database state setting will generate the test data for the unit tests by running one of the data generation plans.

Figure 8 – Database Test Settings
Types of Continuous Delivery
The example above basically deploys the current version of the schema to the target but doesn’t is not a good practice run into production. It basically deploys the changes from the last deployment. My goal of the Continuous Delivery process should be a practice run into production and essentially deploy the application and database the way it will be done for the production deployment. There are two types of delivery based on whether or not the application is already in production. For new systems that haven’t been deployed to production, the deployment will be to deploy all of the schema. This is referred to as Greenfield. For existing systems, the schema will the difference of what is currently in production with what has been developed. This is referred to as Brownfield deployments.
From a Visual Studio Database Project standpoint, Greenfield deployments are a simple using the deploy option. This will drop the database and execute the full schema script to create the database.

Figure 9 – Greenfield Process
For Brownfield deployments in Visual Studio Database Projects, the process is accomplished in two steps using Production and Development versions of the database projects. The first step is to use the Production version of the Database Project to create the full CREATE script. Next, use the compare feature to compare the Production and Development versions to create the DELTA script. Again, the key is not to compare the development against the live production database but to use the version of the Database Project that was created either from the production database or from the Release branch in source control. Once you have these two database scripts, run the CREATE script to drop the database and create the database to the production level. Then execute DELTA script to bring it to the current development level. From there you can follow the similar steps to execute the data generation plan and automated tests to complete. See below to see how this fits together

Figure 10 – Brownfield Process
Putting this all together, here are the steps in order for a good SQL Server database Continuous Delivery process. There is some customization that has to be done for this. The database testing options that were available for the simple process, won’t work out of the box for this solution. This is because the Database Project doesn’t know about the production and delta scripts. The build by default would create the database and run the data generation plan before unit tests including the database unit tests. However, the unit tests are run immediately after the application is built and we need to specify the a step to build create the scripts and then execute them. I customized the build definition by moving the unit test execution activities to later in the process so I could execute the SQL scripts before the Unit Tests are run. Once this was moved, I could use the built in features to run the data generation plan. Below are the steps for the full end to end Database Continuous Delivery process.

Figure 11 – End to End Database Continuous Delivery Process
To combine this process into the application continuous delivery process, the same tasks above can executed along with the application steps. This process is grouped into three groups: Build/Stage, Deploy, and Execute Automated Tests. The process is outlined below.

Figure 12 – End to End Application and Database Continuous Delivery Process
VSDBCMD
One of the great features of Visual Studio Database Projects is that the deployment and compare functionality can be executed via a command line utility called VSDBCMD.exe. This allows us to perform the necessary steps in our Continuous Delivery process. I utilize a InvokeProcess Activity in the build definition to call a PowerShell script to execute the VSDBCMD commands. Below are examples of how to create the Production CREATE script and the DELTA script. The Production Script creates the full CREATE script from the compiled Production version of the Database Project. The DELTA command shows how to compare two Database Projects to generate the DELTA SQL Script.
Create Production Script
& "C:\program files (x86)\Microsoft Visual Studio 10.0\VSTSDB\Deploy\vsdbcmd.exe" /a:deploy /dsp:sql /model:Ecommerce.dbschema /DeploymentScriptFile:c:\temp\OutputFilename2.sql /p:TargetDatabase="NewEcommerce"
Create Production and Development Delta Script
& "C:\program files (x86)\Microsoft Visual Studio 10.0\VSTSDB\Deploy\vsdbcmd.exe" /a:deploy /dsp:sql /model:Ecommerce.dbschema /DeploymentScriptFile:c:\temp\OutputFilename2.sql /targetmodelfile:"C:\tfs\deliveron\Production\EcommerceSolution\Ecommerce\obj\Debug\ecommerce.dbschema" /p:TargetDatabase="NewEcommerce"
In Summary
This concludes the overview of the solution for Continuous Integration and Delivery for SQL Server Databases. I hope it gives you a complete overview for creating your own Continuous Delivery process. Feel free to contact me if you have any questions or comments.
Review of Key Concepts
-
There are three types of Continuous processes: Integration, Delivery, and Deployment.
-
Continuous Delivery should be set up to be a practice run for Production.
-
Create compare scripts between development and production database projects and don’t compare against live databases.
-
VSDBCMD is a command line utility that perform the deployment and compare functionality in Visual Studio Database Projects.
This was also cross posted at http://www.deliveron.com/blog/post/Implementing-Continuous-Integration-(CI)-and-Delivery-for-SQL-Server-Databases.aspx
The Visual Studio ALM Rangers just released two projects, the Build Customization Guide and the Lab Management Guide. Both projects provide real world, in-depth guidance and hands-on-labs (HOL) for planning and creating solutions for utilizing the Team Build 2010 and Visual Studio 2010 Lab Management. Every development team should utilize the features covered in these guides for creating a build strategy that includes Continuous Integration (CI), packaging and versioning of applications, and automated deployments to at least the development and test environments. By utilizing Visual Studio Lab Management, these environments can be quickly provisioned and managed by those development teams. They will be able to do things restore to a baseline before building, deploying, and running tests in those environments, clone the environment to provide multiple test environments for QA, and attaching a snapshot of the virtual environment along with other rich information to bugs for the developers. Visit the websites for all of the details and downloads for the guidance. Build Customization Guide I am especially excited about the Build Customization Guide being released because this was first Visual Studio Ranger project I have had worked on. I had the opportunity to work with many talented and dedicated individuals. The Epics included in this guidance are: - Practical guidance and tooling to simplify the customization of Team Foundation Build
- Practical guidance to use Team Foundation Build process templates to automate build and non-build scenarios in Microsoft environments
- Practical guidance to enable simple and flexible deployment of applications and their data stores
- Practical guidance for Activities to empower developers and build engineers
- Quality hands-on labs that complement the guidance and effectively guide the user through the features
- Visualization of the guidance using quick reference posters
http://rabcg.codeplex.com/ Lab Management Guide I didn’t contribute to the Lab Management Guide, but I have read through the guidance. It includes a lot of great information that include planning Lab Management, setting up the Virtual Lab environment, and creating Virtual Machines using the VM Factory. The Epics included in this guidance are: - Visualization of the guidance using quick reference posters
- Advanced golden image management using the VM Factory for Lab Management
- Provide guidance on setting up Test environments with respect to pre-defined personas
- Provide Guidance to enable large and small teams to setup and configure both automated and manual tests
- Provide practical guidance for managing and maintaining a Lab Management environment
- Provide practical guidance to enable teams to quickly setup and configure their lab management environment
http://ralabman.codeplex.com/ Visual Studio ALM Rangers So who are the the Visual Studio ALM Rangers? They are a group of internal Microsoft employees and external communities leaders/MVPs who’s mission is to accelerate the adoption of Visual Studio with out-of-band solutions for missing features and guidance. Willy-P. Schaub has posted some great information about who we are, the past accomplishments, and future plan in the Visual Studio ALM Rangers 5 year Report. Please contact us at tfs@deliveron.com for information on these guides or implementing these solutions in your environment. Mike
Development teams utilizing Coded UI Tests have several options where to run Coded UI Tests. When a developer creates an automated test either from an existing action recording or using the Coded UI Test Builder, the test can be run within Visual Studio 2010 just like a unit test. Once the Coded UI test is passing, it can be associated with a Test Case and/or run as part of the build along with the unit tests. I will cover associating a Coded UI Test to a Test Case and running the automated test within Microsoft Test Manager in a future post. In this post I will cover configuring the build server to run Coded UI Tests. While this post describes configuring the build server to run the Coded UI Tests, any machine configured as a test agent can be utilized by the build server and build to run the Coded UI Tests. The primary difference between running the Coded UI Test on the build server than a unit test is that the test requires full access to the UI. Having the build server require full access to the UI introduces a couple challenges including a couple additional requirements. First, the build server requires the application to be installed on the build server the same way it was installed when the test was recorded. The build server also requires a Visual Studio 2010 Test Agent running on it. It also needs to be configured to record video if required. Finally the build has to be configured to run the Coded UI Tests. The following steps walk through configuring these items. Configuring the Test Agent to Run Coded UI Tests 1. Run the Microsoft Visual Studio 2010 Test Agent Configuration Tool (Start > Program Files > Visual Studio 2010 > Visual Studio 2010 Test Agent Configuration Tool) 2. Configure the Test Agent to Run Interactive
3. Ensure that Log on automatically and Ensure screen saver is disabled are checked. This will enable the server to be ready to run the tests even if the server is rebooted. Also, the screen saver has to be disabled so the machine doesn’t get locked. The Coded UI Tests can not run if the screen is locked. If you use Remote Desktop (RDP) to connect to the server, when you log out the machine it will automatically lock it. To prevent this from happening, you must log into it from the machine or VM console. If this is not an option, an alternative is to log on to another server such as the TFS server, then RDP into the build server from the TFS server and close the RDP session to the TFS server to lock this server but the build server remains unlocked and the Coded UI Tests will be able to run. 4. Register the Test Agent to a Test Controller that is not configured for Test Manager. Unfortunately, the Coded UI tests run from the Build Server can not share the same test controller. Enabling Video Recording for the Automated Tests One of the options in the test settings is to enabling video recording as part of the data collection. By default the server doesn’t have the required components and configuration to enable this. Follow these steps to enable the video recording. 1. Install the RTM Update for Lab Management on the Build Server http://www.microsoft.com/downloads/en/details.aspx?FamilyID=8406ef19-35a3-4c03-a145-08ba982f3cef&displaylang=en 2. Install Microsoft Expression Encoder http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=75402be0-c603-4998-a79c-becdd197aa79 3. If the Build Server is Windows Server then enable the Desktop Experience Feature. Configuring the Build to run the Coded UI Tests The final part to configure is to configure the build to run the Coded UI Tests. 1. Open the Test Settings file in Visual Studio by clicking Test > Edit Test Settings > Local. 2. Create a copy by clicking “Save As” and call it something like “BuildServer”. 3. Change the name to “BuildServer”. 4. Choose the Roles item. Change the local execution to “Remote Execution”. 5. Enter the name of the Test Controller that the Test Agent on the build server is using. If you get the error “The following test controller is not available : YourServer. You must remove the association using the Lab Center within Microsoft Test Manager”, then you must remove this association. a. To remove the association, remove the registration in the Visual Studio 2010 Test Controller Configuration Tool. Uncheck the “Register with Team Project Collection” option.
6. The Roles item in the BuildServer Test Settings should look like the following
7. Close the Test Settings and Check in the new build definition file. 8. Open the Build Definition. Click on the Process tab. Expand the Automated Tests > Test Assembly. Click on the TestSettings File ellipse. Chose the BuildServer test settings file. 9. Save the build definition and queue the new build. The Coded UI Test should run on the build and your test should pass. If the test fails, open the test results and view the details the same way you would do for a broken unit test. This is a cross post from the Deliveron blog. http://www.deliveron.com/blog/post/Configuring-a-TFS-2010-Team-Build-Server-to-Run-Coded-UI-Tests.aspx
One of my Team Foundation Server 2010 test servers had TFS 2010, VS 2010, and Team Explorer 2010. Installed the TFS 2010 Power tools to utilize some of the cmdlets and the tfpt.exe utility to create a team project. After I did this I also needed to test the TFS Administration Tool 2.0 for TFS 2010. This is a great and free tool for managing the permissions of TFS users across TFS, SSRS, and SharePoint. This works with TFS 2010 but it is written against the TFS 2008 object model. This required - Team Explorer 2008
- Visual Studio 2008 SP1
- Visual Studio 2008 SP1 Forward Compatibility Hotfix
I installed these pre-requisites and the TFS Admin Tool. Today I got a request to add some additional email alerts to a TFS 2008 team project. Since I already had Team Explorer 2008, I installed the TFS 2008 Power tools to get the alerts feature (The TFS 2010 Power tools doesn’t have this feature).. I went back to work on my script for automated team project creation. I ran my script tfpt createteamproject /collection:http://dlvrn2010md:8080/tfs/defaultcollection /teamproject:"testauto5" /processtemplate:"MSF for Agile Software Development v5.0" /sourcecontrol:New Then I get the following error: TFPT.exe : Unrecognized command option 'collection'. I realized the TFPT command is now pointing to the TFS 2008 Power tool version and obviously doesn’t know what a Team Project Collection is. I looked in the Environment Variables. The Path variable showed a reference to the TFSPowerToolsDir variable. Next, I checked the TFSPowerToolDir variable and it was pointing to the 2008 Power Tools. I changed this to "C:\Program Files (x86)\Microsoft Team Foundation Server 2010 Power Tools\". I reopened the PowerShell ISE, executed the script, and it worked again. This is a unique situation, but it happened to me so it could happen to you :)
This is also posted at http://www.deliveron.com/blog/post/Fix-TFS-2010-Power-Tools-after-installing-TFS-2008-Power-Tools.aspx
Today I have released Team Deploy 2010 for Team Foundation Server 2010. In this post, I am going to give a quick overview of Team Deploy if you haven’t used it before, explain this release and upcoming releases, compare it to Lab Management 2010, and give a walkthrough for setting it up and uninstalling it. What is Team Deploy? Team Deploy is a set of custom build activities used to deploy MSIs to multiple client PCs and/or deploy services to servers. This activities include the ability to kill processes, start/stop services, pass in arguments to the MSIs, provide the service username/password, and uninstall previous versions. Team Deploy uses SysInternal’s PSTools to remotely execute MSIEXEC to install the MSIs and PSKill to kill processes. By using Team Deploy, development teams can create automated build and deploy processes for better configuration management. Deployments can be done on demand or scheduled just like any other build in Team Build. If you are using Team Foundation Server 2008, Team Deploy 2.1 is the current release to download. Team Deploy is open source and free to use. It can be downloaded from http://teamdeploy.codeplex.com This Release and Future Plans I am calling this version of Team Deploy 2010, Release 1. This release is a 1 for 1 port of the MSBuild tasks to Workflow custom activities. I wanted to release this version without any additional enhancements so development teams can upgrade their build definitions to workflow. I have a lot ideas for future versions. Lab Management 2010 has given me some ideas (see comparison below) and there are several other things I want to do. Here is a list of some: - MSI Package for Team Deploy 2010 – For custom build tasks, deployments are easy. Basically just copy the Dll to the MSBuilds folder and use that path in the build definitions. For Team Build custom activities, it is a little more complicated. As you will see in the Setup Walkthrough below, there are several steps that are fairly easy to do manually but are going to be more difficult to do with a custom task. I have begun working on this but it wasn’t ready for this release.
- Breakout Deploy activity into Workflow – Currently the Deploy activity does all the work and calls the other activities within code. I want to create an additional workflow with all of these steps in a workflow.
- PowerShell capabilities – PowerShell 2.0 has the ability to be run on remote machines. I want to research this functionality and see if it makes sense to create an addition set of activities that use PowerShell instead of PSTools.
- Custom Build Definition Screen – Display screen to create the deployment options through the UI instead of creating it in XML today.
- Change the Threadpool to .Net 4 Tasks for deploying to multiple machines at the same time.
- Team Deploy build definition to call another definition to do the build and deploy (Similar to Lab Management)
Team Deploy and Lab Management Visual Studio 2010 introduces an additional product for Team Foundation Server 2010 called Lab Management 2010. This product allows virtual environments be created, quickly provisioned, used for manual and automated testing. Lab Management also includes a new build definition type and activities. With the build definition type, it allows you to revert the virtual environment to a baseline snapshot, build the application, deploy the application, run the automated tests, and capture the results. So Lab Management can do what Team Deploy can do and a lot more. The one area that I have seen Team Deploy used where Lab Management would not be used is for deploying applications to QA and Production. I have worked with several companies that use Team Deploy to deploy to all of their environments for a consistent deployment process. Team Deploy Setup Here are the steps to install Team Deploy and create a simple build. 1. The TeamDeploy2010_R1.zip file contains the following 4 files that are used to install the application. 2. Copy TeamDeploy.Activities.* to a location in source control and check in. 3. Add TeamDeploy.Activities.dll to the GAC using Gacutil. 4. Add source control location of custom assemblies to build controller. ($/TestBuilds/CustomActivities in this example) 5. Copy DeployTemplate.xaml to source control in the BuildProcessTemplates folder. 6. Create a new build definition. In the Process Step click on “New” Template and add the existing DeployTemplate.xaml template that was added to source control. Click OK. 7. Set the build properties to where the PSTools is installed and where the deployment XML is located. Click Save. 8. Rename and edit SampleDeployScript.xml to specify applications to install and machines to deploy to. See http://teamdeploy.codeplex.com website for full list of options available. If you open the DeployTemplate.xaml. It should look like this. If there is an error for the deploy activity. Delete the AgentScope activity. 1. Add Team Deploy 2010 Activities by right clicking in the toolbox and select “Choose Items…”. Make sure System.Activities Components tab is selected and select “Browse…” to find the location of the TeamDeploy.Activities.dll and choose it. 2. Once you have added the TeamDeploy.Activities.dll, you will see the activities selected. Click Ok. 3. Clicking Ok will add the activities to the toolbox. Drag the Deploy activity to the AgentScope container. The required properties will cause a red error icon to display. Fill out the properties to where you have the deployment script and PSTools installed. (Sometimes the designer won’t let you drag the Deploy activity to the canvas. Save the workflow, exit Visual Studio 2010, and reopen the workflow. It should then. Uninstalling or Updating Team Deploy 2010 1. Close Visual Studio 2010 2. Stop the Visual Studio Team Foundation Build Service Host service. 3. To remove Team Deploy from the GAC, browse to c:\windows\microsoft.net\assembly\gac_msil and delete the TeamDeploy.Activities folder. Build Log of Deploy activity in Team Build 2010 Here is an example of the build log for the Deploy activity. I hope you enjoy! Let me know if you have any ideas or run into problems. Mike
I’m excited to be speaking 3 times in the next month on the new testing capabilities in Visual Studio 2010 and TFS 2010. Two events are listed below. The third event is full. I hope you can make one of them. Sign up for the Deliveron Newsletter to be notified about future presentations. Presentation Overview Visual Studio 2010 introduces Lab Management 2010 and Test Professional 2010 to remove the silos between QA professionals and developers to establish a more cohesive development and testing process. Together these products include tools and features for creating test plans, creating and running manual tests, automated UI testing, creating test virtual environments, recording manual tests, and collecting diagnostic and error data to easily include with bugs. See how everyone on your development and testing teams can take advantage of these improvements Omaha Team System User Group Meeting March 23, 2010 at 6:00pm Farm Credit Services of America 5015 S 118th St Omaha, NE 68137 Register here Deliveron April Webcast April 14th, 2010 at 11:00am Central Time Register here
This is Part 4 of my Deployments with TFS series. It has been awhile since I started putting this information together but I haven’t found time to finish this. A question about building ClickOnce deployments with Team Build 2008 on the MSDN forums was just what I needed to get this posted. What is ClickOnce? ClickOnce is a deployment technology that enables you to create self-updating windows based applications that can be installed and run with minimal user interaction. For a complete overview of ClickOnce, please visit this the ClickOnce Deployment Overview article on MSDN. Our Requirements Our requirements contained a couple items that made our deployment more complicated. The first one is one a configuration management issue that I strongly pushed. Basically there were two environments, Test and Production. The ClickOnce was to be built and deployed to the Test server, tested and accepted, and finally pushed to production. The problem is that Test used different config files than Production. The thing we didn't want to do is to have to rebuild the application to update the config files, recreate the manifest, and publish to the production. This had the potential to introduce something different than was tested.Fortunately our Production Release build script was able to copy in the new config files and recreate the manifest and push to production. The helped ensure the same version of the assemblies tested. Of course nothing is perfect, we could have still had problems in our config files. :) The next issue is that we wanted to run Test and Production at the same time to compare if there were problems. ClickOnce thought these were the same applications so we were unable to run them both. The solution for this was to use a different key for each environment. In Test we used a test certificate key that we created, in Production, we used our issued certificate key. With this, the assemblies could be the same or different versions and ClickOnce treated them as two separate applications. The Solution The solution consisted of 4 build scripts - Build and Stage to Test – This builds the application, creates the ClickOnce manifest, and then publishes it to a folder share, ready to be deployed to Test (but not yet).
- Deploy to Test – This script copies the ClickOnce application to the web server so the application is available to the testers. This script also deployed a WCF Windows service.
- Stage to Production – This script copied the production config file into the manifest folder, recreated the manifest (with production certificate), and copied the ClickOnce application to a staging folder on a production (so it could be deployed at a later time).
- Deploy to Production – This script copies the ClickOnce application from the production staging folder to the production web server.
The “staging” builds could be combined with the “deployment” builds but I believe by separating these it offers the most flexibility. I will now highlight some of the unique things I had to do to get this all to work. Unfortunately it wasn’t as simple as using the MSBUILD task. I think this would work for a demo or simple scenario but not a real world scenario. There wasn’t any way to change any of the settings. This offers more options. Build and Stage To Test The first part is the properties. Here I set all of the ClickOnce properties that will be used later on in the build. <PropertyGroup> <TF>"$(TeamBuildRefPath)\..\tf.exe"</TF> <PublishUrl>\\myserver\deployments\coolapp\current\ClickOnceStage\</PublishUrl> <ClickOnceAppName>MyCompany.CoolApp</ClickOnceAppName> <ClickOnceExeFile>MyCompany.CoolApp.exe</ClickOnceExeFile> <ClickOnceProduct>Cool Application</ClickOnceProduct> <Company>My Company</Company> <ClickOnceDescription></ClickOnceDescription> <ClickOnceUrl>http://testserver.mycompany.com/</ClickOnceUrl> <SigningCert>$(SolutionRoot)\MyCompany.CoolApp\CoolApp_1_TemporaryKey.pfx</SigningCert> <SigningCertPassword>1234</SigningCertPassword> </PropertyGroup> The first trick is to edit project file and update the publish url. This allows the build to edit it but not check out the file and need to check it in. Do this before the build by overriding the BeforeCompile target. <Target Name ="BeforeCompile"> <Message Text="Making csproj file writable"/> <Exec Command="attrib -R "$(SolutionRoot)\MyCompany.CoolApp\MyCompany.CoolApp.csproj""/> <Message Text="Replacing PublishUrl"/> <File.RegEx Path="$(SolutionRoot)\MyCompany.CoolApp\MyCompany.CoolApp.csproj" RegularExpression="<PublishUrl>(.*?)</PublishUrl>" NewValue="<PublishUrl>$(PublishUrl)</PublishUrl>" /> </Target> Take the publish.htm file from a manual ClickOnce publish change the version to a tag that can be replaced by the updated version number and check it in to the solution. After the compile, use the modified version of the publish.htm file copy it to the staging location and then replace it with the version. MaxVersion is the variable the represents the new version. I like to keep the assembly version the same as the ClickOnce version. <Target Name="AfterCompile" Condition="'$(IsDesktopBuild)'!='true'"> <!-- Copy modified publish htm file to staging publish location --> <Copy SourceFiles="$(SolutionRoot)\publish.htm" DestinationFolder="$(PublishUrl)" /> <ItemGroup> <WebPage Include="$(PublishUrl)\publish.htm" /> </ItemGroup> <RegEx Condition="Exists(@(WebPage))" Path="@(WebPage)" RegularExpression="#VERSION#" NewValue="$(MaxVersion)" Force="true"/> </Target> Next, I used a couple of custom tasks I created. The first was to get the framework version. I couldn’t figure out a way to do this. Basically this just returns the .net framework path so I can call Mage.exe. The second one takes the name of the app and the version to create the manifest folder. Then it does the heavy lifting to create the ClickOnce application. We have to do each step to make this work. There is one thing you will probably noticed is that the setup.exe is renamed to CoolAppSetup.exe. This was done because there was a policy that users couldn’t run setup.exe. I left out the copying of the files to the staging location before running all of this below. I had to copy the files individually because this build script also built the WCF service. You will need to add the appropriate process to copy these. - Generate the application manifest
- Sign the application manifest
- Rename the source files to .deploy
- Generate the deployment manifest
- Sign the application manifest (one more time)
- Create the bootstrapper
<Target Name="AfterEndToEndIteration"> <GetFrameworkPath> <Output TaskParameter="FrameworkPath" PropertyName="FrameworkPath" /> </GetFrameworkPath> <CreateManifestName ExecutableName="MyCompany.CoolApp" ExecutableVersion="$(MaxVersion)"> <Output TaskParameter="ManifestName" PropertyName="ManifestName" /> </CreateManifestName> <PropertyGroup> <ClickOnceApplicationUrl>$(ClickOnceUrl)$(ClickOnceAppName).application</ClickOnceApplicationUrl> <PublishDir>$(PublishUrl)</PublishDir> <AppPublishDir>$(PublishDir)Application Files\$(ManifestName)</AppPublishDir> <SdkPath>$(FrameworkPath)\</SdkPath> <VersionNumber>$(MaxVersion)</VersionNumber> </PropertyGroup> <Message Text="FrameworkPath = $(FrameworkPath)" /> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="Building $(ClickOnceAppName) ClickOnce version: $(VersionNumber)"> <Output TaskParameter="Id" PropertyName="StepId" /> </BuildStep> <!-- ************************************************ Generate application manifest ************************************************ --> <Exec Command="mage.exe -New Application -TrustLevel FullTrust -ToFile "$(AppPublishDir)\$(ClickOnceExeFile).manifest" -Name "$(ClickOnceAppName)" -Version "$(VersionNumber)" -FromDirectory "$(AppPublishDir)" WorkingDirectory="$(SdkPath)"/> <!-- ************************************************ Sign application manifest ************************************************ --> <!--<Exec Condition="'$(SigningCertPassword)'==''" Command="mage.exe -Sign "$(AppPublishDir)\$(ClickOnceExeFile).manifest" -CertFile "$(SigningCert)"" WorkingDirectory="$(SdkPath)" />--> <Exec Condition="'$(SigningCertPassword)'!=''" Command="mage.exe -Sign "$(AppPublishDir)\$(ClickOnceExeFile).manifest" -CertFile "$(SigningCert)" -Password "$(SigningCertPassword)"" WorkingDirectory="$(SdkPath)"/> <!-- ************************************************ Rename source files to .deploy ************************************************ --> <ItemGroup> <SourceFilesToRename Include="$(AppPublishDir)\**\*.*" Exclude="$(AppPublishDir)\*.manifest;$(AppPublishDir)\*.htm"/> <SourceFilesToDelete Include="$(AppPublishDir)\**\*.*" Exclude="$(AppPublishDir)\*.application;$(AppPublishDir)\*.manifest;$(AppPublishDir)\*.htm"/> </ItemGroup> <Copy SourceFiles="@(SourceFilesToRename)" DestinationFiles="@(SourceFilesToRename->'$(AppPublishDir)\%(RecursiveDir)%(Filename)%(Extension).deploy')" /> <Delete Files="@(SourceFilesToDelete)"/> <!-- ************************************************ Generate deployment manifest ************************************************ --> <CreateItem Include="$(AppPublishDir)\$(ClickOnceExeFile).manifest" AdditionalMetadata="TargetPath=Application Files\$(ManifestName)\$(ClickOnceExeFile).manifest"> <Output TaskParameter="Include" ItemName="ApplicationManifest"/> </CreateItem> <Message Text="@(ApplicationManifest)" /> <GenerateDeploymentManifest MapFileExtensions="true" AssemblyName="$(ClickOnceAppName).application" AssemblyVersion="$(VersionNumber)" Description="$(ClickOnceDescription)" Product="$(ClickOnceProduct)" Publisher="$(Company)" SupportUrl="$(SupportUrl)" EntryPoint="@(ApplicationManifest)" Install="false" UpdateEnabled="true" UpdateInterval="7" UpdateMode="Foreground" OutputManifest="$(PublishDir)\$(ClickOnceAppName).application"/> <!-- ************************************************ Sign application manifest ************************************************ --> <!--<Exec Condition="'$(SigningCertPassword)'==''" Command="mage.exe -Sign "$(PublishDir)\$(ClickOnceAppName).application" -CertFile "$(SigningCert)"" WorkingDirectory="$(SdkPath)"/>--> <Exec Condition="'$(SigningCertPassword)'!=''" Command="mage.exe -Sign "$(PublishDir)\$(ClickOnceAppName).application" -CertFile "$(SigningCert)" -Password "$(SigningCertPassword)"" WorkingDirectory="$(SdkPath)"/> <!-- ************************************************ Generate Bootstrapper ************************************************ --> <ItemGroup> <BootstrapperFile Include="Microsoft.Net.Framework.3.5"> <ProductName>Microsoft .NET Framework 3.5</ProductName> </BootstrapperFile> <BootstrapperFile Include="Microsoft.Windows.Installer.3.1"> <ProductName>Windows Installer 3.1</ProductName> </BootstrapperFile> </ItemGroup> <GenerateBootstrapper ApplicationFile="$(ClickOnceAppName).application" ApplicationName="$(ClickOnceAppName)" ApplicationUrl="$(ClickOnceUrl)" BootstrapperItems="@(BootstrapperFile)" Culture="en" FallbackCulture="en-US" CopyComponents="true" Validate="false" OutputPath="$(PublishDir)"/> <Copy SourceFiles="$(PublishDir)\Setup.exe" DestinationFiles="$(PublishDir)\CoolAppSetup.exe" /> <Delete Files="$(PublishDir)\Setup.exe" /> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Succeeded"/> <OnError ExecuteTargets="MarkBuildStepAsFailed" /> </Target> <!-- ************************************************ Mark the buildstep as failed ************************************************ --> <Target Name="MarkBuildStepAsFailed"> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Failed"/> </Target> The Deploy Builds are simply a Copy task to copy the files to the web server. Do this by creating a share to the same location so you can use a UNC. The production stage build is basically all of the above again but with the production certificate key and copy the new config file(s) to the production stage location. Looking back on this it seems complex but this is what the publish wizard is doing behind the scenes and offers complete customizing to fit your needs. I sliced, diced, and renamed items in the scripts above. I tried to make sure everything is correct. If there is a typo or something missing, please let me know and will update it. Enjoy! Mike
In previous versions of Team Foundation Server there was not a way to install and configure TFS to be run in a completely high available environment. TFS 2008 supports the data tier running in a SQL Server Cluster. If the TFS application tier server crashed, there could be a “warm standby” configured to take over but required a manual process to do this. TFS 2010 supports running multiple Application tier servers using Network Load Balancing (NLB). Last year I first heard of topology improvements in TFS 2010 in Brian Harry’s post about the Administrator, Operations,and Setup Improvements in Team Foundation Server 2010. I think this is an extremely important feature as companies are utilizing more features in Team Foundation Server and expecting these services to always be available. In this post I am going to explain: - Configuring the second TFS application tier
- Enabling and configuring Network Load Balancing in Windows Server 2008 R2
- Testing TFS using the NLB Application tier severs
- Lessons learned
Team Foundation Server 2010 Farm Network Topology Diagram This is a diagram shows the topology of the TFS configuration I created to demonstrate the NLB option. I set up this environment on a laptop. I installed Windows Server 2008 R2 x64 on the laptop as the host OS to utilize Hyper-V. I added Active Directory Domain Services (ADDS) and DNS to this machine and configured it as the domain controller. I installed SQL Server 2008 R2 x64 on it also to be the data tier for the TFS installation. Both TFS Application Tier Servers were created as Hyper-V virtual machines with Windows 2008 R2 x64. To make this configuration 100% redundant I would have needed to install the reporting services on both of the TFS Servers, used a SharePoint 2007 Farm for the portal, and a SQL Server cluster for the data tier. In fact, now that I have all of this working, I am going to uninstall everything and try to get WSS and SSRS installed on both application tiers also utilizing the NLB. This would allow for 100% redundant and high availability for all of the TFS 2010 Components with only 4 servers (creating a 2 server SQL Server Cluster). I will post a follow up on how this goes.. Team Foundation Server Installation The TFS installation and configuration for the first server (TFS2010A) was done just as if it was going to be the only server. Here are the settings after I installed the first server. For the second server (TFS2010B), the only pre-requisites that were required were IIS 7 and SQL Client connectivity tools. Below are the steps for configuring the second TFS Server. In the TFS configuration, choose the “Application-Tier Only” installation option. The first step was the Welcome step. There were no options on this step. The next step is to specify the configuration database that was created when the first server was configured.  Next, specify the service account for the the new application tier. I chose to use the same domain account that I used for the first server.  This screen shows the summary of the settings that were chosen before the verification is run.  After the first time I ran the verification I received two errors. One was that .Net 3.5sp1 wasn’t installed. I’m not sure why I reported this error. When I checked it, it was installed. It could be related to other error. The other error, TF255040, was that I didn’t have Reporting Services or SQL Server Connectivity tools installed.  I installed the connectivity tools and reran the verification process and it passed this time.  The configuration completed successfully. The TFS administrative console now shows both application tier servers. Setting up Network Load Balancing in Windows 2008 R2 and Hyper-V Now that both servers are installed and configured correctly, the next step is to set up Network Load Balancing (NLB). This will allows users to connect to TFS through a single endpoint and allow NLB to balance the traffic and route all of the traffic to one server if the other is unavailable. This provides high availability in the event of an outage or when the servers need to be updated. The first thing to do before setting up NLB is to pick a static IP address and create a DNS (A) Record for the shared name. In this example, TFS2010 is the endpoint that clients such as Visual Studio 2010. Here is a snapshot of the A records.  Here is an article I used to help enable and configure NLB in Windows Server 2008 R2. Below are the steps I performed to configure it. http://technet.microsoft.com/en-us/library/cc731695.aspx For each TFS Application Tier server, install Network Load Balancing by going to Server Manager > Features > Add Features > Network Load Balancing Once NLB is installed on all of the App Tiers, run the Network Load Balancing Manager by typing nlbmgr at the command prompt. Then connect to one of the hosts. I chose TFS2010a first. Right click on the Network Load Balance node and choose “Add New Cluster”. Add the current server to the node by walking through the wizard. You should be able to leave the defaults unless you want to limit the NLB to just port 8080. The last step of the wizard is to assign the Cluster a shared IP Address. This IP Address is how all of the clients will access and see it. Make sure this is different than the IP addresses of the any of the nodes in the cluster. Next, add the other host to the cluster by right clicking on the cluster and choosing “Add Host to Cluster”. Enter the name of the Host to be added to the cluster. Here is what the Cluster looks like when it is configured.  Connect to TFS from Visual Studio 2010 Testing the high availability servers To test the high availability configuration, I am going to take down one of the TFS application tier servers and then both. First I created the team project while both servers were available. Then I created a C# windows project, checked it in, and then checked out one of the files. Next, I disabled the NIC on TFS2010a. I did a Undo checkout on the file NLB rerouted the traffic to TFS2010B and it worked perfect. Next, I Disabled the NIC on TFS2010b so now both are disabled and it should error. Tried to check out a file and got a TFS not available error as expected. Last, I re-enabled the NIC on TFS2010A I performed the check out again and worked perfect. The NLB worked as expected. Lessons Learned I’m a developer. I started my IT career as a server and desktop administrator but that was a long time ago. So setting up a domain to test this scenario was fun but I ran into a few unexpected problems. Here are a couple things that slowed me down. - Installed DHCP and DNS with dynamic IP. Make sure you assign a static IP address to the virtual internal network card on the DC. Actually now that I have assigned static IP addresses to both of the TFS Servers, DHCP doesn’t even need to be installed.
- I couldn’t reach SQL Server 2008 R2 from the TFS Servers. I got an TF255049 error in the TFS configuration. I installed the SQL Server Management Studio and couldn’t connect using that. I set up aliases and toggled named pipes on and off. Still couldn’t connect. Finally I stumbled upon the network protocol configuration for SQL. TCP and Named Pipes were disabled. Seems very strange but probably a security precaution. I enabled TCP/IP and it worked perfect.
NLB Issue I ran into an issue trying to configure NLB on Windows Server 2008 R2 using Hyper-V “The interface is misconfigured” Cluster IP address (IP) not added to TCPIP properties Dedicated IP address (IP) not added to TCPIP properties Fix is to enable MAC spoofing in the settings of each VM in Hyper-V. Enjoy! Mike
To me there has always been a feeling a of excitement to be able to build an application and then deliver it to someone that wants it. When I first started programming over 20 years ago with GW-BASIC on my Tandy 1000 EX, it was limiting that what I built could only be run within GW-BASIC since it was an interpreted language environment and not compiled. When I bought Quick Basic 4.5, I could finally compile my applications into an EXE and run them outside of the interpreter. Then I felt like I hit the big time when I was able to build my first setup package in Visual Basic 4. I remember I built a Hello World caliber application and created a setup package that took 3 or 4 floppy disks. I didn’t think it could get any better than this :) Over the years the the excitement about delivering applications became more from the what was built and not how it would be delivered. Visual Studio has always included functional, no frills setup projects. 3rd Party vendors have created easier to use and more power tools for creating deployment projects such as InstallShield. Developers who didn’t purchase a 3rd Party tool were limited to using the OOB (out of the box) setup projects within Visual Studio. While this is functional, the developer has to know where and how to do things and the usability is not very intuitive. It requires many steps to creating a MSI that I have blogged about in Deployments with TFS Part 2: How to create an automated deployment MSI. In Visual Studio 2010 there is finally an easy to solution without purchasing an additional production. Last week I saw this post from Somasegar on Building setup and deployment packages in VS 2010. Microsoft has partnered with Flexera, makers of InstallShield to create InstallShield Limited Edition for Visual Studio 2010. This brings the InstallShield graphical interface to Visual Studio. In addition to providing a highly intuitive interface for building setup packages, this product allows setup packages to be built from with TFS Team Builds. This has been a major pain point for automated deployments and SCM (Software Configuration Management) processes. I downloaded and installed InstallShield 2010 LE and here is a walkthrough of the tool. Download and Installation Read Somasegar’s blog post on how to download and install it. (see link above) InstallShield 2010 LE Setup project Once it is installed and you create a InstallShield Setup project, the Project Assignment view is the default view. As you can see, the graphic is a guide that explains the parts of the MSI and the steps to create the package. At the bottom of the screen are the steps to the installation project. In addition to the steps at the bottom of the guide, there are also intuitive steps to the right that keep all of the package settings cleanly organized. This first step is to fill out the basic information about the application that is going to be deployed. In the second step, required operating systems and prerequisite applications can be specified and enforced when installing the application. Custom prerequisites can be defined by choosing “Create a custom software condition” under “More Options”. The installation Architecture section step is disabled in the Limited Edition. In the other editions different features can be defined for users to choose what sections they want installed. The next step is the Application Files. Here the application’s files can be added to the installation. The “Add Project Outputs” is the primary button for adding the application files. I found this dialog window to be a lot easier to use than the Visual Studio setup project. The Application Shortcuts step is where desktop and start menu shortcuts can be defined. If the application requires any registry entries, they can be defined in the Application Registry step. The last step is the Installation Interview. This step asks a series of questions that drive what dialogs the user running the installation will see. Custom dialogs are not supported in the InstallShield Limited Edition. Custom dialogs are supported in the Visual Studio setup projects. For the automated deployment MSIs, I create a dialog that allows the user to specify the environment. Custom Actions are non-standard activities that can be performed at different points of the installation process. The Limited Edition supports VBScript, JScript, and Exe custom actions. However, as shown in the following image, there are only a couple points in the process where custom actions can be defined. The Premier and Professional editions also support InstallScript, a powerful scripting tool to create more advanced customizations to the installation process. After I built the MSI, I ran package to install it. Users will see this message box that the installation was created with a beta version of InstallShield. InstallShield 2010 LE for Visual Studio 2008 The InstallShield 2010 LE Installation also installs a version that works within Visual Studio 2008. This interface looks the same in Visual Studio 2008 as it does in Visual Studio 2010. Building MSIs with Team Build 2010 This is the feature I am most looking forward to in InstallShield 2010 LE. Standard Visual Studio 2008 setup projects can not be built within Team Build without some tricks. Unfortunately TFS Source Control and Team Build integration is not available in this beta version. I verified this with Flexera. They are currently working on it. As soon as an updated version is available with this enabled I will do a follow up post detailing the TFS Source Control and Team Build experience. I’m interested to see the following in action: - Triggering a build and having the MSI compile with the updated assemblies.
- Curious to see if the InstallShield Setup project build can detect new dependencies added. My tests will include adding a reference to the primary output application. Then do a new build to see if the MSI will automatically include it. It might be expecting too much but this would be very beneficial.
Overall - The Project Assistant is a very simple to use series of steps to create a complete setup project. As users feel more comfortable with the too, they will probably jump to the specific screens they are looking for in the navigation pane on the right. Both are highly intuitive and significant improvements over the the standard Visual Studio setup projects.
- Most things that are supported in the standard Visual Studio setup project can be accomplished with InstallShield 2010 Limited Edition. For most installation packages, these limitations will not be problem. However, I will not be able to create automated deployment MSIs because of the limitations of no custom dialogs and not being able to create custom properties.
- Being able to rebuild the MSIs during each Team Build is a huge benefit. Once this feature is available, I think it will become my favorite feature.
- I believe Microsoft and Flexera will both win with this product. Microsoft’s Visual Studio 2010 will include an improved tool for creating installation packages without having to reinvent the wheel. Flexera has built an amazing and easy to use product that will work for the majority of scenarios, but many will want to upgrade to the Express, Professional, or Premier editions to get the full power of InstallShield.
- The final product should be great, but this beta version is not ready to be used for more than evaluation purposes. Between the beta message box that is displayed when the user installs it and the fact that the TFS Source Control and Team Build integration features are not available yet, I recommend waiting until the final version is released.
Mike

There is a lot of information about the major updates of TFS 2010 and Team Build 2010 including changing from MSBuild to Workflow and Gated Check-Ins to name a couple. In using TFS and Team Build 2010 beta 2, there are a lot little features and improvements that help make these two products complete and polished. Here are a few of the features and I keep discovering new ones each time I use it. New Build Definition will default name and solution to build if you have a solution open in Visual Studio 2010 when you create a new build definition, the build name will default to the solution name. An open solution will also automatically be populated as the Project to Build The build retention policy is not set to “Keep All” by default. Finally, the default retention policy for the builds is not set to “Keep All” anymore. Primarily all results will default to keep the last 10 builds. In Visual Studio 2008, I always recommended that this should be changed. TFS Build notifies you about successful and failed builds The Team Foundation Build Notification tool used to be part of the power tools. Now it is included with the standard installation and alerts you to the success or failure of the build. This supports continuous integration and gated check-in builds. The notification dialog window also has an option for unshelving failed gated check-ins. This dialog displays for a successful Gated Check-in build This dialog is display when a Gated Check-In fails. Notice the Unshelve Changes option to retrieve the changeset that was be attempted to be checked-in. Build Parameters are now strongly typed and visible In Team Build 2008, parameters could be passed in to a build when it was being queued. However the format was command line argument style passed into a textbox similar to this: /p:IsThisCool=”false” In Team Build 2010, the build parameters are displayed as strongly typed properties. This will allow for type checking and eliminate the misspelling of parameters. Enjoy all of the great new features in Team Build 2010 including these smaller but helpful features! Mike
Earlier this week at the Omaha Team System User Group someone asked about how to add new statuses to a work item in TFS. I mentioned I had the steps documented that I would send him. After reviewing the steps I thought it would be useful if I posted this for everyone. Download and Install the TFS Power Tools Unless you prefer editing XML and running command line utilities to GUI editing, the first thing you should do is download the latest edition of TFS Power Tools. The Power Tools are a must have Team Foundation Server add-on that Microsoft has used to add functionality since the release of TFS Power Tools. There has been several updates with October 2008 being the latest release. Download Visual Studio Team System 2008 Team Foundation Server Power Tools - October 2008 Release Work Item Template Process Editor After the TFS Power Tools are installed, Process Editor is now available under the Tools menu item. Opening a Work Item Template for One Team Project To edit a Work Item Template (WIT) there are a couple options. To modify the template for one project, you can open the WIT directly from the project, edit it, and save it back to that project by choosing the “Open WIT from Server” option. When you choose “Open WIT from Server”, it will display a dialog with all of the team projects and the templates. In this example, the Bug WIT from the SampleScrum template is chosen. Opening a Work Item Template for Multiple Team Projects To edit a WIT for multiple team projects, you will want to export the template to a file, edit the changes and then import that change into each of the team projects. To Export the WIT, choose Export WIT. This displays the dialog to select the WIT. Save the WIT to a location on your local machine. It will prompt you if you would like to include the Global List definition. You can choose No. Next open the saved WIT by choosing “Open WIT from File” and selecting the saved file (Bug.xml). Editing the Work Item Template The Work Item Template Editor has three tabs. In this example we don’t change any of the fields or the layout of the work item, so we can ignore these tabs. To add statuses to the Work Item, we will modify the Workflow tab. Adding a status is more than just adding the option to a list. The statuses of a work item are part of the workflow. Basically each status is only available when it is enabled in the workflow. For example, you might have a “Fixed” status and a “In Test” status. In the workflow, you can define it so that “In Test” won’t be available to select until it has been marked “Fixed” first. Here is an example of the workflow tab The different Statuses in Red and the arrows show the flow of one status to the next. Once it is decided when the new statuses will appear and what statuses will be available after the new status, we can add the statuses and connect them to the other statuses. Add a Status by selecting the State item in the Toolbox (if the Toolbox is not visible, choose View -> Toolbox from the menu. Drag the State item to the canvas in an area where it will be easier to connect it to the other States. If the workflow becomes cluttered, you can right click on it and choose “Reset Layout” When you have added the status to the canvas it will look similar to this Give the status a name by typing over the State1 text Now, connect this to the previous status. For this example the bug will go from “In Progress” to “Fixed” to “Ready For Test”. Do this by clicking on the Transaction Link from the Toolbox, this will change your cursor to the link cursor. Click and hold on the starting Status and drag the line to the target Status. This will add the line between the two and create a Transition box. For the new status to be valid, you must give the Transition a Reason. This is just a textual explanation why it would move to this status from the previous. Expand the Transition box so it shows the Reasons, Actions, and Fields. Right click on the box and choose “Open Details”. A Workflow Transition dialog box will display. Choose the Reasons tab and modify the Value to display the text you would like. Add a second Transaction Link from the new status (Fixed) to the Target status (Ready for Retest) and give it a reason. Once this is added, you can validate your workflow by right clicking on the canvas and choosing “Validate All”. If there are any errors in the validation they will be displayed in the Error List. If there are no errors the Output tab will look similar to this Click the save button in the toolbar to save the WIT. If you have opened the WIT from the server then this saves it back to the Team Project and is available. If this was a File then you must import it into the appropriate Team Project(s). To Import the Work Item Template, choose “Import WIT” from the menu. This dialog will display. Select the file that was edited (Bug.xml) and then select the team project and click OK. Repeat to add to the other Team Projects. Applying Change to Process Template Now that the work item is modified, if you want this change to be in new projects created you must update the source and re-upload the templates. Copy the bug.xml and bug.wit to the source template folder on the TFS Server. The Default location is C:\Program Files\Conchango\Scrum for Team System\ProcessTemplate\AgileSoftwareDevelopmentwithScrum\WorkItemTracking\TypeDefinitions To upload the template, right click on the TFS root node in the Team Explorer and choose “Process Template Manager”. A dialog will display that contains a list of the installed templates. Click on the Upload and browse to: C:\Program Files\Conchango\Scrum for Team System\ProcessTemplate\AgileSoftwareDevelopmentwithScrum Open the ProcessTemplate.xml file. It will next prompt you if you want to overwrite. Choose Yes and it will upload the changes. If you do not wish to overwrite it, then you must change the name by opening the same ProcessTemplate.xml with the Process Editor. That completes the steps to modify the Work Item Templates, apply the changes to one or multiple team projects, and also back to the template for future projects created with the the process template. Mike

Here are the updated slides for my Getting Agile with TFS 2010 presentation. I gave this presentation for two lunch and learns at ANT and then earlier this week at the Omaha Team System User Group meeting. I had a great time giving this presentation multiple times. Thanks everyone that attended these talks. Getting Agile with TFS 2010 Presentation Slides Mike 
I am going to giving two Getting Agile with Team Foundation Server 2010 talks in November, both in Omaha, NE. On Thursday November 12th, I will be giving the talk for a lunch and learn at Advanced Network Technologies. You can register for the event here. On November 24th, I will be giving the talk at the Omaha Team System User Group Meeting. Here is more information about the event and registration instructions. This is the same talk as the one I gave at the Heartland Developer Conference in October but I will be using Beta 2 for these two. Here’s some more details on the presentation and myself. I look forward to seeing everyone there. Presentation: Getting Agile with TFS 2010 This presentation will demonstrate a complete two week scrum iteration from the planning meeting to development, testing, and bug fixing to deployment utilizing the features found in Team Foundation Server 2010. New features include gated check-ins for Continuous Integration (CI), Test-Driven Development (TDD), Product Backlog enhancements including hierarchical views and support for multiple teams to work from a single backlog. The presentation also demonstrates the enhancements to the TFS Portal and Web Access to support Agile planning and displaying graphs such as burn-down charts. Each walk through includes a live demonstration of the feature in Visual Studio 2010. Speaker: Mike Douglas, Deliveron Consulting Services Mike Douglas is a Solution Consultant at Deliveron Consulting Services where he provides end-to-end solutions and TFS installation, configuration, and custom development for clients. He has over 11 years experience building enterprise level applications on a variety of .NET technologies including WCF, Web Services, ASP.NET, Disconnected Smart Clients and Data Synchronization, BizTalk, and Team Foundation Server. Mike enjoys trying to keep up with the constant change and evolution of .NET. Mike is an experienced presenter having spoken at several Omaha .NET User Group meetings on CSLA.NET, Subsonic, and TFS. He also spoke at the 2008 ESRI International User Conference on a GIS integration project he helped lead. Mike actively maintains the open source project, Team Deploy, on CodePlex for deploying MSIs using Team Foundation Server. Mike also enjoys sharing his experiences in Code Generation, CSLA.NET, and TFS on his blog at www.CodeSmartNotHard.com.
Here are the slides from my An Iteration in the Life of an Agile Team with Team System 2010 talk at the 2009 Heartland Developer Conference. Thanks for everyone that attended. I had a great time giving the talk and at the rest of the conference. http://www.codesmartnothard.com/content/binary/agile_vsts2010.zip If you didn’t get a chance to attend my talk, I am going to be giving the presentation again (This time with beta 2!) at the next Omaha Team System User Group meeting on November 24th. Check out the Omaha Team System User Group website for more details. Thanks! Mike
In Part 1: The Deployment Process Should Enforce Good Configuration Management Practices, I gave some background on my experiences and how the configuration management process has evolved and some rules and benefits to the automated deployment MSIs. In Part 2: How to create an automated deployment MSI, I walked through the steps to create an automated deployment MSI in Visual Studio satisfying the rules from Part 1. In Part 3, I am going to walk through the steps to install Team Deploy. Then walk through creating a team build, configure Team Deploy, and deploy a MSI with it. There is also a great Screencast by Ian Ceicys walking through the entire process of installing TFS, WIX, Team Deploy and deploying a MSI. I highly recommend watching this. Installing PS Tools - Team Deploy uses the free PSExec and PSKill utilities by Sysinternals (owned by Microsoft). PSExec allows you to remotely run any command and PSKill can kill any process on a local or remote machine.
- Download PSTools at http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx and install to a local folder. I also recommend renaming psexec and pskill to something like psexec2.exe. Some anti-virus software sees these files as a risk.
Installing Team Deploy - Browse to the Team Deploy website on CodePlex at http://TeamDeploy.CodePlex.com
- Click on the Downloads and download the TeamDeploy.MSI.
- Run the MSI to install Team Deploy to c:\Program Files\MSBuild\TeamDeploy
- The windows service account that runs Team Build on the build server will need to be a local administrator on all target machines.
Creating a Team Deploy TFS Build - In Team Explorer, create a new build in your Team Project by right clicking on Builds and choosing “New Build Definition”
 - Give it a name such as “Build and Deploy”
- Create a workspace (Cloak other folders in your project that don’t need to be part of the build. This helps the speed up your build because otherwise the server will try to get all source files in the project)
- Leave Project File name as is but click on the “Create” button to create a new TFSBuild.proj file.
- Next choose the solution you want to build, then the configuration type. I recommend leaving the default.
- Choose any options that you want to enable for running tests and/or code analysis. I would recommend leaving these unchecked for now and once you verify everything is working then go back and enable the options you want.
- In TFS 2008, you can choose retention policies. This will help prevent builds from filling up your server disk space quickly. I usually choose Keep 7 latest.
- the next options are for the Build Defaults. Choose the appropriate build agent. If unsure, just leave the default. Then choose the share where you want to copy the staging files.
- The last option is “Trigger”. The "build and deploy" build should be separate from the continuous integration build. I recommend leaving the default “Check-ins do not trigger a new build”.
 - Finally click “OK” to create the build type.
Creating the build definition will create the TFSBuild.proj that contains the basic options that were selected in the wizard. The following steps will customize the TFSBuild.proj file created. This file is a Xml file based on MSBuild. - To modify the TFSBuild.proj file, located the file under Source Control -> $/YourTeamProject/TeamBuildTypes/Build and Deploy (You can also navigate directly to this file by right clicking on the build definition and choosing "View Configuration Folder".)
- Check out and open the TFSBuild.proj file to configure it to use Team Deploy
- Find the comment <!—Do not edit this -> and add the following line underneath the one that is already there. It should look something like the screenshot below
<Import Project="$(MSBuildExtensionsPath)\TeamDeploy\TeamDeploy.Tasks.targets" />  Scroll to the bottom of the TFSBuild.proj file to the <PropertyGroup>. Overwrite the Property group with the following (Adjust the paths for your specific environment): <PropertyGroup> <KillAppPathFilename>c:\Program Files\PSTools\pskill2.exe</KillAppPathFilename> <RemoteExecutePathFilename>c:\Program Files\PStools\psexec2.exe</RemoteExecutePathFilename> </PropertyGroup> <!-- Deploy MSI --> <Target Name="AfterEndToEndIteration"> <CallTarget Condition="'$(IsDesktopBuild)'!='true'" Targets="DeployMSITargetVirtuals" /> </Target> <Target Name="DeployMSITargetVirtuals"> <Deploy DeployScript="$(SolutionRoot)\..\..\Push Scripts\SampleDeploy.xml" KillAppPathFilename="$(KillAppPathFilename)" RemoteExecutePathFilename="$(RemoteExecutePathFilename)" TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" /> </Target> The copied Xml in the TFSBuild.proj should look something like this  - Save and check-in the TFSBuild.proj file
The Deploy task uses a Xml Deploy Script that contains the information of what Msi(s) to deploy, additional tasks such as starting and stopping the service, and specifies the target machines. The following steps walks you through editing this file.  There are a few things to note here. - Team Deploy can
- Kill 0 to many processes
- Deploy/Uninstall 0 to many MSIs
- Deploy MSIs to 0 to many Target Machines
- Modify the xml appropriately for your environment. The GUID for the uninstalls are the MSI product codes. If the MSI is done correctly it will uninstall previous versions using the upgrade code, however they are usually unable to remove the same version of the MSI, this is why we have the separate step of uninstall.
- The ExtraArgs element contains the SETUPENV variable that is used by the MSI’s custom action to copy the correct environment’s config file to the project’s. The custom action is a simple VBScript that copies the config file (not included with Team Deploy). See Part 2 for more details on creating the config files folder structure.
Once the TFSBuild.proj is checked in and the Deploy script is saved (or also checked in), then you can right click on the build and do a queue new build. The MSI will be deployed to your target machine(s). See the Troubleshooting / FAQ section of Team Deploy or contact me if you have any questions or problems.
Team Deploy is a free set of custom Team Build tasks for deploying MSIs to client PCs and servers. Team Deploy 2.1 has been released and includes a number of fixes and a couple new features.
A special thanks to Jeremy Novak for creating the new CleanupPsExec task and multiple other fixes. Here is the list of the changes: - Moved Guidance and Installation from Word document to wiki site (and created a Troubleshooting section)
- Added -accepteula to all pstools calls so it won’t display the EULA dialog the first time it runs
- Added new CleanupPsExec task and test to clean up the PSTools service if it becomes stuck.
- Fixed spelling error in RemoteExecute task
- Added support to uninstalling 32bit apps on Windows 2008 64bit servers
- Changed property declarations to be auto-implemented
- Updated task required properties to have the Required attribute
- Created Team Deploy Installation Screencast
- Other misc fixes.
Team Deploy 2.1 can be found on CodePlex at http://teamdeploy.codeplex.com/. -Mike
Today I completed the installation of Team Foundation Server 2010 beta 1. I had previously started a couple times and run into a couple issue (mostly time) but didn’t get a chance to finish. Tonight I finally worked through a couple issues and completed it. I kept a few notes of the issues I encountered and what I did to resolve them. If you run into any of these errors, I hope they help. TFS Configuration Wizard Readiness Checks When the configuration wizard completed, I had errors in Reporting Check and SharePoint Check. Reporting Here is the error TF255275: The following Web service for SQL Server Reporting Services could not be accessed: http://myserver/ReportServer/ReportService2005.asmx Problem was I installed Report Services in Integrated Mode. It only supports Native. Here are the steps to fix the error: 1. Deleted the ReportServer databases 2. Recreated the ReportServer database in Native mode. SharePoint We are planning on using this server for multiple things and we installed SharePoint 2007 on before I started the installation of TFS 2010 beta 1. I thought that TFS would simply install the extensions to any compatible SharePoint installation on the server. Apparently, TFS must install and configure SharePoint on the machine before the verification will allow you to continue. Here is the error TF255282: Windows SharePoint 3.0 cannot be installed error on server. The program is already installed on this server. The fix is easy. Simply, go to Add/Remove programs and uninstall. However I do want MOSS 2007 to be install on it. Once, I have a backup made after VSTS 2010 finishes installation. I am going to try uninstalling WSS 3 and reinstalling MOSS 2007. After fixing these two bugs, the Readiness Checks completed successfully. Clear sailing from here? Not quite. When the configuration tool completed, it displayed the following error. Windows NT user or group '.\tfsservice' not found. Check the name again. Installation log details: TF255356: The following error occurred when configuring the Team Foundation databases: Error occurred while executing servicing step Setup Warehouse for component TfsWarehouse during Install: Windows NT user or group '.\tfsservice' not found. Check the name again.. For more information, see the configuration log. (Error occurred while executing servicing step Setup Warehouse for component TfsWarehouse during Install: Windows NT user or group '.\tfsservice' not found. Check the name again.) ---> Microsoft.TeamFoundation.Framework.Server.CollectionServicingException: Error occurred while executing servicing step Setup Warehouse for component TfsWarehouse during Install: Windows NT user or group '.\tfsservice' not found. Check the name again. ---> System.Data.SqlClient.SqlException: Windows NT user or group '.\tfsservice' not found. Check the name again. The system allowed me to enter a dot for the server name instead of the actual server name and then display the error. I would classify this more as a user error but it would be nice to prevent or allow configuration tool, to lookup the actual server so it will complete. I logged an error with Connect. I will see how they rate it. For the fix, fortunately I took a snapshot of server right before I ran this. I restored to the previous step and restarted the configuration tool. For the service name, I entered: <myserver>\TFSService and everything worked. It finally completed with a Success message!!! While I have been typing this, I started the TSVS 2010 Beta 1 Installation. It is really slow (knock on wood), but so far it hasn’t caused any errors. Thanks, Mike
Note: I slightly changed the title from TFS Deployments to Deployments with TFS in case there was any confusion about whether this is about deploying TFS or doing deployments with TFS. In Part 1: The Deployment Process Should Enforce Good Configuration Management Practices, I gave some background on my experiences and how the configuration management process has evolved and some rules and benefits to the automated deployment MSIs. In this Part, I will walk through the steps to create an automated deployment MSI in Visual Studio 2008 satisfying the rules from Part 1. In this example I will build the MSI for a windows service that will auto assign the username and password. The first few steps are standard steps for building the MSI. Then the steps get more interesting when it starts getting into to the automated deployment settings. Step 1: Add the Setup Project to existing solution To add the setup project to the solution, choose “Add New Project” > Other Project Types > Setup Project. Step 2: Add Project Output to MSI Add the required files for the deployment by adding the project output of the primary project. To the project output, right click on the setup project in the solution explorer > View > Project Output. A dialog box similar to the one below will appear. Verify that the windows service project is the selected project in the combo box. Choose Primary Output and click OK. Step 3: Add Custom Actions Next add the Primary output as a Custom action for the install, uninstall, etc. To do this, right click on the Custom Actions > Add Custom Action > Application Folder > Primary Output from <your project>. Step 4: Add Installer to Windows Service project In the Windows Service project, add an Installer class by double clicking on the Service component to view the designer. In the Properties window (usually) at bottom right corner, there will be a link to “Add Installer” similar to the image below. This creates the project installer class containing the service installer and the process installer. We will be modifying these in some later steps. Step 5: Create the environment config files and folders in the windows service and add them to the MSI. If the solution had multiple projects, I usually create a separate project for the config files. Here I will create the folders in the same project. Create the folders and files as shown below. Basically environment’s config file will be stored here and checked into source control. To add these to the MSI, go to the properties of each config file and change the Build Action to Content. Now go back to the MSI, right click on the project > Add > Project Output > Content Files to add these. Step 6: Create Custom Action to copy the selected config file to the application folder Now that environment configs are in the ConfigFiles folder, the selected one needs to be copied to Application folder. To do this we need to create a custom action. This is in VBScript but eventually I want to create these custom actions as a helper class in Team Deploy. To create the custom task, the actual file needs to be created outside the MSI. I have created a CustomActions folder in the windows service project. In there I added a copyconfig.vbs file. This custom action is going to need two values passed into it. One is the environment and the other is TargetDir. I couldn’t figure out a way to get current folder inside for the vbscript so I found it easier to just pass it in. To pass in values into the custom action the name/value pairs are passed into the CustomActionData property. Also since this is going to overwrite the current app.config files, exclude the app.config by clicking on the Primary Output > Exclude > Add for *.config. Here is the code for the copyconfig.vbs file. After you copy and paste this into the vbs file. Save it and in the properties, change the Build Action to None. We do not want this copied to the MSI output like the config files. on error resume next dim paramsList paramsList = split(session.property("CustomActionData"), ",") dim param1 dim param2 param1 = paramsList(0) param2 = paramsList(1) dim filesys dim path path = param2 & "configfiles\" & param1 & "\" dim strEvn, objFile, strLogFile Set objShell = CreateObject("Wscript.Shell") strEnv = objShell.ExpandEnvironmentStrings("%temp%") strLogFile = strEnv & "\MSIInstallLog.txt" Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(strLogFile, 8, True) objFSO.CopyFile path & "*.config", param2, true if err.number > 0 then objFile.WriteLine Now & "::CopyConfigs - " & param1 & err.Description else objFile.WriteLine Now & "::CopyConfigs - Completed Successfully." end if objFile.Close Now add the Custom Action to the MSI by right clicking on the project > View > Custom Actions. We only want this to run during the installation process, so right click on Install > Add Custom Action > Application Folder > Add File > Browse to Copyconfig.vbs and click OK. Notice in the setup project that the copyconfig.vbs has the no sign icon on it so it isn’t copied to the application folder. Next we need to pass in the the values into the Custom Action. Click on the Copyconfig.vbs in the Custom Actions view. In the properties window, set CustomActionData = [ENV],[TARGETDIR]. Repeat the steps above for AssignService.vbs. Set CustomActionData = [USR],[PWD],"SampleService" on error resume next dim param param = split(session.property("CustomActionData"), ",") if len(param(0)) > 0 then dim strEvn, objFile, strLogFile Set objShell = CreateObject("Wscript.Shell") strEnv = objShell.ExpandEnvironmentStrings("%temp%") strLogFile = strEnv & "\MSIInstallLog.txt" Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(strLogFile, 8, True) ' ------ SCRIPT CONFIGURATION ------ strUser = param(0) strPassword = param(1) strSvcName = cstr(replace(param(2), chr(34), "")) strComputer = "." ' ------ END CONFIGURATION --------- set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") set objService = objWMI.Get("Win32_Service.Name='" & strSvcName & "'") intRC = objService.Change(,,,,,,strUser,strPassword) if intRC > 0 then objFile.WriteLine Now & "::" & strSvcName & " - " & "Error setting service account: " & intRC else objFile.WriteLine Now & "::" & strSvcName & " - " & "Successfully set service account" end if if err.number > 0 then objFile.WriteLine Now & "::" & strSvcName & " - " & err.Description end if objFile.Close end if This custom action finds the “SampleService” and changes the username and password. I had to use the service name literal. There wasn’t anything I could find where I could use a dynamic value. Step 7: Modify Project Installer to handle interactive and silent modes One of the requirements is that the MSI needs to work when using the wizard and when specifying parameters when installing from the command line or remote utility. Therefore when the user is installing the MSI through the wizard (we will create this in the next step) it needs to prompt for the user and password. This is accomplished by setting the service account of the installer to LocalSystem so it won’t prompt but if the username isn’t passed in it switches the service account to User. This will then prompt the user. To implement this, add the following code to the ProjectInstaller. private string GetContextParameter(string key) { string sValue = ""; try { sValue = this.Context.Parameters[key].ToString(); } catch { sValue = ""; } return sValue; } // Override the 'OnBeforeInstall' method. protected override void OnBeforeInstall(IDictionary savedState) { try { base.OnBeforeInstall(savedState); string username = GetContextParameter("usr").Trim(); if (username == "") { serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User; } } catch(Exception e) { } } private string getvalues() { string all = ""; foreach (DictionaryEntry value in this.Context.Parameters) { all += value.Value.ToString() + ","; } return all; } Step 8: Add step to wizard to specify the Environment. In addition to prompting the user for the user and password, the MSI needs to prompt the user for the environment. To add a form to the Wizard. Right click on the setup project > View > User Interface. Then right click on Start (as shown) and the click Add Dialog. In this example we have 3 environment, so choose the RadioButtons (3 Buttons) and press Ok. The Dialog window appears below the Confirm Installation box. If you build the setup project you will notice the warning, “All custom dialogs must precede the 'Installation Folder' dialog”. Therefore, click on the up arrow twice to move the RadioButton dialog window above the Installation folder. Now click on the dialog and view the Properties window. There are several empty properties we need to set. Set the following to something similar to these values: - BannerText = “Choose Environment”
- BodyText = “Please select an environment from the list.”
- Button1Label = “Production”
- Button1Value = “Prod”
- Button2Label = “Test”
- Button2Value “Test”
- Button3Labal = “Development”
- Button3Value = “Dev”
- ButtonProperty = “Env”
- DefaultValue = “Prod”
Step 9: Change build type to loose uncompressed files The last step is to change the Package Files option under the setup project’s properties from “In setup file” to “As loose uncompressed files. You will need to do this for each configuration in the project.  These are all of the steps. I hope it helps. Attached below is the sample solution with the setup project hosted on the MSDN Code Gallery. You may use this however you would like. Now that you know how to build the MSI, it is time to deploy it. I will walk through that in the next post. Sample Automated Deployment Solution for building a Windows Service MSI (22k) The other future parts in the series will include: - Building and Deploying ClickOnce applications
- Deploying a web application.
- Hopefully more! Let me know what you would like to see.
Mike
I just received my new Google Voice number. One of the cool features is creating a “Call me” widget. Here’s the link for you to call me. If you have any questions about VSTS or TFS including information about our Team System and Team Foundation Server 2008 Jumpstart program or if you just want to say “hi”, click on the link below. Depending on the amount of SPAM and solicitors, this may be directed to voice mail so please leave a message and I will call you back. Also, feel free to contact us through normal methods on our website at http://www.deliveron.com. Mike
Build automation and more specifically deployments are one of my favorite things to do with Team Build in Team Foundation Server 2008. Deployments are not an “out of the box” feature but there are several ways to accomplish this. I am going to cover some of these different approaches and strategies for doing deployments with TFS. Before I get into doing the actual deployments, I want to give a some background and guidance behind why creating automated deployments are part of a good software configuration management (SCM) process. Then I will go into creating a MSI that supports automated deployments. The subsequent posts will cover a variety of topics including deploying the MSIs with Team Deploy and deploying Click Once applications. Lastly I will explore what automated deployments will look like in TFS 2010. As always, if you have any questions or if there is something you want me to see, send me an email, tweet, or comment. This deployment process has been an evolution of the past 3 years. I began getting engaged in this process when I used to be part of a process where the development team created a MSI for test and a couple weeks before production our PC configuration team would create a new MSI with their tools. We would do some testing of this MSI over those couple weeks before going to production. Unfortunately this process led to a few mistakes, mostly due to the fact we were changing too much too late in the game. We began to think of an improved process with better configuration management in mind. We created a few rules to that we wanted our new process to follow. Rules for MSIs - Create the MSI early in the development process – As early as a development team has most of the projects for the deployment created, compile the assemblies and create the MSI. For Agile teams this can be as early as Iteration 1.
- Create a MSI that is easily updated – MSBuild and Team Build by default do not support building setup projects. There are some workarounds to being able to build a MSI, but I prefer creating the MSI and choose “As loose, uncompressed files” for the build in the setup project properties. This will leave the files out of the MSI and basically add pointers to the files in the MSI. This makes updating the MSI as easy as using the copy task. If a new project is added to the solution, add the new dependency, rebuild the MSI, and add the new assembly to the copy process (more on this later)
- Config files – This could probably be a post by itself. Basically there are a couple rules I have about config files.
- The config files for all of the environments must be checked in to source control. Usually I will create a library project in the solution and add all of the config files to it.
- Along with all of the files being in source control, there can be no editing or copying of config files once the application is deployed. For too long I would always copy the config file from the installed location. Then I would do the uninstall, reinstall, and then copy/modify the config file based on the one I copied to another file. I did this because I didn’t know if there were changes or particular production settings that were not in the MSI.
- Lastly the MSI should contain all of the config files for all of the environments. These can be removed after the installation process is done but the key is that the config files are not copied from another location. This will become more clear when I start to walk through the process.
- Because the MSI contains the config files for multiple environments, the user must be able to select the appropriate environment to install. The MSI should allow the the user to specify the environment in the wizard or through a command line argument when installing it in quiet mode.
- If the MSI is a windows service, the user must also be able to specify the username and password through the wizard or command line.
By following these rules, it provides the following enhancements - Tested and Proven MSI – Just like we shouldn’t deploy code that we haven’t tested, the same is true for the deployment process. By using the same MSI in the Test environment, throughout the development cycle, and in production, this will help ensure that that are no surprises when deploying to production.
- Ready for Automated Deployments – The MSI will include key features that are required for use in automated deployments. These include the config files for multiple environments, easily updateable from Team Build, and supports passing environment and username/password by command line.
In the next part, I will go over the steps and processes for creating a MSI to support these rules and help enforce your configuration management process. I will demonstrate how to do all of this within Visual Studio without using any 3rd party tools. Mike
This week I was informed my presentation, “An Iteration in the Life of an Agile Team with Team System 2010” was added to the schedule at the Heartland Developer Conference 2009. I am excited to be presenting at this event that usually sells out around 600 attendees. It is going to be huge. There are a lot of great speakers and topics. Scott Guthrie is one of the keynote speakers! My session is October 16th at 2:00pm. I am looking forward to this session that will be a unique, real world way of demonstrating some of the new features of Team System 2010. Presentation Summary This presentation will demonstrate a complete two week scrum iteration from the planning meeting to development, testing, and bug fixing to deployment utilizing the features found in Team System 2010. New features include gated check-ins for Continuous Integration (CI), Test-Driven Development (TDD), Product Backlog enhancements including hierarchical views and support for multiple teams to work from a single backlog. The presentation also demonstrates the enhancements to the TFS Portal and Web Access to support Agile planning and displaying graphs such as burn-down charts. Each walk through includes a live demonstration of the feature in Visual Studio Team System 2010. I hope to see everyone there!  Mike
In many of my projects I will create a new release branch when our code is ready for production. This gives me a snapshot of the code when it went to production. This allows us to make any bug fixes in the production code base but continue adding new features to dev and test branches. This has always been a manual step to create the branch until i was talking to a client and suggested that I could automate this process. I hadn’t done a branch from within Team Build but I knew it could be done via the command line so I figured we could automate it. I used the Exec task to create the branch like this: <Exec WorkingDirectory="$(SolutionRoot)" Command="$(TF) branch $/MyTeamProject/Main/ $/MyTeamProject/Releases/2.1.0.0 /noget" Next the build needed to check in the branch: <Exec WorkingDirectory="$(SolutionRoot)" Command="$(TF) checkin /comment:"***NO_CI***New Release Created" /noprompt /override:"New Release Created" /recursive" IgnoreExitCode="true" /> This was the easy part. One of the challenging parts was the workspace mappings. Even though I could get this to work by creating a mapping at the root of the team project, I didn’t want to pull down all of the branches under source control. If I didn’t have the mappings at a high enough level to cover the target, the build will generate an error like this: No appropriate mapping exists for $/MyTeamProject/Releases/2.1.0.0 Since with each release this problem would compound, I wanted to only pull down the necessary source control. To solve this problem I created a custom task that takes a parent folder, in this case $/MyTeamProject/Releases/ and either cloaks all of the subfolders to only add a new row, or it will cloak all of the folders except for the one specified. The second option is beneficial if the source folder for the branch is dynamic also. This will also create a dynamic mapping between the WorkspaceServerItem and WorkspaceLocalItem. The task is called CreateDynamicMapping and here is the call: <CreateDynamicMapping TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" WorkspaceServerItem="$/MyTeamProject/Releases/" WorkspaceLocalItem="$(SolutionRoot)\Releases" WorkspaceName="$(WorkspaceName)" WorkspaceOwner="$(WorkspaceOwner)" ParentFolder="$/MyTeamProject/Releases/" </CreateDynamicMapping> This example uses the ParentFolder to get all of the child folders, loops through each of them and if it finds a match to the WorkspaceServerItem (It won’t in this example because it isn’t a child folder of the ParentFolder) it will keep that folder, otherwise it cloaks the folder so it is not pulled down. Creating this task was my first opportunity to use the TFS API. With the help of some great posts by Shai Raiten, this ended up straight forward and even wrapped some unit tests around make sure it worked. Here’s the main part of the code for the task: TeamFoundationServer tfs = new TeamFoundationServer(teamFoundationServerUrl); // Get a reference to Version Control. VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer)); Workspace[] workspaces = versionControl.QueryWorkspaces(workspaceName, workspaceOwner, null); if (!parentFolder.Contains("*.*")) { parentFolder += "/*.*"; parentFolder = parentFolder.Replace("//", "/"); } RecursionType recursion = RecursionType.OneLevel; ItemSet itemSet = versionControl.GetItems(parentFolder, recursion); foreach (Item item in itemSet.Items) { if (workspaceServerItem.ToUpper() != item.ServerItem.ToUpper()) { workspaces[0].Cloak(item.ServerItem); } } workspaces[0].CreateMapping(new WorkingFolder(workspaceServerItem, workspaceLocalItem)); This is what you need to automate the branching process from with a TFS Build. I didn’t talk about how to get your version number to branch to. This will depend on your projects requirements. You may want to use get the assembly version of one of the assemblies you compiled to use this as the folder or in this instance the source folder was dynamic too. Mike
Today I was installing Team Foundation Server 2008 on a Windows Server 2008 server where I installed WSS 3.0 SP2 when I realized I was going to get error connecting to an existing Windows SharePoint Services server. The error is TF220037: The Windows SharePoint Services administration site could not be found at the following location: http://myserver:17012
Basically this error means that it can’t find the WSS Central Administration site. Usually when I see this error it means that the WSS Central Administration site is installed on a different port. The easiest way I have found to get the correct port number is to open the Central Administration site and look at the port in the URL. In my example below the correct port is 21810. I simply updated the port on the installation screen on the left and it worked fine.
To open Central Administration, go to Start > Administrative Tools > Central Administration.

That’s it! I hope it helps.
Mike
Thanks everyone for attending the meeting on Tuesday. It was a great time. I thought the attendance was good, especially for the day after a holiday and there were a lot of great questions asked. I hope everyone picked up some good tips that will help them implement Team System and Team Foundation Server. If you run into any problems feel free to contact me. I would be happy to try to help.
Here are the slides.
Installing_and_Configuring_Team_Foundation_Server_2008.zip (603.07 KB)
Mike
Team Foundation Server 2008 requires administrators to manage user and group permissions in three locations. Users must be added to the appropriate permissions in TFS, SharePoint, and SQL Server Reporting Services. Doing this manually is cumbersome. The TFS Admin Tool is a free add-on to Team Foundation Server that makes this process much easier. I was installing the latest version 1.4 on Windows Server 2008 and received the message “Please wait while the installer finishes determining your disk space requirements.” when I clicked on Next after the EULA. I had a hunch it was UAL and I needed to do “Run As Administrator” to make this work. Unfortunately with MSIs there is no “Run As Administrator” option in the context menu. To work around this I opened an “Administrator Command Prompt”. Here I ran MsiExec against the Msi and it worked fine. C:\Users\Administrator>msiexec /i c:\users\Administrator\Desktop\TFSAdminToolSetup.msi Mike
Last week I added a MSI for installing Team Deploy. I am excited about this because this simplifies the installation process. Simply run the MSI and it installs all of the components for Team Deploy. Team Deploy still requires the separate download and installation of PSTools. Also, if you have an older version of PSTools, download the latest version to help ensure it works with the latest version of Team Deploy. Here is the listing of installed files with the MSI. I have also included a “real world” type deploy script and TFSBuild.proj file based on some great feedback I have received. These should show some good examples of how to use it. As always you can find Team Deploy at http://teamdeploy.codeplex.com. Mike
I am excited to announce that I am going to be presenting at the next Omaha Team System User Group meeting on May 26th, 2009. In addition to what I think is a great topic that I am looking forward to presenting, Deliveron Consulting Services is co-sponsoring the meeting and giving away an XBOX 360, a NFM gift card, and two TFS books! WOW! I look forward to seeing everyone there.
Here’s the information on the presentation:
Installing and Configuring Team Foundation Server 2008
This presentation provides an overview of TFS 2008 and demonstrates best practices, lessons learned, and “gotchas” installing and configuring TFS 2008. The overview explains the architecture and components of Team Foundation Server 2008 and recommended server configurations. The demonstrations will include using the Best Practice Analyzer, Setting User Permissions and using the TFS Admin Tool, and creating and configuring a Team Project from start to finish. The configuration process will include recommended settings, source control folder structure, and creating appropriate notification. The presentation will conclude with techniques and lessons learned for troubleshooting problems with installations.
About me
Mike Douglas is a Solution Consultant at Deliveron Consulting Services where he provides end-to-end solutions and TFS installation, configuration, and custom development for clients. He has over 11 years experience building enterprise level applications on a variety of .NET technologies including WCF, Web Services, ASP.NET, Disconnected Smart Clients and Data Synchronization, BizTalk, and Team Foundation Server. Mike enjoys trying to keep up with the constant change and evolution of .NET. Mike is an experienced presenter having spoken at several Omaha .NET User Group meetings on CSLA.NET, Subsonic, and TFS. He also spoke at the 2008 ESRI International User Conference on a GIS integration project he helped lead. Mike actively maintains the open source project, Team Deploy, on CodePlex for deploying MSIs using Team Foundation Server. Mike also enjoys sharing his experiences in Code Generation, CSLA.NET, and TFS on his blog at www.CodeSmartNotHard.com.
Date and Location
May 26th, 2009
Farm Credit Services of America 5015 S 118th St Omaha, NE 68137
For more information and to register, visit the Omaha Team System User Group site.
Today I am excited to announce the release of Team Deploy 2.0. Additionally, the total download count of Team Deploy has passed 1000 downloads!
Team Deploy is an open source package of custom build tasks designed for Team Foundation Server 2008 for deploying MSIs to clients and/or servers. There is also a build notification task for lava lamps or street lights with your builds.
The enhancements and fixes for 2.0 include:
Added TaskBase class for common functionality for example,BuildUri and TeamFoundationServerURL. These properties are now optional. It will basically skip the build step display if these properties are not set. All tasks inherit TaskBase.
Added check to "StopService" so it only does it if the service exists and it "canstop". (bug)
Added new RemoteExecute task. Now call any executable on target machines. This also has a WaitForExit property to be able to wait for the response or not from the target machine.
Added setup MSI to install Team Deploy instead of manual steps.
Added IgnoreExitCode attribute to the base class. If the task checks for exit code it now will log it as an error if the code > 0 unless IgnoreExitCode == true.
Fixed a problem where with the new version of pstools, it wouldn't work unless session zero is specified.
Updated the deploy task to ignoreexitcode when calling the Kill task
Added logic to stopservice to not try to stop if it isn't installed or started.
Future updates to Team Deploy will include breaking out the build light notification portion to a new CodePlex project I created called TFSBuildLight. Also 2.x versions will continue to be for Team Foundation Server 2008. New 3.x versions of Team Deploy will be developed for Team Foundation Server 2010.
Team Deploy is a free to download and use. You can find it at http://teamdeploy.codeplex.com.
I wanted to take a look at writing SQL Reports for TFS. I was going to install the Business Intelligence Studio for SQL Server 2005 but I thought it would be better to use the latest edition of SQL Reporting Services in SQL Server 2008. So I decided to upgrade my TFS Test Server to SQL Server 2008. This is a single server install of TFS. I ran the SQL Server 2008 Upgrade Wizard. Most of the steps were straight-forward. I only ran into one roadblock that I was able to fix and I documented below. Here’s the steps.
First I chose the “Upgrade from SQL Server 2000 or SQL Server 2005” option.
I kept the default settings for all of the steps except when it asked what instance I would like to upgrade.
All of the checks passed but one. I got the following error.
Rule "Security Group SID (Security Identifier)" failed.
http://go.microsoft.com/fwlink/?LinkId=94001
I went to the link but it didn’t help. I searched on the web for for the error and I found the fix here. Basically I had to manually replace the invalid SIDs with the new one.
To find the correct SIDs, I ran the command prompt utility: whoami /groups
If you have multiple editions of SQL Server installed make sure you are in the correct one in the registry. Look at the Edition key
I pasted the correct SIDs into the registry keys
I fixed the ones in MSSQL.2 but I was still getting the error. I checked the log file %ProgramFiles%\Microsoft SQL Server\100\Setup Bootstrap\LOG\Detail.txt and here is the error.
2009-04-14 23:24:25 Slp: Sco: Attempting to open registry subkey SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.3\Setup 2009-04-14 23:24:25 Slp: SqlSidRule.GetSidValue - reading value name ASGroup 2009-04-14 23:24:25 Slp: Sco: Attempting to get registry value ASGroup 2009-04-14 23:24:25 Slp: Sco: Attempting to get account from sid S-1-5-21-3621347759-1475631895-1437307089-1014 2009-04-14 23:24:25 Slp: Sco: LookupAccountSid failed for SID S-1-5-21-3621347759-1475631895-1437307089-1014 2009-04-14 23:24:25 Slp: SqlSidRule.EnsureGroupExists - Exception caught and ignored. Returning false. Exception message is No mapping between account names and security IDs was done.
I grabbed the SID for the ASUser and it worked!
The wizard continued and finished. I launched Visual Studio and TFS is working properly.
Now I can look at the SQL Reporting :)
Why use a virtual machine for development?
There are a couple things I like about doing development on a virtual. One of the best features is creating the image once and then being able to have the other developers use the same image. This is a big time saver and ensures consistency across the developers. In addition to having all of the developers use the same image, this also allows us to have separate images for each of our clients. This obviously allows us to keep our clients data and code separate and helps prevent 3rd party controls from conflicting.
Performance
Defrag. Defrag. Defrag. This is must whether you are using a virtual machine or physical only. I have a created a scheduled task to defrag my machine every day. Here are some steps for creating the scheduled defrag. I do it daily because the more often it runs the quicker it will complete. Newer PCs with Intel processors have a virtualization bios setting that is turned off by default. This is supposed to help virtualization performance. When I enabled it on my laptop, it caused my machine to temporarily quit responding. I ended up turning it back off. I recommend enabling it and trying it. The other option to consider is where to save the virtual disk. My laptop has a 7200rpm hard drive and I have a 5400rpm USB Buffalo external drive. I thought the virtual would run better from my local drive but since that is the drive with my swap file and the OS, the virtual image runs faster from my external drive. Both USB 2.0 and Firewire (400) are half duplex so technically data can’t transfer both directions at the same time on the USB. Firewire 800 does support full duplex. If your computer supports this, eSata, or has a second hard drive, I recommend using one of the first, USB 2.0 second, and the C: drive last.
Configuring for Team Foundation Server 2008
When creating your base image, install of of the required software. For TFS, this includes VSTS 2008 (any edition), Team Explorer, and SP1. Do not connect to the TFS Server. TFS will automatically create a workspace for your machine that is not needed. TFS workspaces use the machine and user as the key for unique workspaces. The workspace displays the machine name but uses the machine’s SID (basically a machine GUID). Each copy of the base image that is created, needs to have the machine name and SID changed. The official way to do this is to use SysPrep. I found a handy utility by SysInternals (owned by Microsoft) that can do it called NewSID. there is a disclaimer on the website stating that it isn’t officially supported by Microsoft but I have been using with XP and Windows 2003. I haven’t run into any problems. It is a simple wizard that allows you to enter the new machine name and it creates a new SID. After the reboot it is ready to go.
If you make a copy of a machine that has already been connected to TFS, even after updating the machine name and SID you could still get the error message “The workspace “USER;MACHINENAME” already exists on computer MACHINENAME. TFS caches this information on the machine. To update the cache run use the Visual Studio Command Prompt and run
tf workspaces /updateUserName:USERNAME/s:http://tfsserver:8080
Run this for both the original user and the new user of the machine. This should clear the cache and allow you to create a workspace to the same folder as before.
I hope this helps.
-Mike
I created a nightly build to run my data driven unit tests. When my build finished it was only partially successfully. I looked at the unit tests and they were all passing yet there was an error on the testing step. When I looked in the log below is the message I saw. I thought this was a little confusing because there was only a warning. I wasn’t sure what caused the TestToolsTask to fail. I first thought it was a permission or some other issue when it was trying to publish but the results did publish. Next I looked at the warning VSP1030 message. Then I remembered I enabled code coverage but the build configuration was set to Release. I changed the build to Debug and everything worked! Before I figured out the issue I tried searching the web but I didn’t find any solutions. I hope this helps. Summary ------- Test Run Warning. Passed 6 --------- Total 6 Results file: t:\builds\MyTeamProject\Nightly Build\TestResults\builduser_MYSERVER_2009-03-25 23_56_46_Any CPU_Release.trx Run Configuration: Local Test Run Run has the following issue(s): Instrumentation error while processing file BusinessObjects.dll: TESTTOOLSTASK : warning VSP1030: Invalid, mismatched, or no PDB file was found for t:\builds\MyTeamProject\Nightly Build\Binaries\Release\BusinessObjects.dll. The previous error was converted to a warning because the task was called with ContinueOnError=true. Waiting to publish... Publishing results of test run builduser@MYSERVER 2009-03-25 23:56:46_Any CPU_Release to http://tfsserver:8080/Build/v1.0/PublishTestResultsBuildService2.asmx... ....Publish completed successfully. The command exited with code -1. Build continuing because "ContinueOnError" on the task "TestToolsTask" is set to "true". Done executing task "TestToolsTask" -- FAILED. Mike
Today my employer, Deliveron Consulting Services, was awarded the Microsoft Gold Certified Partner Status. This certification is recognition of the level quality and talent we hold. I am excited to be part of this rapidly growing company. 
I was installing Team Foundation Server on virtual server for some testing. The last install I did went flawless. A quick and painless install is always appreciated but there is something that feels victorious about successfully troubleshooting the install and getting it to work properly. In this case I ran into two errors. Also here's some general troubleshooting information that I found useful in identifying the issues. General Troubleshooting When troubleshooting installation errors for Team Foundation Server there are a couple places that can provide useful information. First is obviously the message box. It will usually have something about the error to get started. If you close the error, you can still usually find the message in the Application Event Log. There may also be additional errors in the event log that can help. If you need more information on the error, you can look in the Local Settings\Temp folder for the current user (C:\Documents and Settings\<user>\Local Settings\Temp). There are three files that I find the most useful. - VSMsiLogxxxx.txt - Detailed installation steps of MSI and where it failed.
- dd_error_vstf_at_90.txt - Lists the error message for each installation attempt.
- dd_install_vstf_at_90.txt - Detailed steps of the installation steps.
Error 28002. An unknown error occurred. The first error I didn't find the solution that fixed this issue. There were a lot of suggestions and I might have missed it. After trying a couple of the suggestions, I remembered that I had Team Explorer with SP1 already installed. I uninstalled this and it fixed the issue. Error 28805. The setup program cannot complete the request to the server that is running SQL Server Reporting Services. I had better luck with this error. I found a good post on the MSDN forums with the answer. There were several suggestions that I tried. Deleting of the encryption keys in the SQL Reporting Configuration Tool fixed it and I was able to continue the install and complete it successfully. To delete this run the Reporting Services Configuration tool. Click on Encryption Keys on the left tool bar. Then click on Delete to delete the keys. You should see a message similar to the one below. Good luck and may all of your TFS installations be successful. Mike
I have read and seen a lot about the TFS Power Tools and I am finally getting a chance to install them and try them out. The first tool I wanted to try was the Best Practices Analyzer. The term Best Practices is rather vague so I didn't know what to expect in its findings. To my surprise, this tool not only tested configuration and server requirement best practices, it also can do pre-requisite checks on servers before you install and it will also check for errors after you install TFS. I have a virtual machine with TFS that I use for some prototyping. I knew my virtual machine had a couple problems but the scan resulted in those and some additional ones I would have never known about. Here's the results of the scan.
I noticed that this database was SUSPECT before I ran the scan. I expanded it to display the details. Not only does it show the details of the issue but you can also click on the the like to tell you more about the issue and how to resolved it. I tried fixing this before through SQL Management Studio and the only I option I had was to restore from backup. I was curious to see if it had any ideas. When I clicked on the the link the explanation only talked about about single user mode and when the database is not online. Unfortunately there was no magic answer for my problem on this one. The other resolutions proved to be more useful. Those solutions pertained to my issues. Here's an example of the resolution
As you have seen this along with the other great tools including the Process Template editor, Build Notification Tool, TFS Users tool, etc is a must to download and utilize for your implementation of Team Foundation Server. View and download the Visual Studio Team System 2008 Team Foundation Server Power Tools Mike
Doing builds and running unit tests after every check-in has become a standard practice in Agile and non-Agile development teams. Continuous Integration is the term that describes this process and helps ensure that that nothing has been broken since the last check-in. One area that is sometimes overlooked is the code generation. Continuous Generation, the re-generating of code / stored procedures for every check-in and build, should be considered for your TFS builds. I believe there is a lot of benefit to generating the code with every build. There are several benefits:
- Table schema and stored procedure parameters can change. How do you know that your generated objects are up to date and match the database?
- It keeps everyone honest so they don’t break the golden rule of never editing generated code. If the build is going to re-generate the code there’s no way to sneak the semicolon or curly bracket that you manually fix each time after generation.
- Sometimes we generate just the class we are working on and keep the rest checked in so it doesn’t overwrite the current object. If any changes are made to the template only this new class will have them. The other classes will be based on the older version.
- It gives more credibility to the generation process. There is sometimes a feeling of nervousness when generating all of the objects. Since generated code is never edited, you can generate the code as often as you wish.
CodeSmith Tools is the code generation tool that we use. It offers an easy way to accomplish this from your Team Foundation Builds. With version 3.2 and newer there is a custom build task included with the Professional edition. Here is the online help with some information about it.
There are a couple things to consider. The generated classes will be checked-in to source control. You will need to check them out before you call the task and then check them back in afterwards. Also, the user guide instructions do not work quite right in the link above. The guide explains how to use it within your visual studio project. However, the task needs to be called from Team Build. Here’s the basic steps and changes for your CI tfsbuild.proj file.
Step 1: Install CodeSmith Professional on your TFS build server. This will install the MSBuild task and Targets file. I contacted CodeSmith Tool’s sales department and this does require an additional license for the server.
Step 2: Import the CodeSmith Targets file. Add the following line just below the import element below the <!-- Do not edit this --> comment.
<Import Project="$(MSBuildExtensionsPath)\CodeSmith\CodeSmith.targets" />
Step 3: Add TF property in the PropertyGroup element specifying the tf.exe location to be used throughout the process.
<PropertyGroup> <TF>"$(TeamBuildRefPath)\..\tf.exe"</TF> </PropertyGroup>
Step 4: Override the AfterGet target to check out the generated file(s). This must be called before the CodeSmith task or it will return an access denied error. This example demonstrates one file but you can use a subfolder or naming prefix for the generated files and recursively check out all of the necessary files.
<Target Name="AfterGet">
<Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild\"
Command="$(TF) checkout Measure.cs" />
Step 5: Call the CodeSmith task to execute the CodeSmith project(s) in your solution. This will also be called in the AfterGet target. Currently the example in the documentation incorrectly shows the CodeSmith task using the ProjectFile attribute. As the usage description shows, the attribute is actually ProjectFiles.
<CodeSmith ProjectFiles="$(SolutionRoot)\Main\TestCodeSmithMSBuild\Test.csp" />
Step 6: Override the AfterCompile target to check in the updated generated files. Fortunately TFS will only check in the file if there is a change. This is good because most of the time re-generating the code should generate the same thing each time. However, tf.exe returns a code of 1 instead of 0 and results in a partial success of the build. Use the IgnoreExitCode=”true” to ignore this. You could additionally update this to create a work item for any other return code. Here’s a post with a good example of this.
<Target Name="AfterCompile" Condition="'$(IsDesktopBuild)'!='true'">
<Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild"
IgnoreExitCode="true"
Command="$(TF) checkin /comment:"***NO_CI***Auto-Generate" /noprompt /override:"Auto Generate" measure.cs "/>
</Target>
Step 7: Undo the check out if the build fails by overriding the BeforeOnBuildBreak.
<Target Name="BeforeOnBuildBreak" Condition="'$(IsDesktopBuild)'!='true'">
<Exec WorkingDirectory="$(SolutionRoot)\Main\TestCodeSmithMSBuild"
Command="$(TF) undo /noprompt measure.cs"/>
</Target>
That is it. Enjoy!
Mike
A couple weeks ago I started a new and exciting chapter of my career. After 8 great years at Farm Credit Services of America as a developer and lead developer, I took a new job as a solution consultant with a small, yet proven and experienced consultanting company called Deliveron Consulting Services. I have no complaints about FCSAmerica and appreciate all of the oportunities that I received while I was there. It was a great place to work and leaving was one of the hardest decisions I have had to make. I'm going to miss working with all of the great people I have gotten to know. I felt this was the right opporturnity at the right time for me. I'm excited to leverage all of my experiences in Team Foundation Server, CSLA.NET, code generation, configuration management, Agile, Biztalk, etc along with the leadership skills in a new environment. In fact, I have already begun helping one of our clients convert a projects to TFS. I'm also utilizing Team Deploy to automate their build and deploy process. I am excited to work with more companies on implementing or improving their implementation of Team Foundation Server.
So this begins a new chapter and I am excited!
Mike
Last week I released some minor updates to Team Deploy. When you use Team Deploy to deploy your MSIs, it will update the build steps and show that it is deploying. The second feature will now write any non-zero return code to the build log. Before this, these return codes were being lost. In the next release of Team Deploy I will build upon this and allow you to pass in an XML file contain return codes. If they are an error, warning or information. For errors, I will make it so it will actually fail the build. Here's the release http://www.codeplex.com/teamdeployMike
Thanks to everyone that attended tonight's Omaha Team System User Group meeting. I thought it went very well. It was a good turnout and there were a lot of good questions asked.
Here are the slides from the presentation.
TFS_Build_Automation.zip (260.07 KB)
Mike
On May 27, 2008 I will be presenting on Build Automation with TFS at the Team System User Group meeting. This presentation will demonstrate how cool it is to automate the build process and have a little fun along the way by having your automated builds control street lights and lava lamps. I will cover the creation of automated builds, demonstrate how to create custom build tasks, and go over a Team Deploy custom task project for build automation
This month's meeting will be at:
Farm Credit Services of America 5015 S 118th St Omaha, NE 68137
Come and check it out!
Please RSVP to Jeff Bramwell if you plan on attending.
I'll post the slides after meeting.
Mike
The latest version of Team Deploy (0.7.0.2) now contains the Device Controller Task. This task allows your Team Foundation Server builds to call the x10 Firecracker to control lamps. http://www.x10.com/automation/firecracker.htm
See the Team Deploy website on CodePlex for all of the details and files. http://www.codeplex.com/TeamDeploy

Here's the street light we are using for our builds.
Build Smart Not Hard
Mike
Last night I just published my first CodePlex (or any open source project)! It is called Team Deploy. This is a collection of custom MSBUILD tasks for deploying applications from Team Foundation Server to a test PCs and servers. I developed this awhile ago for my work and several of our teams are using these extensively to do daily updates of our internally built applications. It has been very helpful for us for a number of reasons:
- Anyone on our team can kick off the Build and Deploy build type in TFS (Not just me doing the builds anymore!)
- We can use the same MSI to deploy to all are environments. Great for configuration management.
- The tasks available allow for killing processes, uninstalling MSIs, stopping/starting windows services, deleting files, and installing MSIs. See the CodePlex site for more details.
There is not a lot of magic in the background on these, the real magic is actually done with PSTools. PSTools is a collection of some really handy free utilities by sysinternals (that was bought by Microsoft). Even if you don't download and try Team Deploy, you should try out PSTools. Eventually it would be nice to replace the PSTools functionality and bake it into the tasks, but for now, it works fine.
Try it out and let me know if you have any suggestions. http://www.codeplex.com/teamdeploy
Deploy Smart Not Hard!
Mike
|