正文

用C#去除代码的SourceSafe管理2006-09-13 11:34:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/Csharpsky/18504.html

分享到:

 经常看一些的程序,有些一个解决方案带有多个项目,由于代码比较多,多人开发,所以好多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   二、编写实现的类 既然文件增多了,还有有些文件被修改,所以想通过编程把他修改回原样,这样可能可以去掉那些提示信息,所以就写了下面的代码。 //********************************************************** // 程序:郑佐  zhzuocn@163.com  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;}          } } }//命名空间 三、测试使用   程序测试运行界面, 界面部分代码大多数由设计器生成,下面列出了主要添加代码,  //委托,更新文本框  private delegate void AppendTextHandler(string content);   //标记转换操作是否完成   private int convertOK =0;   private System.Windows.Forms.TextBox textBoxFolder;//路径文本框   private System.Windows.Forms.Button buttonFolder;//浏览按钮   private System.Windows.Forms.TextBox textBoxInfo;//信息显示框   private System.Windows.Forms.Button buttonOK;//运行按钮   private System.Windows.Forms.Button buttonCancel;//退出按钮   按钮处理函数用来打开一个路径选择框,   private void buttonFolder_Click(object sender, System.EventArgs e)   {        FolderBrowserDialog myDialog = new  FolderBrowserDialog();        myDialog.ShowNewFolderButton = false;        myDialog.Description = "选择需要处理的解决方案或项目目录";        if(myDialog.ShowDialog()==DialogResult.OK)            this.textBoxFolder.Text = myDialog.SelectedPath;        myDialog.Dispose();   }    运行函数,在这里面实例化VssConverter类,并调用了RemoveVss方法,运行时把几个按钮禁了,里面注册了两个事件,起信息传递作用,不过对于直接在地址栏中输入非法路径没有做具体判断,    private void buttonOK_Click(object sender, System.EventArgs e)   {        if(this.textBoxFolder.Text.Length>1)        {            this.textBoxInfo.Clear();            this.convertOK = 0;            this.buttonOK.Enabled = false;            this.buttonFolder.Enabled = false;            this.buttonCancel.Enabled = false;            this.textBoxFolder.Enabled = false;            VssConverter vssConverter = new VssConverter(this.textBoxFolder.Text);            vssConverter.OperateNotify += new OperateNotifyHandler(vssConverter_OperateNotify);            vssConverter.ThreadCompleted += new EventHandler(vssConverter_ThreadCompleted);            vssConverter.RemoveVss();        }        else            MessageBox.Show("请输入解决方案或项目路径!");   }    下面是两个事件处理函数,第一个是用来在前台即时显示当前处理的文件信息,第二个函数是用来通知线程的执行结果。函数如下,   // 信息通知    private void vssConverter_OperateNotify(object sender, VssEventArgs e)   {        AppendTextHandler ath = new AppendTextHandler(this.textBoxInfo.AppendText);        this.textBoxInfo.BeginInvoke(ath,new object[]{e.Message+Environment.NewLine});   }   // 线程结束通知   private void vssConverter_ThreadCompleted(object sender, EventArgs e)   {        if(this.convertOK==0)            this.convertOK++;        else        {            this.buttonOK.Enabled = true;            this.buttonFolder.Enabled = true;            this.buttonCancel.Enabled = true;            this.textBoxFolder.Enabled = true;            this.textBoxInfo.AppendText("#### 转换完成 ####");        }   }         总结,程序通过搜索指定目录下的文件,根据扩展名进行相应的操作来完成处理,其中为了加快运行速度增加了线程来处理。欢迎大家交流。

阅读(1975) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册