Introduction
VSS Helper- Addin for VSTS 2005 is an addin tool to interact with VSS from the Visual Studio IDE. Currently, Visual Studio IDE doesn't provide information about who has checked out a file apart from the current user. It is always time-consuming for the developer to identify who has checked out the file which is required by him/her. VSS Helper gives quick information on this and helps the developer recover this mess, and that too inside VSTS itself.
Background
Most of the .NET projects today are developed using VSTS and VSS as configuration tool. The teams work on different files and do the development. VSTS has already integrated with VSS, wherein the user can check out and check in the file from the IDE. The challenge arises when more than one person wants to work on the same file. VSTS IDE only indicates whether a file has been checked out or not in the solution explorer. The developer will not know who has checked out the file in VSTS, until he goes to VSS and gets the information. ‘VSS helper’ addin comes handy with this functionality and fits snugly within VSTS. This greatly saves the development time for the developers.
This addin tool can be used with any project which suffices the following 2 conditions:
- Using VSTS 2005 for development
- Using VSS as configuration management tool.
Using the Code
I am using the VSS API (ssapi.dll) to get the information from VSS. This API has to be added as reference before running this project. To get the VSS Database path and login details for VSS, an XML file is used. The syntax for the XML file is given below. A sample XML file is also attached with this article.
<xml version="1.0" >
<VSSHelper Databasepath ="#Your VSS database path#"
UserName="#user name#" Password="#password#"
DefaultRootFolder="#Starting folder#"</VSSHelper>
</xml>
The default root folder is the place which is shown to the user when the application starts.
private VSSDatabase vssDatabase = new VSSDatabase();
private bool IsVSSConnected = false;
VSSItem Item; DataSet ds = new DataSet();
private string projectPath = string.Empty;
FileObject fObject = new FileObject();
private string database;
private string userName;
private string password;
private string defaultPath;
private string filePath;
private string xmlFilePath = @"C:\XMLFile2.xml";
On the form load, I get the VSS details from the XML file:
public Form1()
{ try
{
ReadXML();
vssDatabase.Open(this.database, this.userName,this.password);
InitializeComponent();
txtVSSFilePath.Text = this.defaultPath;
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "VSS Helper - Error connecting to VSS");
this.Dispose();
}
}
private void ReadXML()
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
XmlElement root = doc.DocumentElement;
this.database = root.SelectNodes(@"VSSHelper")[0].Attributes[0].Value;
this.userName = root.SelectNodes(@"VSSHelper")[0].Attributes[1].Value;
this.password = root.SelectNodes(@"VSSHelper")[0].Attributes[2].Value;
this.defaultPath = root.SelectNodes(@"VSSHelper")[0].Attributes[3].Value;
}
The following function is called to perform connection with VSS and populate the tree view control. (This tree view control visibility is set to false
and is used internally to get VSS file path information.)
private void ConnectToVSSDatabase()
{
Item = vssDatabase.get_VSSItem(projectPath, false);
TreeNode node = new TreeNode();
node.Text = projectPath;
foreach (VSSItem VSSItem1 in Item.get_Items(false))
{
TreeNode newNode = new TreeNode();
if (VSSItem1.Type == (int)VSSItemType.VSSITEM_PROJECT)
{
string ChildProjectPath = VSSItem1.Spec + "/";
newNode.Text = VSSItem1.Name;
newNode.Name = VSSItem1.Name;
getFiles(ChildProjectPath, ref newNode);
}
else
{
newNode.Text = VSSItem1.Name;
newNode.Name = VSSItem1.Name;
if (VSSItem1.IsCheckedOut > 0)
{
newNode.Name = newNode.Text;
newNode.Text = "~" + newNode.Text;
}
} node.Nodes.Add(newNode);
}
}
private void getFiles(string itemname, ref TreeNode node)
{
VSSItem ItemChild = vssDatabase.get_VSSItem(itemname, false);
foreach (VSSItem VSSItem1 in ItemChild.get_Items(false))
{
if (VSSItem1.Type == (int)VSSItemType.VSSITEM_FILE)
{
TreeNode newNode = new TreeNode();
if (VSSItem1.IsCheckedOut > 0)
{
newNode.Text = "~" + VSSItem1.Name; newNode.Name = VSSItem1.Name;
}
else
{
newNode.Text = VSSItem1.Name;
newNode.Name = VSSItem1.Name;
}
node.Nodes.Add(newNode);
}
else if (VSSItem1.Type == (int)VSSItemType.VSSITEM_PROJECT)
{
string ChildProjectPath = VSSItem1.Spec + "/";
TreeNode newNode = new TreeNode();
newNode.Text = VSSItem1.Name;
newNode.Name = VSSItem1.Name;
node.Nodes.Add(newNode);
getFiles(ChildProjectPath, ref newNode);
}
}
}
The following function shows how to get the VSS file path from the tree view using Tree node find function. Note that the same file can be in different projects. Hence I get all the collections in the array. The details are then stored in a dataset which is finally binded to the grid. This grid is displayed to the user.
private void GetCheckOutByPath()
{
TreeNode[] nodeArray = treeView1.Nodes.Find(filePath, true);
string path = string.Empty;
FileObject fNewObject = new FileObject();
if (nodeArray.Length > 0)
{
foreach (TreeNode node in nodeArray)
{
path = node.FullPath.ToString();
fNewObject = CheckOutBy(path);
if (fNewObject != null)
{
DataRow dr = ds.Tables[0].NewRow();
dr[0] = fNewObject.FileName;
dr[1] = fNewObject.FilePath;
dr[2] = fNewObject.CheckedOutBy;
ds.Tables[0].Rows.Add(dr);
}
}
}
}
The addin also searches if the file name is partly given with wild char (*). The following functions are used to get the file details. These functions are called based on the position of * in the file name.
private void RecursiveStartSearch(TreeNodeCollection nodeCollection)
{
string path = string.Empty;
FileObject fNewObject = new FileObject();
foreach (TreeNode node in nodeCollection)
{
if (node.Name.ToLower().StartsWith(filePath))
{
path = node.FullPath.ToString();
fNewObject = CheckOutBy(path);
if (fNewObject != null)
{
DataRow dr = ds.Tables[0].NewRow();
dr[0] = fNewObject.FileName;
dr[1] = fNewObject.FilePath;
dr[2] = fNewObject.CheckedOutBy;
ds.Tables[0].Rows.Add(dr);
}
}
if (node.GetNodeCount(true) > 0)
this.RecursiveStartSearch(node.Nodes);
}
}
To search with ending character match, use the following function. The same function can be extended to list out all checked out files.
private void RecursiveEndSearch(TreeNodeCollection nodeCollection)
{
string path = string.Empty;
FileObject fNewObject = new FileObject();
foreach (TreeNode node in nodeCollection)
{
if (node.Name.ToLower().EndsWith(filePath))
{
path = node.FullPath.ToString();
fNewObject = CheckOutBy(path);
if (fNewObject != null)
{
DataRow dr = ds.Tables[0].NewRow();
dr[0] = fNewObject.FileName;
dr[1] = fNewObject.FilePath;
dr[2] = fNewObject.CheckedOutBy;
ds.Tables[0].Rows.Add(dr);
}
}
if (node.GetNodeCount(true) > 0)
this.RecursiveEndSearch(node.Nodes);
}
}
Create a new addin in VSTS using the VSTS Addin template wizard. Call this form in the Exec
method in the connect.cs file.
Points of Interest
When the user performs the connection with VSS, I read the entire VSS (from the root folder given in XML) and build a tree view. To get check out information for a file, I used the Tree node find method to get quick information on the VSS file path. This greatly saved time for me to get the check out details. On the other side, for any new files added into VSS, the connection has to be performed again to build the tree view.
History
- 02-Oct-08: Created
- 18-Nov-08: Resolved the problem of back slash if not found in the VSS file path. Added
ConvertSlash
function. Replaced form click event for About information to ? mark. Added a new label for this. - 21-Nov-08: Fixed the following Form Resize issue. Moved the XML file to C:\ Modifying the VSS path when the user clicks FIND Alerting the user when VSS connection is not performed.
- 27-Nov-08: Fixed the following: Modified the form style. Disabling the CONNECT and FIND button while performing connection. Added WORKING status in the title bar when connection is being made.
- 29-Dec-08: Included Wild char search (*). Also added thread while searching so user can see "Working status when search is performed".
I am currently working as programmer in a software company. I focus mostly on Microsoft Products and currently in dot net framework 3.5.