经常看一些的程序有些一个解决方案带有多个项目由于代码比较多多人开发所以好多下的工程是用source safe进行版本控制的而用source safe进行版本控制需要局域网路径共享因此好多项目换一台机器打开会出现一些问题比如解决方案看起来是受源代码管理但无法找到它的绑定信息……之类的提示信息很多有时候修改了代码还保存不了所以想把他去掉下面是对项目管理前后的一些对比
一工程项目比较
同没有受Source Safe代码管理的工程相比
. 多出了sccvssscc和vspscc文件
. C#项目文件(csproj)里面添加了几行标签
SccProjectName = SAK
SccLocalPath = SAK
SccAuxPath = SAK
SccProvider = SAK
.在解决方案文件(sln)中中增加了如下节点原素
GlobalSection(SourceCodeControl) = preSolution
SccNumberOfProjects =
SccLocalPath =
……
SccLocalPath = SUBSCRIBE_TOOLS
CanCheckoutShared = false
EndGlobalSection
二编写实现的类
既然文件增多了还有有些文件被修改所以想通过编程把他修改回原样这样可能可以去掉那些提示信息所以就写了下面的代码
功能去除的原代码Source safe 管理
using System;
using SystemIO;
using SystemText;
using SystemThreading;
namespace ZZ
{
/// <summary>
/// 操作信息事件代理
/// </summary>
public delegate void OperateNotifyHandler(object senderVssEventArgs 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)
{
thisoperatePath = operatePath;
}
OperatePath属性用来设置或获取当前需要处理的工程路径不过在运行时最好不要设置他
/// <summary>
/// 设置解决方案工程路径
/// </summary>
public string OperatePath
{
get{return thisoperatePath;}
set{thisoperatePath = value;}
}
下面是一个public 修饰符的函数也是类实例的惟一对外公开的方法里面用了两个线程来分别删除文件和修改文件
/// <summary>
/// 去除Source Safe代码管理
/// </summary>
public void RemoveVss()
{
Thread deleteThread = new Thread(new ThreadStart(DeleteVssFile));
Thread RemoveVssIdentifyThread = new Thread(new ThreadStart(RemoveVssIdentify));
deleteThreadStart();
RemoveVssIdentifyThreadStart();
}
后来测试了一下deleteThread的完成要比RemoveVssIdentifyThread快一些当然也可以再开一个线程来分担文件的修改不过这里需要注意的是好多文件是带只读属性的所以还要把文件属性设置成Normal才能顺利完成操作否则会抛出异常
这里使用了递归来删除相关文件由三个函数构成
/// <summary>
/// 线程委托函数完成删除*scc*vssscc以及*vspscc文件功能
/// </summary>
private void DeleteVssFile()
{
DeleteVssFile(thisoperatePath);
//通知删除文件结束
OnThreadCompleted(thisnew EventArgs());
}
/// <summary>
/// 递归函数删除*scc*vssscc以及*vspscc文件
/// </summary>
/// <param name=path>当前处理路径</param>
private void DeleteVssFile(string path)
{
DeleteFile(DirectoryGetFiles(path*scc));
DeleteFile(DirectoryGetFiles(path*vssscc));
DeleteFile(DirectoryGetFiles(path*vspscc));
foreach(string dir in DirectoryGetDirectories(path))
DeleteVssFile(dir);
}
/// <summary>
/// 删除文件真正删除文件
/// </summary>
/// <param name=files></param>
private void DeleteFile(string [] files)
{
foreach(string file in files)
{
FileInfo fi = new FileInfo(file);
fiAttributes = FileAttributesNormal;
FileDelete(file);
OnOperateNotify(thisnew VssEventArgs(file+删除完成));
}
}
对于sln解决方案文件和csprojC#项目文件的修改也采用了递归实现
/// <summary>
/// 线程委托函数去除*sln解决方案文件和*csprojC#项目文件的Vss关联标签
/// </summary>
private void RemoveVssIdentify()
{
RemoveVssTag(thisoperatePath);
//通知去除标签结束
OnThreadCompleted(thisnew EventArgs());
}
/// <summary>
/// 去除*sln解决方案文件和*csprojC#项目文件的Vss关联标签
/// </summary>
/// <param name=path>当前处理路径</param>
private void RemoveVssTag(string path)
{
RemoveTagContent(DirectoryGetFiles(path*sln));
RemoveTagContent(DirectoryGetFiles(path*csproj));
foreach(string dir in DirectoryGetDirectories(path))
RemoveVssTag(dir);
}
下面的函数用来分析处理文件的修改因为都是做删除部分文件内容的工作所以把处理函数写成了一个
/// <summary>
/// 去除*sln解决方案文件和*csprojC#项目文件的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);
fiAttributes =FileAttributesNormal;
if(fiExtension == sln)//如果是解决方案文件
{
strStart = GlobalSection(SourceCodeControl);
strEnd = EndGlobalSection;
offSet = ;//包含\r\n和空格
}
else//如果是项目文件
{
strStart = SccProjectName;
strEnd = >;
offSet = ;
}
try
{
int start;//Vss标签文本开始索引
int end;//Vss标签文本结束索引
string content;//文件内容
using(FileStream fs = new FileStream(fileFileModeOpenFileAccessReadWriteFileShareReadWrite))
{
StreamReader sr = new StreamReader(fs);
content = srReadToEnd();
srClose();
start = contentIndexOf(strStart);
}
if(start!=)//文件需要去除标签
{
using(FileStream fs = new FileStream(fileFileModeTruncateFileAccessWriteFileShareRead))
{
end = start+contentSubstring(start)IndexOf(strEnd)+offSet;
content = contentSubstring(start)+contentSubstring(end);
StreamWriter sw = new StreamWriter(fs);
swWrite(content);
swClose();
}
OnOperateNotify(thisnew VssEventArgs(file+去除标签完成));
}
}
catch(Exception ex)
{
OnOperateNotify(thisnew VssEventArgs(file+操作错误+exToString()));
}
}
}
当此为止上面的程序实现了主要的功能不过上面定义的事件下面就是关于事件的函数
/// <summary>
/// 操作信息事件通知
/// </summary>
/// <param name=sender>VssConverter</param>
/// <param name=e>参数</param>
protected virtual void OnOperateNotify(object senderVssEventArgs e)
{
if(OperateNotify!=null)
OperateNotify(sendere);
}
/// <summary>
/// 线程结束事件通知
/// </summary>
/// <param name=sender>VssConverter</param>
/// <param name=e>参数</param>
protected virtual void OnThreadCompleted(object senderEventArgs e)
{
if(ThreadCompleted!=null)
ThreadCompleted(sendere);
}
}
相对于事件中的参数这里定义了一个类从EventArgs继承里面只包含一个字段用来保存信息
/// <summary>
/// 消息通知事件参数类
/// </summary>
public class VssEventArgs : EventArgs
{
private string message;
/// <summary>
/// 构造函数
/// </summary>
/// <param name=message></param>
public VssEventArgs(string message)
{
ssage = message;
}
/// <summary>
/// 消息内容
/// </summary>
public string Message
{
get{return ssage;}
}
}
}//命名空间