But it works on my PC!

The random thoughts of Richard Fennell on technology and software development

Creating a TFS Team Project Collection using Powershell

Grant Holiday posted on how to create a TPC using Powershell. However his post did not address how to set the SharePoint or Reporting Services parameters. His example used for the form

Dictionary<string, string> servicingTokens = new Dictionary<string, string>();
servicingTokens.Add("SharePointAction", "None"); // don't configure sharepoint
servicingTokens.Add("ReportingAction", "None"); // don't configure reporting services

So not much use if like ourselves you have your TFS integrated with the company wide SharePoint farm

Finding the Parameters (the hard way)

If you want configure SharePoint or Reporting Services it turns out there is not source of documentation for the process. So thanks then to Chris Sidi for telling me how to find out the required options. This is his process to find out what parameters a TPC needs to be created with:

  1. Create a TPC via the TFS Administration Console, specifying a custom configuration for Sharepoint and Reporting for your system.
  2. In the Administration Console at the bottom of the screen, switch to the Status tab. Double-click “Create Collection” to load the servicing log.
  3. In the first ~15 lines of the servicing log, find the JobId (e.g. “Setting token. Key: JobId. Value: 9638bd57-f494-4ac3-a073-dd1548ab24dc.”)
  4. Using Powershell, query the servicing tokens used:

[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$credProvider = new-object Microsoft.TeamFoundation.Client.UICredentialsProvider
#Update the TFS url as necessary
$tfsConnection = new-object Microsoft.TeamFoundation.Client.TfsConfigurationServer "
http://localhost:8080/tfs", $credProvider
$tfsConnection.EnsureAuthenticated()
$jobService = $tfsConnection.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamFoundationJobService])

# Replace the JobId. Use the one in the servicing log.
$jobId = '9638bd57-f494-4ac3-a073-dd1548ab24dc'
$servicingJob = $jobService.QueryJobs([Guid[]] @($jobId))[0]
$servicingJob.Data.ServicingTokens.KeyValueOfStringString

This script gets the list of parameters as shown below which we can pass into the PowerShell script used to create a new  TPC.

SharePointAction UseExistingSite
SharePointServer 3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==
SharePointSitePath sites/test
ReportingAction CreateFolder
ReportServer 3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==
ReportFolder /TfsReports/test

It is shame the SharePoint and Reporting Services servers are returned as hash codes not their URLs, but as these will probably be fixed for any TFS implementation this is not a major issue as they can just be hardcoded.

Finding the Parameters (the easy way)

Once I ran this script I actually noticed that I already had access to this information without running  PowerShell or creating any trial TPCs. Isn’t that so often the case the information is under your nose but you don’t recognise it.

Actually all the parameters are actually shown at the start of the creation log for any TPC creation on a given TFS server. Just look for the log files via the TFS admin console.

