最近整理一些資料,發現以前寫的一段代碼,提供對微軟的版本管理軟件visual sourcesafe的一些操作。以下簡稱vss。
想起以前寫的時候,因為資料比較匱乏,只能邊研究邊測試,走了不少彎路。
由於一些個人的原因(有點健忘,有點懶),一直沒分享出來。今天趁着有點空,刷刷blog。
ps:上一個繪制c語言頭文件包含關系圖的小工具(http://www.cnblogs.com/geeking/p/4021044.html),不知大家發現沒有,bug很多。主要集中在頭文件循環引用和大量節點繪制上。(實驗發現,繪制大量節點時,TreeGX控件最好visible false。貌似控件添加“可看到”節點時會觸發內部刷新操作,而此時又正在添加節點,會引發"System.InvalidOperationException"錯誤)。新版本v2.0稍后更新。
言歸正傳。
.net中要對vss操作,要先引用Interop.SourceSafeTypeLib.dll,還有命名空間 using SourceSafeTypeLib;
額,電腦太垃圾,我就不開vs截圖了。貼下工程文件供參照:
<Reference Include="Interop.SourceSafeTypeLib, Version=5.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Interop.SourceSafeTypeLib.dll</HintPath>
</Reference>
具體對vss的操作我都提取在VSSHelper.cs文件中。
以下是具體內容:(哎,發現自己廢話越來越多了,莫非有向唐僧發展的節奏么)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using SourceSafeTypeLib; 6 using System.IO; 7 using System.Windows.Forms; 8 namespace DockSample 9 { 10 public static class VSSHelper 11 { 12 public static string workPath = ""; 13 private static string root = "$/"; 14 private static VSSDatabaseClass db = new VSSDatabaseClass(); 15 /// <summary> 16 /// 檢查VSS是否打開,已打開返回true,未打開返回false 17 /// </summary> 18 /// <returns></returns> 19 public static bool checkVSSOpen() 20 { 21 try 22 { 23 //VSS未提供標志是否打開的字段 24 //故調用get_VSSItem方法,若拋出異常代碼-2147210253則證明未打開 25 //未拋出異常則證明已經打開連接 26 VSSItem vssItem = db.get_VSSItem(root, false); 27 vssItem = null; 28 return true; 29 } 30 //catch (System.Runtime.InteropServices.COMException comex) 31 //{ 32 // if (comex.ErrorCode == -2147210253) 33 // { 34 // MessageBox.Show("您尚未登錄VSS\r\n請登錄后重試", "錯誤"); 35 // } 36 // return false; 37 //} 38 catch (Exception ex) 39 { 40 System.Diagnostics.Debug.WriteLine(ex.Message); 41 return false; 42 } 43 } 44 /// <summary> 45 /// 打開VSS,返回true成功打開,false未成功打開 46 /// </summary> 47 /// <param name="vssIniPath"></param> 48 /// <param name="user"></param> 49 /// <param name="pwd"></param> 50 /// <returns></returns> 51 public static bool openVSS(string vssIniPath, string user, string pwd) 52 { 53 try 54 { 55 //避免重復打開出錯 56 if (!checkVSSOpen()) 57 { 58 db.Open(vssIniPath, user, pwd); 59 } 60 else 61 { 62 MessageBox.Show("連接已經打開\r\n請勿重復打開", "提示"); 63 } 64 65 66 #region 測試用代碼: 67 //creatSub(@"F:\ceshi", root); 68 //creat(@"F:\ceshi"); 69 #endregion 70 return true; 71 } 72 catch (System.Runtime.InteropServices.COMException comex) 73 { 74 System.Diagnostics.Debug.WriteLine(comex.Message); 75 return false; 76 } 77 catch (Exception ex) 78 { 79 System.Diagnostics.Debug.WriteLine(ex.Message); 80 return false; 81 } 82 } 83 #region 棄用 84 //public static void creat(string parentPath) 85 //{ 86 // //if (workPath == string.Empty) 87 // //{ 88 // // return; 89 // //} 90 // DirectoryInfo dirInfo = new DirectoryInfo(parentPath); 91 // try 92 // { 93 // VSSItem vssItem = db.get_VSSItem(root, false); 94 // vssItem.NewSubproject(dirInfo.Name, "created"); 95 // } 96 // catch (Exception ex) 97 // { 98 // System.Diagnostics.Debug.WriteLine(ex.Message); 99 // } 100 // creatSub(parentPath, root); 101 102 //} 103 #endregion 104 public static bool creatSub(string path, string vssRoot) 105 { 106 if (Directory.Exists(path)) 107 { 108 DirectoryInfo dirInfo = new DirectoryInfo(path); 109 FileInfo[] fileInfos = dirInfo.GetFiles(); 110 DirectoryInfo[] subDirInfos = dirInfo.GetDirectories(); 111 VSSItem vssItem = db.get_VSSItem(vssRoot, false); 112 //將目錄中的所有文件(排除.scc文件)添加到VSS中 113 foreach (FileInfo fileInfo in fileInfos) 114 { 115 try 116 { 117 if (fileInfo.Extension.ToLower() != ".scc") 118 { 119 //添加本地文件到VSS 120 vssItem.Add(fileInfo.FullName, "add", 0); 121 } 122 123 } 124 catch (Exception ex) 125 { 126 System.Diagnostics.Debug.WriteLine(ex.Message); 127 return false; 128 } 129 } 130 //使用遞歸,根據本地目錄結構創建VSS工程目錄結構 131 foreach (DirectoryInfo subDirInfo in subDirInfos) 132 { 133 try 134 { 135 //創建VSS子工程(子目錄) 136 vssItem.NewSubproject(subDirInfo.Name, "created"); 137 //遞歸調用,構建當前處理目錄的下層目錄結構(工程結構) 138 if (!creatSub(subDirInfo.FullName, vssRoot + subDirInfo.Name + "/")) 139 { 140 return false; 141 } 142 } 143 catch (Exception ex) 144 { 145 System.Diagnostics.Debug.WriteLine(ex.Message); 146 return false; 147 } 148 } 149 return true; 150 } 151 else 152 { 153 MessageBox.Show("目錄:" + path + " 不存在", "錯誤"); 154 return false; 155 } 156 } 157 public static bool checkOut(string vssPath, string localPath) 158 { 159 return exeCMD(vssPath, localPath, "checkout"); 160 #region 舍棄 161 //try 162 //{ 163 // VSSItem vssitem = db.get_VSSItem(vssPath, false); 164 // //Type==0 項目文件夾,Type==1 項目文件 165 // //若當前checkout的是單個文件,則checkout后直接返回 166 // if (vssitem.Type == 1) 167 // { 168 // vssitem.Checkout("checkout", localPath, 0); 169 // return true; 170 // } 171 // //若checkout的是一個目錄,則遞歸目錄下的所有文件, 172 // //包括子目錄中的文件。並把所有文件checkout 173 // IVSSItems ivssitems = vssitem.get_Items(false); 174 // //防止Path結構錯誤 175 // localPath = localPath.EndsWith(@"\") ? localPath : localPath + @"\"; 176 // vssPath = vssPath.EndsWith("/") ? vssPath : vssPath + "/"; 177 // foreach (IVSSItem ivssitem in ivssitems) 178 // { 179 // if (ivssitem.Type == 1) 180 // { 181 // //項目文件,直接checkout 182 // ivssitem.Checkout("checkout", localPath + ivssitem.Name, 0); 183 // } 184 // else if (ivssitem.Type == 0) 185 // { 186 // //項目文件夾,遞歸調用checkOut函數 187 // bool temp = checkOut(vssPath + ivssitem.Name, localPath + ivssitem.Name); 188 // if (!temp) 189 // { 190 // return false; 191 // } 192 // } 193 194 // } 195 // return true; 196 //} 197 //catch (Exception ex) 198 //{ 199 // System.Diagnostics.Debug.WriteLine(ex.Message); 200 // return false; 201 //} 202 #endregion 203 } 204 private static bool exeCMD(string vssPath, string localPath, string cmd) 205 { 206 try 207 { 208 VSSItem vssitem = db.get_VSSItem(vssPath, false); 209 //Type==0 項目文件夾,Type==1 項目文件 210 if (vssitem.Type == 1) 211 { 212 switch (cmd.ToLower()) 213 { 214 case "checkout": 215 if (vssitem.IsCheckedOut == 0) 216 { 217 vssitem.Checkout(cmd, localPath, 0); 218 return true; 219 } 220 MessageBox.Show("請勿重復CheckOut", "提示"); 221 return false; 222 case "checkin": 223 if (vssitem.IsCheckedOut != 0) 224 { 225 vssitem.Checkin(cmd, localPath, 0); 226 return true; 227 } 228 MessageBox.Show("請先CheckOut", "提示"); 229 return false; 230 case "get": 231 vssitem.Get(ref localPath, 0); 232 return true; 233 default: 234 break; 235 } 236 237 } 238 IVSSItems ivssitems = vssitem.get_Items(false); 239 //防止Path結構錯誤 240 localPath = localPath.EndsWith(@"\") ? localPath : localPath + @"\"; 241 vssPath = vssPath.EndsWith("/") ? vssPath : vssPath + "/"; 242 foreach (IVSSItem ivssitem in ivssitems) 243 { 244 if (ivssitem.Type == 1) //項目文件 245 { 246 string tmpLocalPath = localPath + ivssitem.Name; 247 switch (cmd.ToLower()) 248 { 249 case "checkout": 250 if (ivssitem.IsCheckedOut == 0) 251 { 252 ivssitem.Checkout(cmd, tmpLocalPath, 0); 253 } 254 break; 255 case "checkin": 256 if (ivssitem.IsCheckedOut != 0) 257 { 258 ivssitem.Checkin(cmd, tmpLocalPath, 0); 259 } 260 break; 261 case "get": 262 ivssitem.Get(ref tmpLocalPath, 0); 263 break; 264 default: 265 break; 266 } 267 } 268 else if (ivssitem.Type == 0) //項目文件夾 269 { 270 //遞歸調用checkin函數 271 bool temp = exeCMD(vssPath + ivssitem.Name, localPath + ivssitem.Name, cmd); 272 if (!temp) 273 { 274 return false; 275 } 276 } 277 278 } 279 return true; 280 } 281 catch (System.Runtime.InteropServices.COMException comex) 282 { 283 if (comex.ErrorCode == -2147210253) 284 { 285 MessageBox.Show("您尚未登錄VSS\r\n請登錄后重試", "錯誤"); 286 FrmVSSLogin frm = new FrmVSSLogin(); 287 frm.ShowDialog(); 288 } 289 return false; 290 } 291 catch (Exception ex) 292 { 293 System.Diagnostics.Debug.WriteLine(ex.Message); 294 return false; 295 } 296 } 297 public static bool checkIn(string vssPath, string localPath) 298 { 299 return exeCMD(vssPath, localPath, "checkin"); 300 #region 舍棄 301 //try 302 //{ 303 // VSSItem vssitem = db.get_VSSItem(vssPath, false); 304 // if (vssitem.Type == 1) 305 // { 306 // //IsCheckedOut==0 未checkout 307 // //若被checkout,則checkin 308 // if (vssitem.IsCheckedOut != 0) 309 // { 310 // //vssitem. 311 // vssitem.Checkin("checkin", localPath, 0); 312 // return true; 313 // } 314 // } 315 // IVSSItems ivssitems = vssitem.get_Items(false); 316 // //防止Path結構錯誤 317 // localPath = localPath.EndsWith(@"\") ? localPath : localPath + @"\"; 318 // vssPath = vssPath.EndsWith("/") ? vssPath : vssPath + "/"; 319 // foreach (IVSSItem ivssitem in ivssitems) 320 // { 321 // if (ivssitem.Type == 1) 322 // { 323 // if (ivssitem.IsCheckedOut != 0) 324 // { 325 // ivssitem.Checkin("checkin", localPath + ivssitem.Name, 0); 326 // } 327 328 // } 329 // else if (ivssitem.Type == 0) 330 // { 331 // //項目文件夾,遞歸調用checkin函數 332 // bool temp = checkIn(vssPath + ivssitem.Name, localPath + ivssitem.Name); 333 // if (!temp) 334 // { 335 // return false; 336 // } 337 // } 338 339 // } 340 // return true; 341 //} 342 //catch (Exception ex) 343 //{ 344 // System.Diagnostics.Debug.WriteLine(ex.Message); 345 // return false; 346 //} 347 #endregion 348 } 349 public static bool get(string vssPath, string localPath) 350 { 351 return exeCMD(vssPath, localPath, "get"); 352 } 353 354 #region 棄用 355 //public static bool checkOut(string vssPath, string localPath, string selectFileName) 356 //{ 357 // try 358 // { 359 // VSSItem vssitem = db.get_VSSItem(vssPath, false); 360 // IVSSItems ivssitems = vssitem.get_Items(false); 361 // localPath = localPath.EndsWith(@"\") ? localPath : localPath + @"\"; 362 // foreach (IVSSItem ivssitem in ivssitems) 363 // { 364 // if (ivssitem.Name == selectFileName) 365 // { 366 // ivssitem.Checkout("checkout", localPath + ivssitem.Name, 0); 367 // } 368 // } 369 // return true; 370 // } 371 // catch (Exception ex) 372 // { 373 // System.Diagnostics.Debug.WriteLine(ex.Message); 374 // return false; 375 // } 376 //} 377 #endregion 378 379 } 380 }
每個函數就不講了,主要是分清vsspath和localpath的區別。
簡單登陸
1 private void btnBrowse_Click(object sender, EventArgs e) 2 { 3 OpenFileDialog ofd = new OpenFileDialog() 4 { 5 Filter = "VSS配置文件|*.ini", 6 Title = "打開VSS數據庫文件" 7 }; 8 if (ofd.ShowDialog() == DialogResult.OK) 9 { 10 tboxVSS.Text = ofd.FileName; 11 } 12 13 } 14 15 private void btnLogin_Click(object sender, EventArgs e) 16 { 17 string[] messboxText ={ 18 "VSS打開錯誤!\r\n請檢查配置重試。", 19 "VSS配置文件不存在!" 20 }; 21 22 if (tboxVSS.Text == "") 23 { 24 return; 25 } 26 if (System.IO.File.Exists(tboxVSS.Text)) 27 { 28 //打開VSS 29 if (VSSHelper.openVSS(tboxVSS.Text, tboxUserName.Text, tboxPassword.Text)) 30 { 31 this.Close(); 32 } 33 else 34 { 35 //if (MessageBox.Show(messboxText[0], "錯誤", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) != DialogResult.Retry) 36 //{ 37 // this.Close(); 38 //} 39 MessageBox.Show(messboxText[0], "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); 40 } 41 } 42 else 43 { 44 MessageBox.Show(messboxText[1], "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); 45 46 } 47 }
checkIn,checkOut 使用:
1 //提交到VSS 2 void menuItemSubmit2Vss_Click(object sender, System.EventArgs e) 3 { 4 if (VSSHelper.checkVSSOpen()) 5 { 6 if (VSSHelper.creatSub(treeVwExplorer.SelectedNode.FullPath, "$/")) 7 { 8 MessageBox.Show("提交成功!", "提示"); 9 } 10 } 11 else 12 { 13 MessageBox.Show("您尚未登錄VSS\r\n請登錄后重試", "錯誤"); 14 FrmVSSLogin frm = new FrmVSSLogin(); 15 frm.ShowDialog(); 16 } 17 18 } 19 //Get右鍵菜單處理事件 20 void menuItemGet_Click(object sender, System.EventArgs e) 21 { 22 string vssPath, localPath; 23 if (matchPath(treeVwExplorer.SelectedNode, out vssPath, out localPath)) 24 { 25 bool result = VSSHelper.get(vssPath, localPath); 26 } 27 } 28 //CheckOut右鍵菜單處理事件 29 void menuItemCheckOut_Click(object sender, System.EventArgs e) 30 { 31 32 string vssPath, localPath; 33 if (matchPath(treeVwExplorer.SelectedNode, out vssPath, out localPath)) 34 { 35 //bool result = VSSHelper.checkOut(vssPath, localPath); 36 if (VSSHelper.checkOut(vssPath, localPath)) 37 { 38 //setTreeNodeColor(treeVwExplorer.SelectedNode, Color.LightBlue); 39 setTreeNodeImg(treeVwExplorer.SelectedNode, true); 40 } 41 } 42 43 44 45 } 46 //CheckIn右鍵菜單處理事件 47 void menuItemCheckIn_Click(object sender, System.EventArgs e) 48 { 49 50 string vssPath, localPath; 51 if (matchPath(treeVwExplorer.SelectedNode, out vssPath, out localPath)) 52 { 53 //bool result = VSSHelper.checkIn(vssPath, localPath); 54 if (VSSHelper.checkIn(vssPath, localPath)) 55 { 56 //setTreeNodeColor(treeVwExplorer.SelectedNode, Color.Transparent); 57 setTreeNodeImg(treeVwExplorer.SelectedNode, false); 58 } 59 } 60 61 62 }
因為是整理東西翻出來的項目中一小塊代碼,就不提供打包下載服務了。O(∩_∩)O哈哈~
有需求的直接使用VSSHelper.cs就好。保證可用。
打完收工。