用C#去除代码的SourceSafe管理

常看一些的程序,有些一个解决方案带有多个项目,由于代码比较多,多人开发,所以好多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
  二、编写实现的类
  既然文件增多了,还有有些文件被修改,所以想通过编程把他修改回原样,这样可能可以去掉那些提示信息,所以就写了下面的代码。
  功能:去除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;}
  }
  }
  }//命名空间

你可能感兴趣的:(用C#去除代码的SourceSafe管理)