用C#去除代碼的SourceSafe管理

 

C#去除代碼的SourceSafe管理

作者:秋楓<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

         經常看一些的程序,有些一個解決方案帶有多個項目,由於代碼比較多,多人開發,所以好多vs.net下的工程是用source safe進行版本控制的。而用source safe進行版本控制需要局域網路徑共享,因此好多項目換一臺機器打開會出現一些問題,比如“解決方案看起來是受源代碼管理,但無法找到它的綁定信息……”之類的提示信息很多。有時候修改了代碼還保存不了,所以想把他去掉,下面是對項目管理前後的一些對比。

 

 一、工程項目比較

同沒有受Source Safe代碼管理的工程相比:

1.   多出了.scc、.vssscc和.vspscc文件;

2.   C#項目文件(.csproj)裏面添加了幾行標籤:

SccProjectName = "SAK"

SccLocalPath = "SAK"

SccAuxPath = "SAK"

SccProvider = "SAK"

3.在解決方案文件(.sln)中,中增加了如下節點原素:

         GlobalSection(SourceCodeControl) = preSolution

                   SccNumberOfProjects = 4

                   SccLocalPath0 = .

                   ……

SccLocalPath3 = SUBSCRIBE_TOOLS

                   CanCheckoutShared = false

         EndGlobalSection

 

二、編寫實現的類

既然文件增多了,還有有些文件被修改,所以想通過編程把他修改回原樣,這樣可能可以去掉那些提示信息,所以就寫了下面的代碼。

//**********************************************************

// 程序:鄭佐  [email protected]  2004/06/10 

// 功能:去除C#.net的原代碼Source safe 管理

//**********************************************************

using System;

using System.IO;

using System.Text;

using System.Threading;

namespace ZZ

{

     /// <summary>

     /// 操作信息事件代理

     /// </summary>

     public delegate void OperateNotifyHandler(object sender,VssEventArgs e);

     /// <summary>

     /// VssConverter 處理解決方案或項目的SourceSafe關聯。

     /// </summary>

     public class VssConverter

     {

         //操作根目錄

         private string operatePath;

         /// <summary>

         /// 操作信息事件

         /// </summary>

         public event OperateNotifyHandler OperateNotify;

         /// <summary>

         /// 線程結束通知事件

         /// </summary>

         public event EventHandler ThreadCompleted;

         /// <summary>

         /// 構造函數

         /// </summary>

         /// <param name="operatePath">項目路徑</param>

         public VssConverter(string operatePath)

         {

              this.operatePath = operatePath;

         }

     OperatePath屬性,用來設置或獲取當前需要處理的工程路徑,不過在運行時最好不要設置他,

         /// <summary>

         /// 設置解決方案工程路徑

         /// </summary>

         public string OperatePath

         {

              get{return this.operatePath;}

              set{this.operatePath = value;}

         }

     下面是一個public 修飾符的函數,也是類實例的惟一對外公開的方法,裏面用了兩個線程來分別刪除文件和修改文件。

         /// <summary>

         /// 去除Source Safe代碼管理

         /// </summary>

         public void RemoveVss()

         {

              Thread deleteThread = new Thread(new ThreadStart(DeleteVssFile));

              Thread RemoveVssIdentifyThread = new Thread(new ThreadStart(RemoveVssIdentify));

              deleteThread.Start();

              RemoveVssIdentifyThread.Start();

         }

後來測試了一下deleteThread的完成要比RemoveVssIdentifyThread快一些,當然也可以再開一個線程來分擔文件的修改,不過這裏需要注意的是好多文件是帶只讀屬性的,所以還要把文件屬性設置成Normal才能順利完成操作,否則會拋出異常。

這裏使用了遞歸來刪除相關文件,由三個函數構成:

         /// <summary>

         /// 線程委託函數,完成刪除"*.scc","*.vssscc"以及*.vspscc文件功能。

         /// </summary>

         private void DeleteVssFile()

         {

              DeleteVssFile(this.operatePath);

              //通知刪除文件結束

              OnThreadCompleted(this,new EventArgs());

         }

         /// <summary>

         ///  遞歸函數,刪除"*.scc","*.vssscc"以及*.vspscc文件。

         /// </summary>

         /// <param name="path">當前處理路徑</param>

         private void DeleteVssFile(string path)

         {

              DeleteFile(Directory.GetFiles(path,"*.scc"));

              DeleteFile(Directory.GetFiles(path,"*.vssscc"));

              DeleteFile(Directory.GetFiles(path,"*.vspscc"));

              foreach(string dir in Directory.GetDirectories(path))

                   DeleteVssFile(dir);

         }

         /// <summary>

         /// 刪除文件,真正刪除文件

         /// </summary>

         /// <param name="files"></param>

         private void DeleteFile(string [] files)

