基于VSTO的Visual SourceSafe 2005二次开发
2008-11-19 21:21
375 查看
1.想办法去down两个文件:IVSSLibrary.dll,Interop.SourceSafeTypeLib.dll
2.上代码。(注:登录、获取最新代码、签出、签入都可以实现,还是有些问题的,这只是一个学习的小Demo)using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using MSProject = Microsoft.Office.Interop.MSProject;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
namespace VSSAddIn
{
public partial class ThisAddIn
{
VssOperate op = new VssOperate();
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.ProjectBeforeSave += new MSProject._EProjectApp2_ProjectBeforeSaveEventHandler(Application_ProjectBeforeSave);
op.AddApplication(this.Application);
if (GetCommand())
{
try
{
ReadConfig();
//登录
if (op.Login())
{
//是否存在版本
if (op.HasFile())
{
//获取最新版本,签出
op.GetNewestFile();
op.CheckOut();
}
//保存文件签入
op.Save();
Application.FileClose(Microsoft.Office.Interop.MSProject.PjSaveType.pjDoNotSave, Type.Missing);
op.CheckIn();
}
else
{//登录失败,另存为文件版本
throw new Exception();
}
}
catch
{
op.SaveAs();
}
}
//等待1秒
System.Threading.Thread.Sleep(1000);
//退出程序
Application.FileExit(Microsoft.Office.Interop.MSProject.PjSaveType.pjSave);
}
private void ReadConfig()
{
Database.UserName = "arden";
Database.UserPassword = "";
Database.IniPath = @"//10.25.6.148/mss/srcsafe.ini";
Database.Name = "VSS";
Database.ProjectPath = @"$/MSS.root/MSS";
Database.TempPath = @"D:/MSS";
op.PathName = Database.TempPath;
op.FileName = "arden.mpp";
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private bool GetCommand()
{
foreach (var com in Environment.GetCommandLineArgs())
{
if (com.ToLower().Equals("/vsscheckin"))
{
return true;
}
}
return true;
}
private void Application_ProjectBeforeSave(MSProject.Project pj, bool SaveAsUi, ref bool Cancel)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IVSSFunctionLibrary;
using IVSSFlags;
using System.Windows.Forms;
using MSProject = Microsoft.Office.Interop.MSProject;
using System.IO;
namespace VSSAddIn
{
public class VssOperate
{
public String FileName { get; set; }
public String PathName { get; set; }
public MSProject.Application App { get; set; }
public String VSSUserName { get; set; }
public String VSSPasswork { get; set; }
public String VSSIniPath { get; set; }
public clIVSSLibrary IVSS = new clIVSSLibrary();
public VSSFlags IVSSFlags = new VSSFlags();
public VssOperate()
{
}
public bool Login()
{
//Open database
IVSS.CloseDB();
var localErr = IVSS.OpenDB(Database.UserName, Database.UserPassword, Database.IniPath);
if (!string.IsNullOrEmpty(localErr))
{
throw new VssLoginException("登录失败");
}
return true;
}
/// <summary>
/// 保存
/// </summary>
public void Save()
{
if (App != null)
App.FileSaveAs(PathName + "//" + FileName, Microsoft.Office.Interop.MSProject.PjFileFormat.pjMPP,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, false, false, false, false, Type.Missing,
false);
}
/// <summary>
/// 另存文件
/// </summary>
/// <remarks>当登录等原因失败后,将文件加上时间戳另存为在Bak文件夹中。</remarks>
public void SaveAs()
{
if (App != null)
App.FileSaveAs(PathName + "//" + App.Name.Replace("<>", "") + DateTime.Now.ToFileTime(), Microsoft.Office.Interop.MSProject.PjFileFormat.pjMPP,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, false, false, false, false, Type.Missing,
false);
}
/// <summary>
/// 签出
/// </summary>
public void CheckOut()
{
long checkOutFlags;
var checkOutFilePath = PathName + "//" + FileName;
var filePath = Database.ProjectPath + "//" + FileName;
//不递归签出
checkOutFlags = IVSSFlags.FlagRecursiveNo();
//
checkOutFlags += IVSSFlags.FlagGetLocalCopyYes();
//
checkOutFlags += IVSSFlags.FlagMultipleCheckOutNo();
checkOutFlags += IVSSFlags.FlagSetFileTimeNow();
//Replace本地
checkOutFlags += IVSSFlags.FlagReplaceLocalReplace();
var comment = string.Empty;
if (!string.IsNullOrEmpty(IVSS.CheckOutItem(filePath,
checkOutFilePath, ref comment, (int)checkOutFlags)))
{
throw new Exception();
}
}
/// <summary>
/// 签入
/// </summary>
public void CheckIn()
{
string userName = string.Empty;
if (!string.IsNullOrEmpty(IVSS.GetUserName(ref userName)))
{
throw new VssInvalidUserException("无此用户名");
}
var checkInFlags = Flags.ForceDirFlag + Flags.CompareFilesFlag;
//Recursive递归
checkInFlags += IVSSFlags.FlagRecursiveYes();
//不移除本地copy
checkInFlags += IVSSFlags.FlagDeleteLocalCopyNo();
//不保持签出
checkInFlags += IVSSFlags.FlagKeepCheckedOutNo();
var checkIn = true;
var checkOutCount = 0;
var checkingInByAdmin = false;
string[,] CheckOutData;
var checkInFilePath = PathName + @"/" + FileName;
var filePath = Database.ProjectPath + "/" + FileName;
var checkedOut = false;
if (!string.IsNullOrEmpty(IVSS.IsFileCheckedOut(filePath, ref checkedOut)))
{
throw new Exception();
}
// File is checked out
if (checkedOut)
{
var checkedOutStatus = 0;
if (!string.IsNullOrEmpty(IVSS.GetCheckOutState(filePath, ref checkedOutStatus)))
{
throw new Exception();
}
// If the file is checked out by the user OR it is checked out to another user
// and we are admin then we can check in the file. It the situation is the later
// then ask Admin if they want to continue
if (!string.IsNullOrEmpty(IVSS.GetUserName(ref userName)))
{
throw new Exception();
}
if (checkedOutStatus == IVSSFlags.FlagCheckedOutMe() || (userName == ConstData.Admin && checkedOutStatus == IVSSFlags.FlagCheckedOut()))
{
//如果非本人签出,取消
if (checkedOutStatus != IVSSFlags.FlagCheckedOutMe())
{
throw new VssCheckedOutException("文件已经被他人签出");
}
if (!string.IsNullOrEmpty(IVSS.GetCheckOutInfo(out CheckOutData, filePath)))
{
throw new Exception();
}
bool isDifferent = false;
var err = IVSS.DoItemsDiffer(filePath, checkInFilePath, ref isDifferent);
if (!string.IsNullOrEmpty(err))
{
throw new Exception();
}
if (!isDifferent && Flags.CheckInUnchangedFilesFlag == IVSSFlags.FlagCheckInUnChangedAsk())
{
//Check in files
checkInFlags += IVSSFlags.FlagCheckInUnChangedYes();
}
else
{
checkInFlags += Flags.CheckInUnchangedFilesFlag;
}
var commentText = string.Empty;
if (checkIn)
{
//签入
err = IVSS.CheckInItem(filePath, checkInFilePath,
ref commentText, (int)checkInFlags);
if (!string.IsNullOrEmpty(err))
{
throw new Exception();
}
}
}
}
}
/// <summary>
/// 获取最新版本
/// </summary>
public void GetNewestFile()
{
var getFlags = IVSSFlags.FlagRecursiveNo();
getFlags += IVSSFlags.FlagSetFileTimeNow();
getFlags += IVSSFlags.FlagReplaceLocalReplace();
var getFilePath = PathName + "//" + FileName;
var filePath = Database.ProjectPath + "//" + FileName;
var str = IVSS.GetItem(filePath, ref getFilePath, (int)getFlags);
if (!string.IsNullOrEmpty(str))
{
throw new Exception("获取最新版本失败!");
}
File.SetAttributes(getFilePath, FileAttributes.Normal);
}
/// <summary>
/// 检查VSS中是否已经存在文件
/// </summary>
/// <returns></returns>
public bool HasFile()
{
return true;
}
public void AddApplication(MSProject.Application application)
{
App = application;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public enum CheckoutItems
{
UserName = 0,
Date = 1,
Version = 2,
Computer = 3,
CheckOutFolder = 4,
Project = 5,
Comment = 6,
ItemName = 7
}
public enum CheckOuts
{
UserName = 0,
CheckOutFolder = 1,
Version = 2,
Date = 3
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
/// <summary>
/// 登录出错
/// </summary>
public class VssLoginException : Exception
{
public VssLoginException()
{
}
public VssLoginException(string message)
: base(message)
{
}
}
public class VssInvalidUserException : Exception
{
public VssInvalidUserException()
{
}
public VssInvalidUserException(string message)
: base(message)
{
}
}
public class VssCheckedOutException : Exception
{
public VssCheckedOutException()
{
}
public VssCheckedOutException(string message)
: base(message)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public static class Database
{
/// <summary>
/// VSS数据库名
/// </summary>
public static String Name { get; set; }
/// <summary>
/// 用户名
/// </summary>
public static String UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public static String UserPassword { get; set; }
/// <summary>
/// 配置文件路径
/// </summary>
public static String IniPath { get; set; }
/// <summary>
/// 本地映射路径
/// </summary>
public static String TempPath { get; set; }
/// <summary>
/// VSS服务器上路径
/// </summary>
public static String ProjectPath { get; set; }
}
public class ConstData
{
public const string Admin = "管理员";
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public class Flags
{
// Global Flags
public static long CheckInUnchangedFilesFlag { get; set; }
public static long CompareFilesFlag { get; set; }
public static Boolean CreateEventLog { get; set; }
public static Boolean CreateOutputLog { get; set; }
public static Int32 CurrentControl { get; set; }
public static String DoubleClickFile { get; set; }
public static long EolCharacter { get; set; }
public static long ForceDirFlag { get; set; }
public static Boolean IncludeDeletedItems { get; set; }
public static Boolean WarnCheckOutAnAlreadyCheckedOutFile { get; set; }
public static Boolean WarnDeleteAFileOrProject { get; set; }
public static Boolean WarnDestroyFileOrProject { get; set; }
public static Boolean WarnExitSample { get; set; }
public static Boolean WarnPurgeFileOrProject { get; set; }
public static Boolean WarnUndoCheckOutOfModifiedFile { get; set; }
}
}
2.上代码。(注:登录、获取最新代码、签出、签入都可以实现,还是有些问题的,这只是一个学习的小Demo)using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using MSProject = Microsoft.Office.Interop.MSProject;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
namespace VSSAddIn
{
public partial class ThisAddIn
{
VssOperate op = new VssOperate();
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.ProjectBeforeSave += new MSProject._EProjectApp2_ProjectBeforeSaveEventHandler(Application_ProjectBeforeSave);
op.AddApplication(this.Application);
if (GetCommand())
{
try
{
ReadConfig();
//登录
if (op.Login())
{
//是否存在版本
if (op.HasFile())
{
//获取最新版本,签出
op.GetNewestFile();
op.CheckOut();
}
//保存文件签入
op.Save();
Application.FileClose(Microsoft.Office.Interop.MSProject.PjSaveType.pjDoNotSave, Type.Missing);
op.CheckIn();
}
else
{//登录失败,另存为文件版本
throw new Exception();
}
}
catch
{
op.SaveAs();
}
}
//等待1秒
System.Threading.Thread.Sleep(1000);
//退出程序
Application.FileExit(Microsoft.Office.Interop.MSProject.PjSaveType.pjSave);
}
private void ReadConfig()
{
Database.UserName = "arden";
Database.UserPassword = "";
Database.IniPath = @"//10.25.6.148/mss/srcsafe.ini";
Database.Name = "VSS";
Database.ProjectPath = @"$/MSS.root/MSS";
Database.TempPath = @"D:/MSS";
op.PathName = Database.TempPath;
op.FileName = "arden.mpp";
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private bool GetCommand()
{
foreach (var com in Environment.GetCommandLineArgs())
{
if (com.ToLower().Equals("/vsscheckin"))
{
return true;
}
}
return true;
}
private void Application_ProjectBeforeSave(MSProject.Project pj, bool SaveAsUi, ref bool Cancel)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IVSSFunctionLibrary;
using IVSSFlags;
using System.Windows.Forms;
using MSProject = Microsoft.Office.Interop.MSProject;
using System.IO;
namespace VSSAddIn
{
public class VssOperate
{
public String FileName { get; set; }
public String PathName { get; set; }
public MSProject.Application App { get; set; }
public String VSSUserName { get; set; }
public String VSSPasswork { get; set; }
public String VSSIniPath { get; set; }
public clIVSSLibrary IVSS = new clIVSSLibrary();
public VSSFlags IVSSFlags = new VSSFlags();
public VssOperate()
{
}
public bool Login()
{
//Open database
IVSS.CloseDB();
var localErr = IVSS.OpenDB(Database.UserName, Database.UserPassword, Database.IniPath);
if (!string.IsNullOrEmpty(localErr))
{
throw new VssLoginException("登录失败");
}
return true;
}
/// <summary>
/// 保存
/// </summary>
public void Save()
{
if (App != null)
App.FileSaveAs(PathName + "//" + FileName, Microsoft.Office.Interop.MSProject.PjFileFormat.pjMPP,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, false, false, false, false, Type.Missing,
false);
}
/// <summary>
/// 另存文件
/// </summary>
/// <remarks>当登录等原因失败后,将文件加上时间戳另存为在Bak文件夹中。</remarks>
public void SaveAs()
{
if (App != null)
App.FileSaveAs(PathName + "//" + App.Name.Replace("<>", "") + DateTime.Now.ToFileTime(), Microsoft.Office.Interop.MSProject.PjFileFormat.pjMPP,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, false, false, false, false, Type.Missing,
false);
}
/// <summary>
/// 签出
/// </summary>
public void CheckOut()
{
long checkOutFlags;
var checkOutFilePath = PathName + "//" + FileName;
var filePath = Database.ProjectPath + "//" + FileName;
//不递归签出
checkOutFlags = IVSSFlags.FlagRecursiveNo();
//
checkOutFlags += IVSSFlags.FlagGetLocalCopyYes();
//
checkOutFlags += IVSSFlags.FlagMultipleCheckOutNo();
checkOutFlags += IVSSFlags.FlagSetFileTimeNow();
//Replace本地
checkOutFlags += IVSSFlags.FlagReplaceLocalReplace();
var comment = string.Empty;
if (!string.IsNullOrEmpty(IVSS.CheckOutItem(filePath,
checkOutFilePath, ref comment, (int)checkOutFlags)))
{
throw new Exception();
}
}
/// <summary>
/// 签入
/// </summary>
public void CheckIn()
{
string userName = string.Empty;
if (!string.IsNullOrEmpty(IVSS.GetUserName(ref userName)))
{
throw new VssInvalidUserException("无此用户名");
}
var checkInFlags = Flags.ForceDirFlag + Flags.CompareFilesFlag;
//Recursive递归
checkInFlags += IVSSFlags.FlagRecursiveYes();
//不移除本地copy
checkInFlags += IVSSFlags.FlagDeleteLocalCopyNo();
//不保持签出
checkInFlags += IVSSFlags.FlagKeepCheckedOutNo();
var checkIn = true;
var checkOutCount = 0;
var checkingInByAdmin = false;
string[,] CheckOutData;
var checkInFilePath = PathName + @"/" + FileName;
var filePath = Database.ProjectPath + "/" + FileName;
var checkedOut = false;
if (!string.IsNullOrEmpty(IVSS.IsFileCheckedOut(filePath, ref checkedOut)))
{
throw new Exception();
}
// File is checked out
if (checkedOut)
{
var checkedOutStatus = 0;
if (!string.IsNullOrEmpty(IVSS.GetCheckOutState(filePath, ref checkedOutStatus)))
{
throw new Exception();
}
// If the file is checked out by the user OR it is checked out to another user
// and we are admin then we can check in the file. It the situation is the later
// then ask Admin if they want to continue
if (!string.IsNullOrEmpty(IVSS.GetUserName(ref userName)))
{
throw new Exception();
}
if (checkedOutStatus == IVSSFlags.FlagCheckedOutMe() || (userName == ConstData.Admin && checkedOutStatus == IVSSFlags.FlagCheckedOut()))
{
//如果非本人签出,取消
if (checkedOutStatus != IVSSFlags.FlagCheckedOutMe())
{
throw new VssCheckedOutException("文件已经被他人签出");
}
if (!string.IsNullOrEmpty(IVSS.GetCheckOutInfo(out CheckOutData, filePath)))
{
throw new Exception();
}
bool isDifferent = false;
var err = IVSS.DoItemsDiffer(filePath, checkInFilePath, ref isDifferent);
if (!string.IsNullOrEmpty(err))
{
throw new Exception();
}
if (!isDifferent && Flags.CheckInUnchangedFilesFlag == IVSSFlags.FlagCheckInUnChangedAsk())
{
//Check in files
checkInFlags += IVSSFlags.FlagCheckInUnChangedYes();
}
else
{
checkInFlags += Flags.CheckInUnchangedFilesFlag;
}
var commentText = string.Empty;
if (checkIn)
{
//签入
err = IVSS.CheckInItem(filePath, checkInFilePath,
ref commentText, (int)checkInFlags);
if (!string.IsNullOrEmpty(err))
{
throw new Exception();
}
}
}
}
}
/// <summary>
/// 获取最新版本
/// </summary>
public void GetNewestFile()
{
var getFlags = IVSSFlags.FlagRecursiveNo();
getFlags += IVSSFlags.FlagSetFileTimeNow();
getFlags += IVSSFlags.FlagReplaceLocalReplace();
var getFilePath = PathName + "//" + FileName;
var filePath = Database.ProjectPath + "//" + FileName;
var str = IVSS.GetItem(filePath, ref getFilePath, (int)getFlags);
if (!string.IsNullOrEmpty(str))
{
throw new Exception("获取最新版本失败!");
}
File.SetAttributes(getFilePath, FileAttributes.Normal);
}
/// <summary>
/// 检查VSS中是否已经存在文件
/// </summary>
/// <returns></returns>
public bool HasFile()
{
return true;
}
public void AddApplication(MSProject.Application application)
{
App = application;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public enum CheckoutItems
{
UserName = 0,
Date = 1,
Version = 2,
Computer = 3,
CheckOutFolder = 4,
Project = 5,
Comment = 6,
ItemName = 7
}
public enum CheckOuts
{
UserName = 0,
CheckOutFolder = 1,
Version = 2,
Date = 3
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
/// <summary>
/// 登录出错
/// </summary>
public class VssLoginException : Exception
{
public VssLoginException()
{
}
public VssLoginException(string message)
: base(message)
{
}
}
public class VssInvalidUserException : Exception
{
public VssInvalidUserException()
{
}
public VssInvalidUserException(string message)
: base(message)
{
}
}
public class VssCheckedOutException : Exception
{
public VssCheckedOutException()
{
}
public VssCheckedOutException(string message)
: base(message)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public static class Database
{
/// <summary>
/// VSS数据库名
/// </summary>
public static String Name { get; set; }
/// <summary>
/// 用户名
/// </summary>
public static String UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public static String UserPassword { get; set; }
/// <summary>
/// 配置文件路径
/// </summary>
public static String IniPath { get; set; }
/// <summary>
/// 本地映射路径
/// </summary>
public static String TempPath { get; set; }
/// <summary>
/// VSS服务器上路径
/// </summary>
public static String ProjectPath { get; set; }
}
public class ConstData
{
public const string Admin = "管理员";
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSSAddIn
{
public class Flags
{
// Global Flags
public static long CheckInUnchangedFilesFlag { get; set; }
public static long CompareFilesFlag { get; set; }
public static Boolean CreateEventLog { get; set; }
public static Boolean CreateOutputLog { get; set; }
public static Int32 CurrentControl { get; set; }
public static String DoubleClickFile { get; set; }
public static long EolCharacter { get; set; }
public static long ForceDirFlag { get; set; }
public static Boolean IncludeDeletedItems { get; set; }
public static Boolean WarnCheckOutAnAlreadyCheckedOutFile { get; set; }
public static Boolean WarnDeleteAFileOrProject { get; set; }
public static Boolean WarnDestroyFileOrProject { get; set; }
public static Boolean WarnExitSample { get; set; }
public static Boolean WarnPurgeFileOrProject { get; set; }
public static Boolean WarnUndoCheckOutOfModifiedFile { get; set; }
}
}
相关文章推荐
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- Visual Studio2005 + Visual SourceSafe 6.0 实现团队开发
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- 应用Microsoft Visual SourceSafe组织软件开发项目
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- 应用Microsoft Visual SourceSafe组织软件开发项目
- 不同网段之间的通过Visual sourcesafe 8.0协作开发
- Visual SourceSafe如何支持并行开发
- 用 Visual Studio.NET 和 Visual SourceSafe 进行团队开发
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、
- 应用Microsoft Visual SourceSafe组织软件开发项目
- 抛弃强大的TFS ,借助于BugTracker.NET + Visual Source Safe + SourceLink搭建项目开发环境
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发
- Visual SourceSafe如何支持并行开发
- Visual Studio2005 + Visual SourceSafe 2005 实现团队开发、源代码管理、版本控制