一般的我们都是用VS.NET作为开发环境,因此这个小程序就要成为VS.NET的扩展程序。但编写VS.NET的扩展程序不是很方便,于是我们就想到更方便的扩展VS.NET的方法,那就是VBA.NET。
VBA.NET是扩展VS.NET的方法,是Office的VBA在VS.NET中的延续。使用方便,和VS.NET紧密结合,而且是解释运行,调试方便,而且其中的函数能绑定到VS.NET的工具条和菜单上面,调用方便。
现在说说压缩备份C#工程的流程。以下以VS.NET2003为例子进行说明,本文中的代码也只能处理VS.NET2003的C#工程。用记事本打开一个VS.NET2003的C#工程文件(扩展名为 .csproj ),可以看到这是一个XML文件,但这个XML文件没有XML声明头"<?xml version='1.0' encoding='编码格式' ?>",但它的编码格式是GB2312,而.NET框架加载XML文件时若没有找到XML声明头则使用的默认编码格式是UTF8,因此不能直接使用 System.XML.XmlDocument.Load 加载该文件。在此程序将使用GB2312编码格式(该编码格式在.NET中的代码为936)把C#工程文件当作一个文本文件读取其中所有的文本内容,然后使用System.Xml.XmlDocument.LoadXml 加载XML文档。
C#工程XML文档中,从根节点出发,路径 VisualStudioProject/CSHARP/Build/Referencds/Reference 是指明工程使用的引用,也就是使用的DLL的文件名。而路径 VisualStudioProject/CSHARP/Files/Include/File 则列出了工程中包含的所有的文件。程序将利用这两个信息来获得要拷贝的文件。此时程序拷贝所得的是干净的C#项目,包含在C#项目目录下的其他文件就不拷贝了。
程序把文件拷贝到一个临时目录后就调用WinRar的命令行程序来压缩工程文件。如此完成压缩备份C#工程。
点击VS.NET的菜单项目"工具->宏->宏IDE",打开了VS.NET的VBA.NET的集成开发环境,编写代码,然后切换到VS.NET的IDE,在工具条上右击弹出快捷菜单,选择最下面的"自定义"菜单项目,切换到"命令"页面,在左边的列表中选择"宏",在右边的列表中选中刚刚写好的VBA.NET的函数,然后将其拖拽到VS.NET的工具条上,即可完成工具条按钮和VBA.NET函数的绑定,此后你只有点击这个按钮就能压缩备份你当前编辑的C#工程了,实在是太方便了.以下就是操作过程的演示录像.
完整的VBA.NET源代码为
2 ' 本函数调用 WinRar 软件进行压缩,因此计算机系统必须安装 WinRar
3 ' 程序编制 袁永福(http://www.xdesigner.cn) 2007-8-7
4 Public Sub CreateCSProjectRAR()
5 If CheckCSProject() = False Then
6 Return
7 End If
8 Dim strPath As String
9 Dim myPrj As EnvDTE.Project = DTE.ActiveWindow.Project
10
11 strPath = System.IO.Path.GetFileNameWithoutExtension(myPrj.FullName)
12
13 Dim strFileName As String
14 ' 设置要保存生成的文件的目录
15 strPath = System.IO.Path.Combine( " D:/SourceBack " , strPath & " [ " & System.DateTime.Now.ToString( " yyyy-MM-dd " ) & " ] " )
16 strFileName = strPath & " .rar "
17
18 If System.IO.File.Exists(strFileName) Then
19 System.IO.File.Delete(strFileName)
20 End If
21 Dim iCount As Integer = CopyCSProjectFiles(strPath)
22 If System.IO.File.Exists(strFileName) Then
23 System.IO.File.Delete(strFileName)
24 End If
25 If iCount > 0 Then
26 DTE.StatusBar.Text = " 正在生成压缩文件
27 Dim start As New System.Diagnostics.ProcessStartInfo
28 ' 此处指定 WinRar 压缩软件的可执行文件名,若 WinRar安装在其他的目录则修改此文件名
29 start.FileName = " C:/Program Files/WinRAR/WinRAR.exe "
30 start.Arguments = " a -r -df -ep1 " & strFileName & " " & strPath
31 Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(start)
32 p.WaitForExit()
33 DTE.StatusBar.Text = " 已生成压缩文件 " & strFileName
34 MsgBox ( " 已生成压缩文件 " & strFileName, MsgBoxStyle.Information, " 系统提示 " )
35 End If
36 End Sub
37
38 ' 将当前编辑的VS.NET2003的C#工程整体复制到用户指定的目录下,不支持VS.NET2005
39 Public Sub CopyCSProject()
40
41 ' 检查是否是C#工程
42 If CheckCSProject() = False Then
43 Return
44 End If
45 ' 让用户输入目录
46 Dim strPath As String = InputBox ( " 请输入输出目录名称 " , " 输入 " )
47 If strPath Is Nothing Then
48 Return
49 End If
50 If strPath.Length = 0 Then
51 Return
52 End If
53 ' 复制文件
54 Dim iCount As Integer = CopyCSProjectFiles(strPath)
55
56 MsgBox ( " 共拷贝 " & iCount & " 个文件 " )
57
58 End Sub
59
60 ' 复制当前VS.NET2003的C#工程的所有包含的文件到指定的目录下,不支持VS.NET2005
61 ' 不复制项目中使用绝对路径引用的文件
62 Public Function CopyCSProjectFiles( ByVal strPath As String ) As Integer
63
64 If CheckCSProject() = False Then
65 Return - 1
66 End If
67
68 If System.IO.Directory.Exists(strPath) = False Then
69 System.IO.Directory.CreateDirectory(strPath)
70 End If
71 Dim myPrj As EnvDTE.Project = DTE.ActiveWindow.Project
72
73 ' 加载项目文件
74 Dim myFile As New System.IO.StreamReader(myPrj.FullName, System.Text.Encoding.GetEncoding( 936 ))
75 Dim myDoc As New System.Xml.XmlDocument
76 myDoc.LoadXml(myFile.ReadToEnd())
77 myFile.Close()
78
79 Dim ThisPath As String = System.IO.Path.GetDirectoryName(myPrj.FullName)
80
81 ' 复制项目定义文件本身
82 CopyFile(myPrj.FullName, strPath)
83
84 Dim FileCount As Integer
85 Dim myElement As System.Xml.XmlElement
86 Dim strFileName As String
87 Dim strNewFileName As String
88 ' 复制引用的文件
89 For Each myElement In myDoc.SelectNodes( " VisualStudioProject/CSHARP/Build/Referencds/Reference " )
90 strFileName = myElement.GetAttribute( " HintPath " )
91 If System.IO.Path.IsPathRooted(strFileName) = False Then
92 CopyFile(ThisPath, strPath, strFileName)
93 FileCount = FileCount + 1
94 End If
95 Next
96
97 ' 复制项目文件
98 For Each myElement In myDoc.SelectNodes( " VisualStudioProject/CSHARP/Files/Include/File " )
99 strFileName = myElement.GetAttribute( " RelPath " )
100 If Not strFileName Is Nothing Then
101 If System.IO.Path.IsPathRooted(strFileName) = False Then
102 CopyFile(ThisPath, strPath, strFileName)
103 FileCount = FileCount + 1
104 DTE.StatusBar.Text = FileCount & " 正在复制文件 " & strFileName
105 End If
106 End If
107 Next
108 Return FileCount
109 End Function
110
111
112 ' 检查当前编辑的工程是不是C#工程
113 Public Function CheckCSProject() As Boolean
114 Dim myPrj As EnvDTE.Project = DTE.ActiveWindow.Project
115 If UCase (System.IO.Path.GetExtension(myPrj.FullName)) <> " .CSPROJ " Then
116 MsgBox ( " 当前工程不是 C# 工程 " , MsgBoxStyle.Information, " 系统提示 " )
117 Return False
118 End If
119 Return True
120 End Function
121
122 ' 创建指定的目录
123 Public Sub CreateDirectory( ByVal strDir As String )
124 If System.IO.Directory.Exists(strDir) = False Then
125 System.IO.Directory.CreateDirectory(strDir)
126 End If
127 End Sub
128
129 ' 将指定目录下的指定相对路径的文件复制到另一个目录,保持相对路径不变
130 Public Sub CopyFile( ByVal strPath1 As String , ByVal strPath2 As String , ByVal strFilePath As String )
131 Dim strName1 As String = System.IO.Path.Combine(strPath1, strFilePath)
132 Dim strName2 As String = System.IO.Path.Combine(strPath2, strFilePath)
133
134 Dim dir1 As String = System.IO.Path.GetDirectoryName(strName1)
135 If System.IO.Directory.Exists(dir1) = False Then
136 System.IO.Directory.CreateDirectory(dir1)
137 End If
138
139 Dim dir2 As String = System.IO.Path.GetDirectoryName(strName2)
140 If System.IO.Directory.Exists(dir2) = False Then
141 System.IO.Directory.CreateDirectory(dir2)
142 End If
143
144 System.IO.File.Copy(strName1, strName2, True )
145
146 End Sub
147
148 ' 复制指定的文件到指定的目录下
149 Public Sub CopyFile( ByVal strFileName As String , ByVal strNewPath As String )
150 System.IO.File.Copy(strFileName, System.IO.Path.Combine(strNewPath, System.IO.Path.GetFileName(strFileName)), True )
151 End Sub
152
153