views:

51

answers:

1

I'm trying to write a macro that will generate a plain-text list of files changed based on the list of files in the Pending Changes pane but I can't figure out how to do it. The server location of a file is the property that is formatted like this:

$/TfsName/SomeSolution/Web/SomeFolder/SomeFile1.aspx
$/TfsName/SomeSolution/Web/SomeFolder/SomeFile2.aspx

The closest I can get is opening the properties of the selected item in the pane, which isn't very useful:

DTE.ExecuteCommand ("TeamFoundationContextMenus.SourceControlPendingChangesSourceFiles.TfsContextPendingCheckinsPendingCheckinsProperties")

Edit: here's the entire code for the macro I have so far, the TODOs are where I need help:

Public Class Pending

    Public Shared Sub Pending()
        OutputClear()
        OutputWriteLine("Files Changed:")

        Dim outInfo As String = ""
        DTE.Windows.Item("{2456BD12-ECF7-4988-A4A6-67D49173F564}").Activate() 'Pending Changes - Source Files

        'TODO: loop through each changed file
        'TODO: get TFS server location of each file
        outInfo &= "some file name"

        OutputWriteLine(outInfo)
    End Sub

    ' snip: other supporting functions

End Class
A: 

Well I haven't been able to figure out how to do it with a macro yet, but thanks to Bob Hardister on twitter, I can use this command to get what I'm looking for:

"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe" status $/ProjectName/SubDir/ /recursive

...but what works even better is a command-line app that uses this code:

const string TFSSERVER = "http://TfsServer:8080";
static void Main(string[] args)
{
    //http://blogs.msdn.com/b/buckh/archive/2006/03/15/552288.aspx
    //http://blogs.msdn.com/b/jmanning/archive/2005/12/01/499033.aspx
    string projectName = args[0];
    TeamFoundationServer tfs = new TeamFoundationServer(TFSSERVER);
    VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
    PendingSet[] sets = versionControl.GetPendingSets(new String[] { "$/Projects/" + projectName }, RecursionType.Full);
    Console.WriteLine(versionControl.AuthenticatedUser + " pending changes for " + projectName + ":");

    foreach (PendingSet set in sets)
    {
        if (set.Type == PendingSetType.Workspace && set.OwnerName == versionControl.AuthenticatedUser)
        {
            foreach (PendingChange pc in set.PendingChanges)
            {
                Console.WriteLine(pc.ServerItem);
            }
        }
    }
}

Then I just added the compiled EXE call to the External Tools menu and use it within VS there.

Bonus Edit: Here's the VSS version (not as nice):

const string SSDIR = @"\\VssServer\VssShare";
static void Main(string[] args)
{
    string projectName = args[0];
    string userName = "user";

    VSSDatabaseClass vss = new VSSDatabaseClass();
    vss.Open(SSDIR + @"\srcsafe.ini", userName, userName);
    VSSItem sourceItem = vss.get_VSSItem("$/Projects/" + projectName, false);

    Console.WriteLine(userName + " pending checkins for " + projectName + ":");
    int total = GetItems(sourceItem);
    Console.WriteLine(total.ToString() + " total changes.");

}

const int VSSFILE_CHECKEDOUT_ME = 2;
const int VSSITEM_PROJECT = 0;
const int VSSITEM_FILE = 1;
public static int GetItems(IVSSItem originalItem)
{
    int total = 0;
    foreach (IVSSItem subItem in originalItem.get_Items(false))
    {
        if (subItem.Type == VSSITEM_FILE && subItem.IsCheckedOut == VSSFILE_CHECKEDOUT_ME)
        {
            Console.WriteLine(subItem.Spec);
            total++;
        }
        else if (subItem.Type == VSSITEM_PROJECT)
        {
            total += GetItems(subItem);
        }
    }
    return total;
}
travis