         {

              foreach(string file in files)

              {

                   FileInfo fi = new FileInfo(file);

                   fi.Attributes = FileAttributes.Normal;

                   File.Delete(file);

                   OnOperateNotify(this,new VssEventArgs(file+"刪除完成"));

              }

         }

對於".sln"解決方案文件和".csproj’"C#項目文件的修改也採用了遞歸實現:

                   /// <summary>

         /// 線程委託函數,去除"*.sln"解決方案文件和"*.csproj"C#項目文件的.Vss關聯標籤。

         /// </summary>

         private void RemoveVssIdentify()

         {

              RemoveVssTag(this.operatePath);

              //通知去除標籤結束

              OnThreadCompleted(this,new EventArgs());

         }

        

         /// <summary>

         /// 去除"*.sln"解決方案文件和"*.csproj"C#項目文件的.Vss關聯標籤。

         /// </summary>

         /// <param name="path">當前處理路徑</param>

         private void RemoveVssTag(string path)

         {

              RemoveTagContent(Directory.GetFiles(path,"*.sln"));

              RemoveTagContent(Directory.GetFiles(path,"*.csproj"));

              foreach(string dir in Directory.GetDirectories(path))

                   RemoveVssTag(dir);

         }

     下面的函數用來分析處理文件的修改,因爲都是做刪除部分文件內容的工作,所以把處理函數寫成了一個,

         /// <summary>

         /// 去除"*.sln"解決方案文件和"*.csproj"C#項目文件的.Vss關聯標籤。

         /// </summary>

         /// <param name="file">當前處理文件</param>

         private void RemoveTagContent(string [] files)

         {

              foreach(string file in files)

              {

                   string strStart; //Vss標籤文本開始內容

                   string strEnd; //標籤文本結束內容

                   int offSet;//結束標籤文本的偏移量

                   FileInfo fi = new FileInfo(file);

                   fi.Attributes =FileAttributes.Normal;

                   if(fi.Extension == ".sln")//如果是解決方案文件

                   {

                       strStart = "GlobalSection(SourceCodeControl)";

                       strEnd = "EndGlobalSection";

                       offSet = 19;//包含/r/n和空格

                   }

                   else//如果是項目文件

                   {

                       strStart = "SccProjectName";

                       strEnd = ">";

                       offSet = 0;

                   }

                   try

                   {

                       int start;//Vss標籤文本開始索引

                       int end;//Vss標籤文本結束索引

                       string content;//文件內容

                       using(FileStream fs = new FileStream(file,FileMode.Open,FileAccess.ReadWrite,FileShare.ReadWrite))

                       {

                            StreamReader sr = new StreamReader(fs);

                            content = sr.ReadToEnd();

                            sr.Close();

                            start = content.IndexOf(strStart);

                       }

                       if(start!=-1)//文件需要去除標籤

                       {

                            using(FileStream fs = new FileStream(file,FileMode.Truncate,FileAccess.Write,FileShare.Read))

                            {

                                 end = start+content.Substring(start).IndexOf(strEnd)+offSet;

                                 content = content.Substring(0,start)+content.Substring(end);

                                 StreamWriter sw = new StreamWriter(fs);

                                 sw.Write(content);

                                 sw.Close();

                            }

                            OnOperateNotify(this,new VssEventArgs(file+"去除標籤完成"));

                       }

                   }

                   catch(Exception ex)

                   {

                       OnOperateNotify(this,new VssEventArgs(file+"操作錯誤:"+ex.ToString()));

                   }

              }            

     }

當此爲止,上面的程序實現了主要的功能,不過上面定義的事件,下面就是關於事件的函數,

         /// <summary>

         /// 操作信息事件通知

         /// </summary>

         /// <param name="sender">VssConverter</param>

         /// <param name="e">參數,</param>

         protected virtual void OnOperateNotify(object sender,VssEventArgs e)

         {

              if(OperateNotify!=null)

                   OperateNotify(sender,e);

         }

         /// <summary>

         /// 線程結束事件通知

         /// </summary>

         /// <param name="sender">VssConverter</param>

         /// <param name="e">參數</param>

         protected virtual void OnThreadCompleted(object sender,EventArgs e)

         {

              if(ThreadCompleted!=null)

                   ThreadCompleted(sender,e);

     }

}

相對於事件中的參數,這裏定義了一個類從EventArgs繼承,裏面只包含一個字段用來保存信息,

/// <summary>

     /// 消息通知事件參數類

     /// </summary>

     public class VssEventArgs : EventArgs

     {

         private string message;

         /// <summary>

         /// 構造函數

         /// </summary>

         /// <param name="message"></param>

         public VssEventArgs(string message)

         {

              this.message = message;

         }

         /// <summary>

         /// 消息內容

         /// </summary>

         public string Message

         {

              get{return this.message;}

         }

}

}//命名空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章