SourceSafe management with C # removal code
Author: Bischofia
Other procedures, some solutions have multiple projects, because the code is more, multi-person development, so many projects under VS.NET are controlled with Source Safe. The Source Safe is used to control the local area network path sharing. Therefore, many projects have changed some problems, such as "Solutions seem to be subject to source code, but cannot find its binding information ..." The prompt information is much. Sometimes I have already modified the code, I can't save it, so I want to remove him. The following is some contrast to the project management.
I. Comparison of project projects
Compared with the project management of Source Safe code:
1. Many.scc, .vssscc and .vspscc files;
2. C # project files (.csproj) have added a few lines of labels:
Sccprojectname = "SAK"
SccLocalPath = "SAK"
Sccauxpath = "SAK"
SccProvider = "SAK"
3. In the solution file (.sln), the following node is added:
GlobalSection (SourceCodecontrol) = PRESolution
Sccnumberofprojects = 4
ScclocalPath0 =.
......
SccLocalPath3 = SUBSCRIBE_TOOLS
Cancheckoutshared = false
Endglobalsection
Second, write the implementation
Since the file is increased, some files have been modified, so they want to modify him back by programming, so that I can remove those prompt information, so I wrote the following code.
// ******************************************************** **********
// Program: Zhengzu zhzuocn@163.com 2004/06/10
// Function: Removing C # .NET's original code Source Safe Management
// ******************************************************** **********
Using system;
Using system.io;
Using system.text;
Using system.threading;
Namespace ZZ
{
///
/// Operating information event agent
/// summary>
Public Delegate Void OperateNotifyHandler (Object Sender, VSSEventArgs E);
///
/// VssConverter process solution or project's SourceSafe association.
/// summary>
Public Class VssConverter
{
// Operate the root directory
PRIVATE STRING OPERATEPATH;
///
/// Operating information event
/// summary>
Public Event OperatenotifyHandler OperationNotify;
///
/// thread end notification event
/// summary>
Public Event EventHandler ThreadCompleted;
///
/// Constructor
/// summary>
/// Project path param>
Public vssconverter (String OperatePath)
{
THIS.OPERATEPATH = OPERATEPATH;
}
The OperatePath property is used to set or get the project path that currently needs, but it is best not to set him at runtime.
///
/// Set the solution engineering path
/// summary>
Public String OperatePath
{
Get {returnid.operatepath;}
Set {this.operatepath = value;
}
Below is a function of a public modifier, as well as the unique external public method of class instance, with two threads to delete files and modify files separately.
///
/// Remove Source Safe Code Management
/// summary>
Public void transovevss ()
{
Thread deletethread = new thread (New ThreadStart (deletevssfile);
Thread Removevssidentifythread = New Thread (New ThreadStart (RemovevssIdentify);
deletethread.start ();
REMOVEVSSIDENTIFYTHREAD.START ();
}
Later, I was tested that DELETETHREAD was faster than RemovevssiDentifythread. Of course, I can also open a thread to share the modification of the file, but here I need to pay attention is that a lot of files are read-only attributes, so I have to set the file attribute to Normal. The operation can be successfully completed, otherwise it will throw an exception.
Here, recursive deletion related files, consisting of three functions:
///
/// Thread delegate function, complete the deletion "* .scc", "*. Vsscc", and * .vspscc file function.
/// summary>
Private void deletevssfile ()
{
Deletevssfile (this.operatepath);
// Notice Delete File End
OnthreadCompleted (this, new evenetargs ());
}
///
/// Recresence function, delete "* .scc", "*. Vsscc", and * .vspscc files.
/// summary>
/// Current processing path param>
Private void deletevssfile (String Path)
{
DELETEFILE (Directory.GetFiles));
DELETEFILE (Directory.GetFiles);
DELETEFILE (Directory.GetFiles));
FOREACH (String Dir in Directory.GetDirectories (PATH))
Deletevssfile (DIR);
}
///
/// Remove the file, really delete the file
/// summary>
/// 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);
}
}
Recursive implementation for the ".sln" solution file and ".csproj '" C # project files are also used:
///
/// Thread Principal, remove the "* .sln" solution file and "* .csproj" C # project file. VSS associated tag.
/// summary>
Private void transovevssidentify ()
{
Removevsstag (this.operatePath);
// Notice Removing the end of the label
OnthreadCompleted (this, new evenetargs ());
}
///
/// Remove the "* .sln" solution file and "* .csproj" C # project file .vss associated tag.
/// summary>
/// Current processing path param>
Private void transovevsstag (String Path)
{
REMOVETAGCONTENT (Directory.Getfiles));
RemoveTagContent (Directory.GetFiles (PATH, "*. Csproj");
FOREACH (String Dir in Directory.GetDirectories (PATH))
Removevsstag (DIR);
}
The following functions are used to analyze the modification of the file, because they are doing the work of deleting some file content, so write the processing function into one,
///
/// Remove the "* .sln" solution file and "* .csproj" C # project file .vss associated tag.
/// summary>
/// Current processing file param>
Private void RemoveTagContent (String [] Files)
{
FOREACH (String File In Files)
{
String strs; // vss label text start content
String strand; // Label text ends
INT OFFSET; / / End the offset of the label text
FileInfo Fi = New FileInfo (file);
Fi.attributes = fileAttributes.Normal;
IF (FI.EXTension == ".SLN") // If it is a solution file
{
strStart = "GlobalSection (Sourcecodecontrol)";
Strend = "EndglobalSection";
OFFSET = 19; // contain / r / n and spaces
}
Else // If it is a project file {
Strstart = "sccprojectname";
STREND = ">";
OFFSET = 0;
}
Try
{
Int start; // vss label text begins index
INT end; // vss tag text end index
String content; // file 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) // The file needs to remove the label
{
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 "removal tag"))
}
}
Catch (Exception EX)
{
ONOPERATENOTIFY (this, New vsseventargs): " EX.TOSTRING ()));
}
}
}
That do this, the above program implements the main function, but the event defined above, the following is the function of the event,
///
/// Operating information event notification
/// summary>
/// VssConverter param>
/// parameter, param>
Protected Virtual Void OnoperationNotify (Object Sender, vsseventargs e)
{
IF (Operatenotify! = null)
OperateNotify (Sender, e);
}
///
/// thread end event notification
/// summary>
/// VssConverter param>
/// parameter param>
Protected Virtual Void ONTHREADCOMPLETED (Object Sender, Eventargs E)
{
IF (Threadcompleted! = NULL)
ThreadCompleted (Sender, e);
}
}
Compared to the parameters in the event, a class is defined here from Eventargs inherited, and only one field is used to save information, ///
/// Message Notification Event Parameter Class
/// summary>
Public Class vssEventArgs: Eventargs
{
PRIVATE STRING MESSAGE;
///
/// Constructor
/// summary>
/// param>
Public vsseventargs (String Message)
{
THIS.MESSAGE = Message;
}
///
/// Message content
/// summary>
Public String Message
{
Get {return this.Message;}
}
}
}//Namespaces