[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational] Creating dictionary with 14 initial tokens:
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     FinalHostState => Started
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     VMM_SHARES (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     VMM_HOSTS (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     INT_USRACC (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointAction => UseExistingSite
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointServer => 3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointSitePath => sites/test
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportingAction => CreateFolder
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportServer => 3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportFolder => /TfsReports/test
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     DataTierConnectionString => Data Source=sqlserver;Initial Catalog=Tfs_Configuration;Integrated Security=True
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     CollectionName => test
[Info   @11:12:34.876] [2011-05-04 20:32:37Z][Informational]     InstanceId => 0cf30e1d-d8a6-4265-a854-9f6c5d288f7e
[Info   @11:12:34.876] [2011-05-04 20:32:37Z][Informational]     DefaultDatabase => Data Source=sqlserver;Initial Catalog=Tfs_test;Integrated Security=True

The revised TPC creation script

So given this new set of parameters we can edit Grant’s script to pass in all the extra parameters as shown below


param(
    [string]$tpcName = $( throw "Missing: parameter tpcname"),
    [string]$serverUrl = http://localhost:8080/tfs/ ,
    [string]$sqlServer = "sqlserver" ,
    [string]$spBase = "sites", 
    [string]$spServer = "3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==", 
    [string]$rsBase = "TfsReports",
    [string]$rsServer = "3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==" )

Write-Host "Using the TPC with the following settings"
Write-Host "tpcName:   $tpcName"
Write-Host "serverUrl: $serverUrl"
Write-Host "sqlServer: $sqlServer"
Write-Host "spBase:    $spBase"
Write-Host "spServer:  $spServer"
Write-Host "rsBase:    $rsBase"
Write-Host "rsServer:  $rsServer"

# Load client OM assembly.
[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

# Get the server
$tfsServer = new-object Microsoft.TeamFoundation.Client.TfsConfigurationServer $serverUrl;

# Create the token set
$servicingTokens = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"

$spPath = $spBase +"/" +  $tpcName;
Write-Host "Sharepoint path is  $spPath"
$servicingTokens.Add("SharePointAction", "UseExistingSite");
$servicingTokens.Add("SharePointServer", $spServer);
$servicingTokens.Add("SharePointSitePath", $spPath);


$rsPath = "/" + $rsBase + "/" + $tpcName
Write-Host "Reporting Services path is  $rsPath"
$servicingTokens.Add("ReportingAction", "CreateFolder");
$servicingTokens.Add("ReportServer", $rsServer);
$servicingTokens.Add("ReportFolder", $rsPath);

# Create and run the job
$tpcSvc = $tfsServer.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamProjectCollectionService]);

$sqlString ="Server=$sqlServer;Integrated Security=SSPI;"
Write-Host "SQL connection string is  $sqlString "

$job = $tpcSvc.QueueCreateCollection(
    $tpcName,      # collection name.
    "",                  # description.
    $false,              # don't make this the default collection.
    "~/" + $tpcName + "/",   # virtual directory.
    "Started",           # State after creation.
    $servicingTokens,               # tokens for other services.
    $sqlString,       # The SQL instance to create the collection on. Specify SERVER\INSTANCE if not using default instance
    $null,               # null because the collection database doesn't already exist.
    $null)               # null because the collection database doesn't already exist.

Write-Host "Creating TPC (this could take a few minutes)"
$collection = $tpcSvc.WaitForCollectionServicingToComplete($job)
Write-Host "Compeleted"

If you get any errors from the script the best place to go is the TFS Admin console to look at the logs (the same ones you used to find the parameters). You should see the detailed create process log that gives normal TF errors as to why the process has failed; usually rights on SharePoint for Reporting Services from my experience.

Problems and workaround for the EMC Scrum for Team System Process Template

I have recently been looking at the EMC Scrum for Team Systems (SFTS) 3 Template for TFS 2010 with SharePoint 2010. The core of it works, and works well for Scrum based teams. If you have not used it before have a read of the getting started post to get a feel of what it can do.

However, there are some issues when you try to make use of SharePoint 2010 as opposed to SharePoint 2007. Hopefully you will find some of the adventures I have had enlightening

Installation

The first one is that the installation and configuration tools just ignore SP2010. This means when you try to create a team project using the process template you get the error:

“TF249033: The site template is not available for the locale identifier (LCID).” ”The site template name is: SCRUM.”

You have to manually download and install the SharePoint template WSP, as detail in this blog post. Once the WSP is deployed on your SharePoint 2010 farm you can create new team projects using the process template.

How it looks

There are problems with the way the site renders. The two major issues are the site actions drop down appears behind the main display area (red box in left screen shot), and on some page large blocks of CSS get rendered to the screen as opposed to being dealt with programmatically (right screen shot).

image image

Both of these issues have been reported on the support forum

My reading is that the current SFTS SharePoint template WSP has only had minimal changes to port it to SP2010 from SP2007, just enough to get it to load. I think the key issue here maybe that the SFTS SharePoint template has its own master page. This is something all TFS 2005/2008 templates tended to do, but for 2010 there has been a general move to inherit from core SharePoint master pages. Basically the master page structure needs to be rebuild from the ground up by EMC for fix all the issues, but we can address some of them…

Change the master page

Fixing all the issues in the master page is somewhat daunting as 2007 and 2010 master pages are very different in style. However, after a chat with one of our SharePoint developers it was suggested a better solution is to just tell the site just to use a different master page (one of the SP2010 standard ones). This is a technique we have used on bespoke site upgrades and usually will address most of the issues, then it is a matter of fixing the, hopefully smaller, list of outstanding problems.

So below is the process to make the change

  1. Install SharePoint Designer 2010 on a PC (this is a free download from Microsoft)
  2. Logging in as a user with admin rights on the site, open SP2010 Designer and open the url of the Scrum for Team System SharePoint Site e.g. http://tfsdemo/sites/DefaultCollection/team1
  3. In the site objects tree on the left select the master pages node
  4. You should see four master pages
  5. Right click on the v4.master and select ‘set as custom master page’
  6. Load the site in a browser and it should look like a more normal SP2010 site
  7. You can swap it back by making the SFTS.master the custom master page

image

Actually on first look the swapping the master page seems to have done the job on the homepage in default view mode without any other edits. However, there are still problem of stray CSS being shown when accessing the other pages, and a trace of green in some of the borders.

So a partial success, but with more work maybe a complete one? But that is not the route I took.

Report Title Click-through

Both the SFTS and standard Microsoft reports are displayed in dashboards the same way, they use a page view webpart and the TFSredirect.aspx page. This shows the report chart and a link to take you to its Reporting Services home when the title is clicked. The rendering of the report works for SFTS, but another reported problem is that when you click the report title links (highlighted in green in above graphic) you get the error

TF250008: This SharePoint site is not currently associated with a team project in Team Foundation Server. To ensure that this site functions correctly, you must configure a team project to refer data for that project to this site. For more information, see this topic on the Microsoft Web site: How to: Add a Team Project Portal. You can use the following querystring argument to specify a specific project: tf:ProjectId.

The error says a workaround is to pass the TF:ProjectID parameter in the title URL. This is the only solution I have found. To do this

  1. Load SQL Management Studio
  2. Open the tfs_defaultcollection DB (or the one for your tema project collection) and the tbl_projects table.
  3. Look for and copy the projectID for the project you want to report on
  4. Open the SharePoint page with the failing chart. Click the small down triangle in the top right of the webpart to get the webpart editor.
  5. In the advanced section add &TF%3aPROJECTID={guid} with your {GUID} to the end of the Title URL (the %3a is the : character)
  6. I also had to remove the &IsDashboard=false else I got a “An attempt was made to set a report parameter 'IsDashboard' that is not defined in this report. (rsUnknownReportParameter)” error.
  7. Press OK to save, the chart should render and the link work

Basically the title URL as automatically build is wrong, it has an extra parameter the report does not support and for some reason the automatically passed project ID is being lost. In fact even when you fix the Url is wrong as the report it points to is a dashboard summary when you probably want to take the user to a fuller version of the report. Which of course you could do by altering the Url provided.

I think the root problem here is that the webpart assumes that the report has a dashboard and full version mode, as many of the MSF agile ones do, so this sort of makes sense.If you reports are single mode you need to pass two Urls.

Again this editing is all a bit of pain, but you don’t do it too often, and you could also write a command line tool to easily get the GUID.

But maybe a better overall option?

However, whilst trying all this I realised that the SFTS created SharePoint site does not really do what much ‘special’. Beyond being a basic SharePoint site it has

  • a link to the process guidance, but is just an HTML file that redirects to http://www.scrumforteamsystem.com/processguidance/v3/ so can be added as link
  • a link to the Team Web Access, there is a standard webpart for this or you could just use a link
  • the front page dashboard, this has the two SFTS chart webparts and a TFS query webpart, but we can recreate this ourselves with the standard TFS webparts

Therefore I would suggest the best option to avoid all these SharePoint 2007/2010 issues is to manually create a new SharePoint site and add similar controls to those used by SFTS to make the SharePoint site you want. As long as you are not creating new team projects all the time this should not be too much of a problem.

The steps to do this are as follows:

  1. In Team Explorer create a new Team Project using STFS template but set it not to create a Sharepoint site (you can always use an existing SFTS Team project if you want in place of this step if it already exist)
  2. On the default collections SharePoint e.g http://tfsdemo/sites/DefaultCollection create a new site (site actions), give it a name e.g. ‘Team1’ so it’s URL is http://tfsdemo/sites/DefaultCollection/team1. You can select any site template, but the collaboration/team one would seem a good start, nice and generic
  3. In Team Explorer select the STFS created in step1 and right click, select team project settings | portal settings
  4. Check the enable tram project portal (if not already set) press the configure URL and enter the details of the site created in step 2, press OK to exit
  5. Check the ‘reports and dashboards refer to data for this team project’ checkbox and press OK.
  6. Return to the web site created in step 2, it is now wired to the correct team project

You can now add pages, links and webpart to the web site to build your portal. The most important are

  1. Adding the set of ‘Visual Studio Team Foundation Server Web Parts’ which provide items such a build list, work item list etc.They should all pickup the correct team project.
  2. The page viewer that allows redirections via the TFSRedirect.aspx page as detailed above

We can also link directly to the reporting services reports using the SQL Server reporting web part. As SFTS does not ship its reports as Excel workbooks we don’t have to consider Excel Services..

And finally

I hope this post has given you some ideas as to how to address the issues with SFTS 3.0 on SP2010, enough too keep you happy until there is a release of the template what fully supports SP2010.

How to use the TFS 2010 Community StyleCop Build Actvity (Addendum)

Recently I posted on How to use the TFS 2010 Community StyleCop Build Activity and I am sure it all sounded very awkward and complex, well it did to me.

The point I should have made is that you don’t have to follow this process every time you want to make use of the custom activity. As long as the build process template is the same between to builds you can just copy it, you only need to follow the method in the post the first time.

So assuming you have followed the process in my last post and want to add the same build process to another project, lets say in another Team Project Collection, you do the following

Get the files onto the build box
  1. In VS2010 open Source Control Explorer select your Team Project and map the BuildProcessTemplates folder to a location on your local disk.
  2. Create a new folder under the BuildProcessTemplates called Custom Assemblies
  3. In this new folder copy all the assemblies from the equivalent folder you created in my last post
  4. Into the BuildProcessTemplates copy the edited build process template that uses the custom activities, again from the equivalent folder in my last post
  5. From within Source Control Explorer add these new files and check the files into TFS.
  6. Open Team Explorer, right-click on Builds and select Manage Build Controllers
  7. Select the controller to configure, and then select Properties
  8. Set the Version control path to custom assemblies to the location just created under version control containing your added assemblies
  9. You might want to restart the build service, it should automatically pick up the changes, but I usually do a restart to make sure

Making use of the build

  1. Create a new build and set it up as normal.
  2. On the process tab press the new button and browse to find the newly added process template

image

Once this is done can now save the build and queue it and all should work.

So the 2nd, 3rd etc. uses of a custom activity are not too bad as the first, as long as you can keep your process templates generic.

Now I have three TFS build instances on my VM

A while ago I posted on my experiences running multiple instances of 2010 build service on a single VM. Well a couple more experiences as now one of my VM is running 3 instances.

Firstly it seems to work OK, you have to have the right build profile i.e. fairly low load but a need to support many Team Project Collections. This is not a solution for a highly loaded build environment. At Black Marble we run a TPC per client model and tend to have fair few projects on the go at any one time, so need plenty of build controllers. However, in general the builds are small, taking minutes not hours If we have a seriously long running build I would still create a dedicated build service VM.

So what have I learn since the last post

  • Set the agents working directory differently for each agent on the VM. You will probably be OK if you don’t, as the $(BuildAgenId) should differ, but life is easier of you know what is where. So I use $(SystemDrive\Build1, $(SystemDrive\Build2 etc. as opposed to the default $(SystemDrive\Build.

image

  • When you create the new service instance using the Sc.exe command line remember to make sure it starts automatically when the operating system is rebooted. Stupid mistake but I keep make it!

TF30162: Task &quot;UploadStructure&quot; from Group &quot;Classification&quot; failed

When trying to create a new Team Project on TFS2010 from a client PC I got the following error

Event Description: TF30162: Task "UploadStructure" from Group "Classification" failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException

Inner Exception Details:

Exception Message: TF205029: No catalog resource type exists with the following identifier: 41c8b6db-39ec-49db-9db8-0760e836bfbe. (type CatalogResourceTypeDoesNotExistException)

However if I did the create on the TFS console all was fine.

Turned out the problem was due to the caching done by Team Explorer in Visual Studio. Exiting the copy of VS2010 on the client and reloading it fixed the problem as the updated team process settings will cached locally.

TF255115 Access Denied when starting TFSAgent Service

Whist configuring a new TFS2010 server I got the error

TF255115: The following service did not start: TfsJobAgent. Cannot start service TfsJobAgent on computer '<COMPUTERNAME>'.

This was identical to the thread on MSDN and it turned out my problem was similar.

I was installing TFS onto drive D:\APPS, not the usual C:\PROGRAM FILE. The problem was the <COMPUTERNAME>\User group did not have the default Read & Execute, List Folder Contents and Read rights on the D:\APPS directory and sub directory, the right all users have on C:\PROGRAM FILES.

Once these rights were added the TFS configuration completed without issue.

By the way something else I noticed, you can only change the path TFS will install on if you set the check boxes to install all components (server, proxy build etc.) However, once the path is altered you can deselect any components you don’t want, at which point the path textbox become read only again, but you now have the path you wanted

PC Rebuild time – remembering how to mount a bitlockered VHD

When your PC reaches the point that MSI cannot connect to the Install Service you know it is time to repave the PC. This is the time to you have to try remember what you installed on the PC, your license codes and how you actually got things to work.

So going through this process this week all went OK until I tried to remember how I handled bitlockered VHDs.

My PC does not have a TPM chip, but I wanted to bitlocker as much of my data as possible. The process to do this was as follows:

  • I created an empty folder c:\projects
  • I opened Computer Manager, then Disk Management as an administrator.
  • Via the Actions menu I created a new VHD c:\VHDs\projects.vhd
  • This will be mounted by default onto a drive letter, I changed this to mount it on a path (the one I created in step 1)

image

  • Then via the Disk Management tool I created a partition and then formatted the new disk.
  • I could then go onto the new disk by changing to the C:\Projects directory
  • I now needed to bitlocker the new VHD drive. This is done via the Control Panel | loaded the Bitlocker Drive Encryption

image

  • As I had no TPM chip I have to encrypt the drive with a password.
  • So when this finishes I have my C:\Projects directory this is a mount point for the bitlockered VHD

But I did not want to go into disk management each time I booted to attach the drive; but I did not want it automatically mounted as that defeats the purpose that I wanted a drive that could only be accessed via a password on a reboot..

To get around this I added a shortcut to the project.vhd file to my desktop. To be able to click this to attach the VHD I installed the vhdattach untility(http://www.jmedved.com/vhdattach/). This allowed me to right click the VHD shortcut and attached it, at which would I am prompted to enter the bitlock password for the VHD,.

So I now have a means attach my drive (fairly) easily even though I have no TPM chips. Just wish I had written down how I did it before so I did not have to work it out again.

It is not a perfect solution but at least my important data is bitlockered.

Why can’t I see my TFS reports?

Whist recently installing a TFS 2010 system onto a single box server, that was also a domain controller, I had a problem that though everything seemed in order I could not view my reporting services based reports in either SharePoint or directly from the http://myserver/reports interface.

During the installation I had verified I had the correct password for my [domain]\tfsreports account used to run the reports. If went to the http://myserver/reports page and edited the TFS2010ReportsDs or TFS2010OlapReportDS and tried to test the [domain]\tfsreports login it failed. However, if I swapped to the [domain]\administrator all was fine and my reports worked.

So what was the issue?

The key point is that the server, as it is a PDC, would only allow limited accounts to login to the server console. The actual Reporting Services web services were running as a named domain account (you cannot use Network Service and like on a PDC), but it seems that the connection by the [domain]\tfsreports account is considered the same as a login via the login screen as far as security systems are concerned.

The immediate fix was to make sure the [domain]\tfsreports user was in a group listed in the “Allow log on locally". To check this

  1. Run gpedit.msc
  2. Expand Computer Configuration\Windows Settings\Security Settings\Local Policies
  3. Click on User Rights Assignment
  4. Ensure that "Allow log on locally" includes user required, or that the user is in one of the listed groups

Now I am not sure this is the end of story, I am sure I can waste loads of time to find out exactly the minimum security settings needed, but this is an adequate solution for no for me.

How to waste time with Lab Management – Missing the obvious that MTM points to a Team Project

I posted a while ago about common confusion I had seen with Lab Management. We I have recently managed to get myself completely confused whilst working with Lab Management. It turns out the issue was so obvious I managed to miss it for hours, but as usual I learnt a good deal whilst trying to troubleshoot my stupidity.

I have a Lab Management system linked up to a a Team Project Collection (TPC). In this TPC there is a Team Project used for SharePoint development and on my Lab Management system I have an environment to allow testing of the SharePoint products. I setup a new Team Project in this TPC. In the new project I created a new MVC solution and created an automated build, which all worked fine.

I wanted to deploy this MVC application to a web server in an environment in my Lab Management system. So I created a basic web server environment and deployed it onto a host in my Lab. I then tried to create a Lab Management workflow build to deploy to the newly created environment. However the combo to select the environment was empty when I ran the wizard.

image

I was confused, I knew I had an environment on the Lab Management system, I had just created it in Test Manager (MTM) I could attach to it in MTM or Remote Desktop.

So I checked again

  • that the TPC was correctly registered with Lab Management
  • the environment was running in MTM
  • that all the configuration for the Team Project looked OK via TFSLABCONFIG.EXE

All to no avail. Then after far too long I realised I was not looking at the same things in MTM and Visual Studio.

When you are in the Lab Center (green border) pages of MTM there is no obvious indication of the Team Project you are using. I had forgotten this and got it into my head I was looking at all the environments and libraries for my whole TPC. THIS IS NOT THE CASE. The environments and libraries are Team Project specific and not TPC specific. I had created my new environment in my SharePoint team project not in my new MVC one.

To swap Team Project I needed to change to the Testing Centre (blue border) view and change the Test Plan (top right)

image

to get the dialog to change the Team Project.

image

Once this is done you can go to the Lab Center again and you see the environments for the selected Team Project. This was where I needed to create my environment.

At this point you will notice that all the templates and VMs you imported into the other Team project are not in this one. You have to reimport them from SCVMM and then create the environments in MTM for that Team Project

To the technical tip here is remember that Lab Center in MTM is Team Project specific – NOT Team Project Collection specific, but it does its best to not remind you of this fact so it is easy to forget.

How to expose IIS Express to external network connections and use a non-self signed certificate

IIS Express is a great addition to the tools for .NET web developers; it allow a slightly cut down copy of IIS 7.5 to be run without administrative privileges on a developer’s PC. This means we can hopefully get away from the problems associated by either

  1. Using Cassini – which is not IIS and does not do any clever
  2. Using full IIS which means Visual Studio has to run as administrator to debug it and also causes source control issues when a project is shared between multiple developers (their IIS setup must match up)

If you install Visual Studio 2010 SP1 and IIS express you now get a new option, that is to use IIS express as your web server. This, via a few clicks, can be configured for SSL and should address 90%+ of the needs of most developers. Once a project is set to use IIS express the key properties are set via the VS Property windows

image

However you are not limited to only editing these options; but to do more you need to use some command line tools.

What I wanted to do

My problem was that I wanted to test a Windows Phone 7 application that used a WCF web service. If I switched the WCF project to use IIS Express the WP7 application could not access the web server as, for security reasons, IIS Express is by default limited to only responding to requests from the localhost. The WP7 application is on another device (or at least a VM for development), so its request are not handled.

So we need to enable remote access to the server. ScottGu said this can be done in his post about IIS Express, but not how to do it.

Also I wanted to test my WP7 application using HTTPS. This raised a second issue. By default IIS express uses a self signed certificate. When this is used the WP7 WCF client throws as error as it cannot validate the certificate. I needed to swap the certificate for a ‘real one’. Again ScottGu’s post says it can be done but not how.

How I got it working

NOTE: I think the process covers all the steps, but it took me a while to get this going so there is a chance I might have missed step. Please treat this as outline guide and not definitive way to get it going. if I find errors I will update the post and highlight them.

Step 1 – Get the right Certificate onto the Development PC

I had already installed  the wildcard SSL certificate we have on my development PC from ita .PFX file.

To confirm this was OK I load MMC (running as a local administrator). Loaded the certificates snap-in, browsed to Personal|Certificates and checked it was there. I then clicked on the certificate and made a note of its thumbprint, you need it later

image

Step 2 – List the certificates you have installed for IIS

I opened a command prompt as administrator and run the command

netsh http show sslcert

This will stream past so you probably want to pipe it into a file to look at. Anyway you should find an entry for the self sign certificate that Visual Studio created when you setup IIS Express (on port 44300 in my case). Something like

IP:port                 : 0.0.0.0:44300
    Certificate Hash        : c3a234250edfb2adcd2b501cf4c44d0281e29476
    Application ID          : {214124cd-d05b-4309-9af9-9caa44b2b74a}
    Certificate Store Name  : MY
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0
    URL Retrieval Timeout   : 0
    Ctl Identifier          : (null)
    Ctl Store Name          : (null)
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled

We need to remove this self signed certificate so we can re-assign a real one to this port. To do this use the command

netsh http delete sslcert ipport=0.0.0.0:44300

then add the new certificate association using the command

netsh http add sslcert ipport=0.0.0.0:44300 certstorename=MY certhash=<certificate hash> appid=<appid>

<certificate hash> is the thumbprint of the SSL certificate found in step 1, with the spaces removed
<appid> can be any unique GUID

if you have the command line right it should say added OK. You could then run the list command again to check it is as you want.

So where are we up to…..

So at this point we have associated a real SSL certificate with any call to the port 44300 on this PC, note any call to this port, not just for IIS Express. If we do nothing else to configure IIS Express, let Visual Studio automatically start it, and try to load the site it will work for HTTP but when you try HTTPS it will error

image

If you inspect the certificate you will see it is using the one you set, but the certificate is linked to a Url, in my case *.blackmarble.co.uk so is deemed invalid when you try to use it with localhost.

We need to set IIS Express to respond on other addresses than localhost.

Step 3 – Making IIS Express respond to requests from the network

If you wish to make IIS Express respond to calls other than for localhost you have to run it as administrator, this is by design for security. Now it is fair to say from here onwards you are at the point where you lose some of the ease of use of the product as it does not ‘just work form Visual Studio’, but needs must.

We now need to edit the bindings of IIS Express. This could be done with command

c:\program files\iis express>appcmd set site "SiteName" /+bindings.[protocol='https', bindingInformation='*:44300:']

But I found it easier just to edit the edit the file C:\Users\[user name]\Documents\IISExpress\config\applicationhost.config in notepad. I altered the bindings section as follows

<bindings>
      <binding protocol="http" bindingInformation="*:60213:" />
      <binding protocol="https" bindingInformation="*:44300:" />
</bindings>

Basically I removed the :localhost at the end of each line. This allowing IIS Express to bind any Url not just localhost

Step 4 – Running IIS Express

You now need to just start your copy of IIS Express, this again has to be done from the command prompt running with administrative privileges. However, the command line parameters are identical to those used by Visual Studio (you can check task manager if you wish by showing the command line column on the processes tab)

"c:\Program Files (x86)\IIS Express\iisexpress.exe" /config: "c:\Documents and Settings\[username]\Documents\IISExpress\config\applicationhost.config" /site:"MyServer" /apppool:"Clr4IntegratedAppPool"

When you run this you should see the IIS Express process start-up.

So what have we ended up with?

So we now have IIS Express running the a wildcard certificate and listening to requests from any source. So as long as we use a Url valid for the SSL certificate we should be be able to load an HTTPS Url and get no errors.

However, be warned, due to the way we have had to launch IIS Express we have lost the ability to launch and debug from Visual Studio when not running as administrator. So I am not sure I have addressed the problem I started out try to address, I might as well just use the full version of IIS.

But look on the bright side I learnt something.

Thanks to Andy Westgarth for his assistance in getting to the bottom of assigning the right certificate, I was going in circles