用C#去除代碼的SourceSafe管理
2024-07-21 02:19:24
供稿:網友
用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
二、編寫實現的類
既然文件增多了,還有有些文件被修改,所以想通過編程把他修改回原樣,這樣可能可以去掉那些提示信息,所以就寫了下面的代碼。
//**********************************************************
// 程序:鄭佐 [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;}
}
}
}//命名空間