Wednesday, February 13, 2008

Team Foundation Server and VSIP tidbits

One basic question that immediately comes up when writing Visual Studio Integration Package (VSIP) that needs to make use Team Foundation Server extensiblity, is how to handle TFS extensibility objects. "How to" for writing add-ins is well described in now classic blog post by Ed Hintz; while most of it applies also to VSIP there are some missing pieces that I will try to address.

As a first step, one needs to get TFS extensibility objects; once the extensibility objects are available, there is no major difference between add-in (as described in Ed's article) development and VS package.

To obtain reference to TFS specific objects (such as VersionControlExt) one needs DTE2 instance; in VSIP one may use the following approach to retrieve global DTE:

// use package GetService method to get
// extensibility service
EnvDTE.IVsExtensibility extensibility = 
   GetService(typeof(EnvDTE.IVsExtensibility)) as EnvDTE.IVsExtensibility;
// get IDE Globals object and DTE from that
EnvDTE80.DTE2 dte2 = 
   extensibility.GetGlobalsObject(null).DTE as EnvDTE80.DTE2;
            Debug.Assert(dte2 != null, "No DTE2");

Once reference to DTE2 is available, reference to TFS extensibility objects may be obtained as follows:

VersionControlExt versionControlExt = 
   dte2.GetObject("Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt") 
   as VersionControlExt;

Another frequently asked question is how to monitor when TFS server connection status in Visual Studio IDE. There is no special event exposed for this purpose; however, ProjectContextChanged event of TeamFoundationServerExt object may be used for this purpose (see Tim Noonan's excellent post for more details on this event). When TFS server is disconnected, active project context properties become null; when connected, the values in the context can be used to get reference to TeamFoundationServer object:

private void ProjectContextChanged(object sender, EventArgs e)
{
    // server is disconnected
    if (_teamServerExt.ActiveProjectContext.DomainName == null)
        ; // do disconnected stuff
    else 
    {
        // connected, can get reference to server
        //TeamFoundationServerFactory.GetServer(
        //    _teamServerExt.ActiveProjectContext.DomainUri.ToString());                
    }
}

Tracking TFS server connection status may seem unimportant, but it becomes vital in scenarios with several TFS servers available, or where VS may be started disconnected with connection to TFS established later on. In such cases assuming that the connection is always active may lead to some ugly bugs in your package.

Wednesday, February 06, 2008

Microsoft Static Code Analysis tools survey

February issue of TFS Times newsletter is out; and this time I am personally involved since it contains a short bit I did on Microsoft Static Code Analysis tools in Visual Studio 2005/2008. Read that online or get the PDF version here.

Update: There is mirror for the article available here.

Monday, February 04, 2008

Building VS2008 projects in VS2005

Today I got reminded of one issue, that I did not mention in the previous post on VS2005 solutions and projects conversion to VS2005 (mostly because I was not aware of that at the time :).

As it is .Net projects created in VS2005 can be built both in 2005 and 2008 without any changes to the project file. However, should you create a new project in VS2008 (even one targeting .Net 2.0), you will not be able to build it in VS2005. The reason is that VS2008 project is created compliant with MSBuild 3.5, in which $(MSBuildBinPath) property (location of all system target files) is deprecated, and $(MSBuildToolsPath) is used instead. Thus VS2008 will use MSBuildToolsPath to specify the location of Microsoft.CSharp.targets file, and the project will promptly blow in VS2005 on build.

As far as I know, there is no elegant solution to this problem (short of changing the project file). Probably the easiest solution would be to create the projects in VS2005 (that is, if you want to have .Net 2.0 projects that can be opened in both versions of Visual Studio). If you do modify the project files, here is the snippet I use to make sure that the project can be built in both flavours of Visual Studio:

<!-- VS2008 original import (sans condition 

     which is added for VS2005 benefit) -->

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" 

        Condition="$(MSBuildToolsPath) != ''" />

<!-- VS2005 import - added for VS2005 compatibility 

     (since there is no ToolsPath there) -->

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" 

        Condition="$(MSBuildToolsPath) == ''" />

Footnote: once you decide to use .Net 3.5 in your project on VS2008, then obviously your project wont build in VS2005 no matter the modifications.