就醬玩 Team Foundation Server API

因為工作的地方的檔案版本控管是使用 TFS,而上版是要整理好修改的檔案,書寫說明後,壓成壓縮檔後寄出,而不是自己說想說改過哪些檔案就直接簽入了,算比較麻煩

那為了節省我找出我倒底變更哪些檔案,並將檔案整理成制式的 Excel 報表,我就去研究 TFS API

透過這樣的 API 我可以達到取得暫止的變更的檔案清單,並勾選檔案後自動複製到指定的目錄及產生檔案的 Excel 清單,而 Excel 我是透過 NPOI 產生,這未來有機會再寫篇文章來介紹!

節省我去一個一個目錄翻檔案的工作時間,當然,應該也是可以寫出一個取得變更集的 API ,但目前沒去找資料

正題開始,要使用 TFS API ,首先要引用

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.VersionControl.Client
  • Microsoft.TeamFoundation.VersionControl.Common

但這三個參考都沒辦法直接在 加入參考 中的 .Net 參考直接找到,最後我找了文章,他是放在

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\

目錄裡面,將這三個加入參考後,就能使用一些常用的 TFS 功能了(其中我的 Visual Studio 是 2008 ,所以是在 Visual Studio 9.0 找,不同的 VS 可能會在不同的版本號)。

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

using System.Text.RegularExpressions;

namespace TFSCommitHelper
{
    public partial class Form1 : Form
    {
    
        TeamFoundationServer tfsServer = null;
        VersionControlServer vcServer = null;
        Workspace workspace = null;
        List pendingItems = new List();
        List localFilePaths = new List();
        string userName = string.Empty;
        PendingSet[] pendingSets = null;

        string strWorkspace = @"mywctpc";
        string sourcePath = @"C:\MySource\Developer";
        Dictionary<string, ChangeType> fileChangeType = new Dictionary<string, ChangeType>();
        
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
            checkedListBox1.AllowDrop = true;
            checkedListBox1.DragEnter += new DragEventHandler(checkedListBox1_DragEnter);
            checkedListBox1.DragDrop += new DragEventHandler(checkedListBox1_DragDrop);
        }
        
        void Form1_Load(object sender, EventArgs e)
        {
            // 判斷是否是 config 檔, config 檔不需要上版
            Regex re1 = new Regex(".*\\.config");

            string tmp;
            int i = 1;
            do
            {
                tmp = string.Format(@"D:\上版需求\{0}{1:00}", DateTime.Now.ToString("yyyyMMdd"), i++);
            }
            while (Directory.Exists(tmp));
            textBox2.Text = tmp;

            try
            {
                // TFS Init
                tfsServer = new TeamFoundationServer("http://tfs:8080/");
                tfsServer.Authenticate();

                object obj = tfsServer.GetService(typeof(Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer));
                vcServer = obj as Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer;

                if (vcServer != null)
                {
                    workspace = vcServer.GetWorkspace(strWorkspace, tfsServer.AuthenticatedUserName);
                }
                foreach (Microsoft.TeamFoundation.VersionControl.Client.WorkingFolder folder in workspace.Folders)
                {
                    pendingItems.Add(folder.ServerItem);
                }

                userName = tfsServer.AuthenticatedUserName;

                pendingSets = workspace.QueryPendingSets(pendingItems.ToArray(), RecursionType.Full, null, userName, false);
                foreach (PendingSet ps in pendingSets)
                {
                    foreach (PendingChange change in ps.PendingChanges)
                    {
                        localFilePaths.Add(change.LocalItem);
                        fileChangeType.Add(change.LocalItem, change.ChangeType);
                    }
                }
                foreach (var s in localFilePaths)
                {
                    string fileName = s.Substring(s.LastIndexOf('\\') + 1);

                    if (s != null && s.StartsWith(sourcePath))
                    {
                        checkedListBox1.Items.Add(s);
                        if(!re1.IsMatch(s))
                            checkedListBox1.SetItemChecked(checkedListBox1.Items.Count - 1, true);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void checkedListBox1_DragEnter(object sender, DragEventArgs e)
        {
            // 確定使用者抓進來的是檔案
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            {
                // 允許拖拉動作繼續 (這時滑鼠游標應該會顯示 +)
                e.Effect = DragDropEffects.All;
            }
        }

        void checkedListBox1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                foreach (string file in files)
                {
                    if(file.StartsWith(sourcePath))
                        checkedListBox1.Items.Add(file);
                }
            }
        }
    
    }
}

上面是我撰寫的程式碼,主要會將所有暫止的變更且檔案絕對路徑開頭與 sourcePath 變數值相符的全加進去 checkListBox1 清單列表

然後當檔案符合 re1 正規式的話,則不勾選該選項。

 


 

Reference

http://stackoverflow.com/questions/3413527/how-to-connect-with-tfs-and-get-list-of-projects-for-a-specific-user
http://stackoverflow.com/questions/269425/list-of-files-with-pending-changes-in-vs2008-tfs-to-clipboard
http://blogs.msdn.com/b/buckh/archive/2012/03/10/team-foundation-version-control-client-api-example-for-tfs-2010-and-newer.aspx

留言

這個網誌中的熱門文章

DB 資料庫呈現復原中

Outlook 刪除大量重覆信件

[VB.Net] If vs IIf ,兩者的差異