用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
二、编写实现的类
既然文件增多了,还有有些文件被修改,所以想通过编程把他修改回原样,这样可能可以去掉那些提示信息,所以就写了下面的代码。
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("#### 转换完成 ####");
}
}
总结,程序通过搜索指定目录下的文件,根据扩展名进行相应的操作来完成处理,其中为了加快运行速度增加了线程来处理。
相关文章:

用jarsigner对android apk进行签名
以前对apk重新打包签名都是用的apktool里面的Auto-sign 工具,后来发现有时候利用该工具对一些apk签名会失败,所以后来就使用 jarsigner这个工具,现记录一下这个工具的使用方法1 首先要生成一个自己的keyD:\>keytool -genkey -alias myKey…

利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换
作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上的疏散耦合,而非…

C#操作消息队列
public class QueueManage { /// /// 发送对象到队列中 /// /// 队列名称,因为队列名称在一个应用中应该不改变的,所以大家最好写在配置文件中 /// 要发出去的对象 public static void SendQueue(string QueuePath,MyBase.SmsQueue sq) { Syste…

2021《程序员》数字科技企业研发实力榜TOP50
互联网的盛行带来了众多数字科技企业的崛起,但如何客观地衡量每家企业的技术实力?研发投入、研发人才的数量和人才密度是关键指标。2021年5月,《程序员》根据相关企业披露的财报数据及市场调研数据,整理发布“2021数字科技企业研发实力榜TOP5…

eclipse中java项目转换为web项目
2019独角兽企业重金招聘Python工程师标准>>> 经常在eclipse中导入web项目时,出现转不了项目类型的问题,导入后就是一个java项目,有过很多次经历,今天也有同事遇到类似问题,就把这个解决方法记下来吧&#x…

MySQL · 引擎介绍 · Sphinx源码剖析(三)
在本节中我会介绍Sphinx在构建索引之前做的一些事情,主要是从mysql拉取数据保存,然后分词排序保存到内存等等一系列的操作。下面是几个相关指令 sql_query \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, \title, content \FROM doc…

C#给图片添加版权信息
现在越来越多的网站都喜欢将用户上传的图片加上网站的版权信息,不要以为那是用photoshop之类的图片处理软件加上去的,其实我们只要写一小段代码,就可以实现这个功能。 添加版权信息的原理其实挺简单:通过图片获取Graphics类的对象…

Python + 爬虫:可视化大屏帮你选粽子
来源 | 数据分析与统计学之美头图 | 下载于ICphoto端午节快要到了,旅游?回家?拜访亲友?少不了要带上粽子。那么,选择什么牌子的粽子呢?选择什么口味的粽子呢?选择什么价格区间呢?今年…

adviser vs mentor
研究生或博士生提到自己导师的时候是说adviser呢?还是mentor呢? 至少我认识一个Berkeley的博士是说adviser的。 另外,我的导师也是说adviser。 那还是说adviser吧……

T extends Serializable这是什么意思呢?看明白这个,你的问题就自然而然的明白了!...
1.转自:https://blog.csdn.net/liwenqiang758/article/details/8131185 自己动手丰衣足食!!! 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、接口和方法的创建中&a…

C#中switch语句注意
大家肯定对switch语句并不陌生,它能够让程序根据控制表达式的值,从多个动作中作出选择(从逻辑过程看,和多分支语句if-else有些相似)。在C和java中也有这一语句,不过在C#中,这一语句则有了些变化。先看下边一…

对Cost (%CPU) 粗略的理解
今天研究执行计划,看到执行计划里面有Cost (%CPU),我这边研究了一把,不知道对与否,拿出来晒晒在Oracle 10g中,Oracle 把CPU的cost也统计在执行计划中去了, 这和以前的8i,9i(9i其实已经开始了)有很大的不同。…

后疫情时代,RTC期待新的场景大爆发
整理 | 寇雪芹头图 | 下载于ICphoto出品 | AI 科技大本营(ID:rgznai100) 过去的一年中,新冠疫情悄然改变了社会发展和人们的生活,也助推了实时音视频(Real-Time Communication)技术的落地应用,数…

JS-DOM-元素节点
查看元素节点: 1、getElementById():通过 id 取到唯一节点;如果 id 重名,只能取到第一个 getElementByName(): 通过name属性 getElementByTagName(): 通过标签名 getElementByClassName(): 通过class名 获取元素节点时,一定要注意:获取节点的语句,必须在 DOM 渲染完成之后执行。…

现代软件工程 第十章 【典型用户和场景】 练习与讨论
1. 讨论:下面的老板犯了什么错误? 只看用户的表面语言或行动还是不够的。我们还要找到用户语言行动背后的动机! (图像来源: http://www.weibo.com/funnyshoelace) 2. 是否要文档 有人说,我们敏捷的团队,就喜欢直接的面对面的交流࿰…

赠书 | 读懂生成对抗神经网络 GAN,看这文就够了
生成对抗神经网络(Generative Adversarial Nets,GAN)是一种深度学习的框架,它是通过一个相互对抗的过程来完成模型训练的。典型的GAN包含两个部分,一个是生成模型(Generative Model,简称G&#…

把Doc文档转换成rtf格式
先在项目引用里添加上对Microsoft Word 9.0 object library的引用。 using System; namespace DocConvert { class DoctoRtf { static void Main() { //创建一个word的实例 Word.Application newApp new Word.Application(); // 指定源文件和目标文件 object Source&quo…

中国书法的造型元素与原理 刘彦湖
为什么80%的码农都做不了架构师?>>> --------------------------------------------------------------------------------中国书法的造型元素与原理 刘彦湖 中国书法是用最基本的元素遵从中国人特有的形式原则建构起来的大厦。 对于元素及其品质的认…

融云任杰:强互动,RTC 下一个“爆点”场景 | 拟合
从无序中寻找踪迹,从眼前事探索未来。2021 年正值黄金十年新开端,CSDN 以中立技术社区专业、客观的角度,深度探讨中国前沿 IT 技术演进,推出年度重磅企划栏目——「拟合」,通过对话企业技术高管大咖,跟踪报…

推荐一个个人感觉比较有吸引力的网站
2019独角兽企业重金招聘Python工程师标准>>> 廖雪峰的官方网站 转载于:https://my.oschina.net/AaronCN/blog/294293

C# 2进制、8进制、10进制、16进制...各种进制间的轻松转换
在.NET Framework中,System.Convert类中提供了较为全面的各种类型、数值之间的转换功能。其中的两个方法可以轻松的实现各种进制的数值间的转换: Convert.ToInt32(string value, int fromBase): 可以把不同进制数值的字符串转换为数字&#x…

solrj操作单机solr
2019独角兽企业重金招聘Python工程师标准>>> 在目前的生产过程中全文检索技术应用越来越广,其中涌现了一批非常好得开源搜索引擎框架,如solr,elasticsearch等等。其中我工作使用最多的是solr,并在此对之前工作做一个总结。 solr的…

基于微软开源深度学习算法,用 Python 实现图像和视频修复
作者 | 李秋键编辑 | 夕颜出品 | AI科技大本营(ID:rgznai100)图像修复是计算机视觉领域的一个重要任务,在数字艺术品修复、公安刑侦面部修复等种种实际场景中被广泛应用。图像修复的核心挑战在于为缺失区域合成视觉逼真和语义合理的像素&…

C#实现光盘做启动盘
一 :编程思想 1、创建启动盘 插入要创建的启动盘,程序自动检测光驱中光盘,利用WMI(Windows管理架构:Windows Management Instrumentation)读取该光盘的序列号(具有唯一性)…

为云服务立规矩——首批可信云服务认证名单公布
俗话说,没有规矩不成方圆。在云服务蓬勃发展的今天,无论从规范行业发展,还是为用户提供保障,推动政府云服务采购的角度来说,云服务市场都需要立规矩。7月15日至16日,以“可信中国云,未来新生态”…

Java:多个文档合并输出到一个文档
多个文档合并输出到一个文档 方法:Java NIO package First;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel;public class Test {pu…
线性表之顺序表(C语言实现)
线性表是从数据元素的逻辑结构上定义的. 这种数据元素的逻辑结构的特征如下: 1.除开第一个和最后一个元素之外.所有元素都有一个前驱元素和后继元素. 2.第一个元素无前驱元素,但有后继元素. 3.最后一个元素有前驱元素,单无后继元素. 可以抽象为如下表述: 元素1元素2元素3元素4元…

C# POP3编程
POP3的使用很简单,所以.net没有向SMTP那样给出相应的类来控制. 废话少说,程序员最需要的使代码,:)! 1.打开VS.NET 2003. 2.新建一个WinForm Application. 3.添加命名空间 using System; using System.Drawing; using System.Collections; using System.ComponentModel; usi…

终于有人把 Python 讲清楚了!
Python因为其优越的特性广泛应用于数据分析、人工智能、Web开发、后端开发、自动化测试/运维、爬虫等领域,也得到了很多企业的青睐。甚至连BATZJ的技术大牛,都无可否认Python现在对于一个程序员发展的重要性!最近一两年,我身边也有…