How do I call Workstation.GetLocalWorkspaceInfo in a way that works for those using VS2012 and those using VS2013 without reflection?

Workstation.Current.GetLocalWorkspaceInfo(string)

returns the object WorkspaceInfo

associated with the given local directory.

So, I wrote a simple program that displays the workspace name with the name of the local directory. It works fine on my machine, but doesn't work on another.

The difference between the two is that mine is running VS2012 and the other is VS2013. For life, I cannot understand this. Both workspaces are associated with the same TFS 2010 server.

After reading the TFS API: GetLocalWorkspaceInfo always returns null I replaced the Microsoft.TeamFoundation.XXX references with the ones found on the second machine and it worked again. But of course it stopped working on my machine.

It can't be right. I must be doing something wrong.

I want one executable to work for both machines without having to think. My question is simple - how?

The complete source code can be found here - https://bitbucket.org/markkharitonov/tfsinsanity/src . Basically, these are two projects that use the same source code but use a different set of dependencies.

Main source code:

private static Workspace GetWorkspace(string wsRoot, string wsName, string wsOwner)
{
    var coll = new TfsTeamProjectCollection(new Uri("http://torsvtfs01:8080/tfs/DefaultCollection"));
    var vcs = (VersionControlServer)coll.GetService(typeof(VersionControlServer));
    WorkspaceInfo wsInfo;
    if (wsRoot == null)
    {
        Console.WriteLine(Workstation.Current.Name);
        wsInfo = Workstation.Current.GetLocalWorkspaceInfo(vcs, wsName, wsOwner);
        if (wsInfo == null)
        {
            throw new Exception(string.Format("Failed to identify the workspace {0};{1}", wsName, wsOwner));
        }
    }
    else
    {
        wsInfo = Workstation.Current.GetLocalWorkspaceInfo(wsRoot);
        if (wsInfo == null)
        {
            throw new Exception(string.Format("Failed to identify the workspace corresponding to \"{0}\"", wsRoot));
        }
    }
    return wsInfo.GetWorkspace(coll);
}

      

This is how it works on my machine (VS2012):

PS C:\work\GetShelvedChangeset> tf workspaces
Collection: http://torsvtfs01:8080/tfs/defaultcollection
Workspace Owner                Computer Comment
--------- -------------------- -------- ------------------------------------------------------------------------------------
CANWS212  DAYFORCE\mkharitonov CANWS212
PS C:\work\GetShelvedChangeset> .\bin\Debug2012\GetShelvedChangeset.exe --wsRoot C:\dayforce\SharpTop
Microsoft.TeamFoundation.VersionControl.Client, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Workspace instance -784339741
  Comment:
  Computer: CANWS212
  EffectivePermissions: 0
  Folders: [0]
  IsLocalWorkspace: False
  LastAccessDate: 1/1/0001 12:00:00 AM
  Name: CANWS212
  Options: 0
  OwnerAliases: [0]
  OwnerDisplayName: DAYFORCE\mkharitonov
  OwnerIdentifier:
  OwnerIdentityType:
  OwnerName: DAYFORCE\mkharitonov
  OwnerUniqueName:
  SecurityToken: /CANWS212;34be4ed8-c4fd-4e9f-bdae-d1843df36b0f
PS C:\work\GetShelvedChangeset> .\bin\Debug2013\GetShelvedChangeset.exe --wsRoot C:\dayforce\SharpTop
Failed to identify the workspace corresponding to "C:\dayforce\SharpTop"
PS C:\work\GetShelvedChangeset>

      

And on another computer:

PS C:\tfs\DFGatedCheckInTest2\Build\2010\scripts> &"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\tf.exe" workspaces
Collection: http://torsvtfs01:8080/tfs/defaultcollection
Workspace            Owner             Computer     Comment
-------------------- ----------------- ------------ ----------------------------------------------------------------------------------------
1733_TORSVBUILD10    DAYFORCE\tfsbuild TORSVBUILD10 Workspace Created by Team Build
1846_91_TORSVBUILD10 DAYFORCE\tfsbuild TORSVBUILD10 Workspace Created by Team Build
1846_92_TORSVBUILD10 DAYFORCE\tfsbuild TORSVBUILD10 Workspace Created by Team Build
PS C:\tfs\DFGatedCheckInTest2\Build\2010\scripts> .\debug2012\GetShelvedChangeset.exe --wsRoot C:\tfs\DFGatedCheckInTest2
Failed to identify the workspace corresponding to "C:\tfs\DFGatedCheckInTest2"
PS C:\tfs\DFGatedCheckInTest2\Build\2010\scripts> .\debug2013\GetShelvedChangeset.exe --wsRoot C:\tfs\DFGatedCheckInTest2
Microsoft.TeamFoundation.VersionControl.Client, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Workspace instance 215494889
  Comment: Workspace Created by Team Build
  Computer: TORSVBUILD10
  EffectivePermissions: 0
  Folders: [0]
  IsLocalWorkspace: False
  LastAccessDate: 1/1/0001 12:00:00 AM
  Name: 1733_TORSVBUILD10
  Options: 0
  OwnerAliases: [0]
  OwnerDisplayName: DAYFORCE\tfsbuild
  OwnerIdentifier:
  OwnerIdentityType:
  OwnerName: DAYFORCE\tfsbuild
  OwnerUniqueName:
  SecurityToken: /1733_TORSVBUILD10;f2899138-af14-4449-9f6d-78a0fbccebb8
PS C:\tfs\DFGatedCheckInTest2\Build\2010\scripts>

      

+3


source to share


2 answers


In this case, the method signatures must be identical, you just have to worry about getting the proper DLL reference in the first place. You should be able to reference the new DLL and use binding redirection to load the DLL for users who have VS 2012 installed.

We have successfully used this method in a previous product to ensure compatibility with TFS 2005 and 2008.

In short, you are creating a custom assembler. Here we will try to load all DLLs Microsoft.TeamFoundation.*

from VS 2012 when we fail to load the VS 2013 versions we linked to:



AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

public static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
    String[] arguments = args.Name.Split(new string[] { ", ", "," }, 
        StringSplitOptions.RemoveEmptyEntries);
    String assemblyName = arguments[0];

    if(assemblyName.StartsWith("Microsoft.TeamFoundation.", StringComparison.CurrentCultureIgnoreCase))
    {
        return Assembly.Load(assemblyName + ", Version=11.0.0.0");
    }

    return null;
}

      

(Note that you should probably check the requested version number and pass the culture information to the bootloader as mentioned in the blog post, but that snippet should be enough to get you started.)

+3


source


Add the executable file associated with the project to the project in the installation file by setting the CopyLocal property to Always.



0


source







All Articles