前三篇简单介绍了VSTA的用途以及开发前期准备,这一篇将介绍具体的开发。
我们先实现一个最简单的功能,打开VSTA IDE编程环境。
首先在VSTASAMPLE项目中,添加如下引用:
以及:
Microsoft Development Enviroment 8.0.
DTEProvider 1.0 Type Library
添加HostItemProvider.cs,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.AddIn.Contract;
5
using System.AddIn.Contract.Automation;
6
using System.Runtime.Remoting;
7
using Microsoft.VisualStudio.Tools.Applications.Contract;
8
using Microsoft.VisualStudio.Tools.Applications;
9
10
namespace VSTASample
11
{
12
internal class HostItemProvider : ContractAdapterBase,
13
IHostItemProviderContract
14
{
15
private VSTAApplication application;
16
17
public HostItemProvider( VSTAApplication application,
18
TypeInfrastructureManager typeInfrastructureManager )
19
: base(typeInfrastructureManager)
20
{
21
this.application = application;
22
}
23
24
protected override IContract QueryContract( string contractId )
25
{
26
if(String.Compare(contractId,
27
typeof(IHostItemProviderContract).AssemblyQualifiedName,
28
StringComparison.Ordinal) == 0)
29
{
30
return (IContract)this;
31
}
32
33
return base.QueryContract(contractId);
34
}
35
36
public IRemoteObjectContract GetHostObject( string objectType, string cookie )
37
{
38
if(String.Compare(objectType,
39
typeof(RCS.Common.VSTA.VSTAApplication).FullName,
40
StringComparison.Ordinal) == 0)
41
{
42
RemoteObjectAdapter adapter = new RemoteObjectAdapter(
43
typeof(RCS.Common.VSTA.VSTAApplication),
44
application, TypeInfrastructureManager);
45
return adapter;
46
}
47
48
throw new ArgumentOutOfRangeException();
49
}
50
51
protected override string RemoteToString()
52
{
53
return this.ToString();
54
}
55
56
protected override int GetRemoteHashCode()
57
{
58
return this.GetHashCode();
59
}
60
61
protected override bool RemoteEquals( IContract contract )
62
{
63
if(contract == null)
64
return false;
65
66
if(!System.Runtime.Remoting.RemotingServices.
67
IsObjectOutOfAppDomain(contract))
68
{
69
HostItemProvider contractAdapter =
70
contract as HostItemProvider;
71
return this.Equals(contractAdapter);
72
}
73
74
return false;
75
}
76
}
77
}
78

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

添加一个IDEManagement.cs,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Reflection;
5
using System.Windows.Forms;
6
using Microsoft.VisualStudio.Tools.Applications;
7
using Microsoft.VisualStudio.Tools.Applications.Contract;
8
using Microsoft.VisualStudio.Tools.Applications.DesignTime.Interop;
9
using System.AddIn.Contract.Automation;
10
using EnvDTE80;
11
using VSTADTEProvider.Interop;
12
using System.IO;
13
using System.Collections;
14
using EnvDTE;
15
16
namespace VSTASample
17
{
18
///
19
/// VSTA操作方法类
20
///
21
internal partial class IDEManagement
22
{
23
private VSTAApplication application;
24
//private Context macroContext;
25
//private AddInCollection addInCollection;
26
private IHostItemProviderContract itemProvider;
27
private TypeInfrastructureManager typeInfrastructureManager;
28
private EnvDTE.DTE vstaDTE;
29
private EnvDTE.Project macroProject;
30
//private IEntryPointContract[] hostItems;
31
private string hostID;
32
private string templateName;
33
34
///
35
/// 初始化Extension类的新实例。
36
///
37
internal IDEManagement()
38
{
39
InitializeTypeInfrastructureManager();
40
}
41
42
43
internal void Connect(VSTAApplication application, string hostID,string templateName)
44
{
45
this.application = application;
46
this.application.IDEManagement = this;
47
this.hostID = hostID;
48
this.templateName = templateName;
49
50
this.itemProvider = new HostItemProvider(application,TypeInfrastructureManager);
51
//this.macroPath = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros\bin";
52
//LoadAddIns();
53
//InitializeMenus();
54
55
}
56
57
Internal Properties
67
68
///
69
/// 打开脚本编程环境
70
///
71
/// 脚本程序所在目录
72
/// 脚本程序工程文件名称(*.vbproj)
73
///
74
public bool StartIDE(string projectDirectory, string projectFilename)
75
{
76
EnsureIDE(hostID);
77
if (vstaDTE.MainWindow.Visible)
78
{
79
//vstaDTE.MainWindow.Activate();
80
vstaDTE.MainWindow.SetFocus();
81
return true;
82
}
83
else
84
{
85
vstaDTE.MainWindow.Visible = true;
86
vstaDTE.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMaximize;
87
string projectFilePath = System.IO.Path.Combine(projectDirectory, projectFilename);
88
if (System.IO.File.Exists(projectFilePath))
89
{
90
OpenMacroProject(projectFilePath);
91
}
92
else
93
{
94
try
95
{
96
CreateNewMacroProject(projectDirectory, projectFilename);
97
}
98
catch(Exception e)
99
{
100
MessageBox.Show(
101
e.Message,
102
hostID, MessageBoxButtons.OK, MessageBoxIcon.Error);
103
this.vstaDTE.Quit();
104
vstaDTE = null;
105
return false;
106
}
107
}
108
return true;
109
}
110
}
111
112
private void EnsureIDE(string hostID)
113
{
114
if (this.vstaDTE == null)
115
{
116
try
117
{
118
IDTEProvider dteProvider = new VSTADTEProviderClass();
119
//string HostID = "MyVSTADLLTest";
120
UInt32 TimeOut = 10000;
121
vstaDTE = dteProvider.GetDTE(hostID, TimeOut);
122
System.Diagnostics.Debug.Assert(this.vstaDTE != null);
123
}
124
catch
125
{
126
// If DTEProvider does not work, try co-creating DTE instead.
127
object objDTE = new EnvDTE.DTE();
128
this.vstaDTE = (EnvDTE.DTE)objDTE;
129
}
130
131
//vstaDTE.MainWindow.Visible = true;
132
//增加关闭IDE窗口时关闭vsta.exe进程以及编译
133
EnvDTE.CommandEvents commandEvents = vstaDTE.Events.get_CommandEvents("{00000000-0000-0000-0000-000000000000}", 0);
134
135
commandEvents.BeforeExecute += new EnvDTE._dispCommandEvents_BeforeExecuteEventHandler(commandEvents_BeforeExecute);
136
137
//get and subscribe to the File.Exit event prior to execution
138
EnvDTE.CommandEvents exitCommand = vstaDTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 229);
139
140
exitCommand.BeforeExecute += new EnvDTE._dispCommandEvents_BeforeExecuteEventHandler(exitCommand_BeforeExecute);
141
}
142
}
143
144
///
145
/// 关闭IDE
146
///
147
public void ExitIDE()
148
{
149
if(this.vstaDTE != null)
150
{
151
if(this.vstaDTE.Mode == EnvDTE.vsIDEMode.vsIDEModeDebug)
152
{
153
this.vstaDTE.Debugger.Stop(true);
154
}
155
this.macroProject.Save(null);
156
this.vstaDTE.Quit();
157
}
158
private void CreateNewMacroProject(string projectDirectory, string projectFileName)
159
{
160
Solution2 sol = (Solution2)vstaDTE.Solution;
161
//string projectTemplatePath = @"C:\ShapeAppSamples\VSTATest\templates\VisualBasic\1033\";
162
string projectTemplatePath = sol.GetProjectTemplate(templateName, "VisualBasic");
163
//string targetProjectDirectory = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros";
164
//string targetProjectFilename = "MyEventSampleMacro.vbproj";
165
166
this.vstaDTE.Solution.AddFromTemplate(projectTemplatePath,projectDirectory, projectFileName, true);
167
this.vstaDTE.Solution.SolutionBuild.Build(true);
168
}
169
170
private void OpenMacroProject(string projectFilePath)
171
{
172
//string projectFilePath = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros\MyEventSampleMacro.vbproj";
173
this.macroProject = this.vstaDTE.Solution.AddFromFile(projectFilePath, true);
174
//vstaDTE.MainWindow.Visible = true;
175
}
176
177
EnvDTE.CodeElement FindCodeElementInCodeElements(EnvDTE.CodeElements codeElems, EnvDTE.vsCMElement kind, string fullName)
178
{
179
foreach (EnvDTE.CodeElement codeElem in codeElems)
180
{
181
if (codeElem.Kind == kind)
182
{
183
if (codeElem.FullName == fullName)
184
{
185
if (codeElem.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
186
{
187
EnvDTE.CodeFunction codeFunc = (EnvDTE.CodeFunction)codeElem;
188
if (codeFunc.IsOverloaded)
189
{
190
if (codeFunc.Parameters.Count != 0)
191
{
192
continue;
193
}
194
}
195
}
196
197
return codeElem;
198
}
199
}
200
}
201
202
return null;
203
}
204
private void exitCommand_BeforeExecute( string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault )
205
{
206
//Project.IsDirty is always false, so use .Saved which starts true
207
if(this.macroProject.Saved == true)
208
{
209
//prompt the user to save the project
210
this.macroProject.Save(null);
211
//change the saved state
212
this.macroProject.Saved = false;
213
214
this.vstaDTE.Solution.SolutionBuild.Build(true);
215
}
216
217
//quit the IDE
218
this.vstaDTE.Quit();
219
220
this.vstaDTE = null;
221
}
222
223
private void commandEvents_BeforeExecute( string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault )
224
{
225
EnvDTE.Command objCommand = default(EnvDTE.Command);
226
//string sCommandName = null;
227
228
//break here to check out any commands you are interested in
229
objCommand = vstaDTE.Commands.Item(Guid, ID);
230
231
//if((objCommand != null))
232
//{
233
// sCommandName = objCommand.Name;
234
235
// if(sCommandName.Equals("Something.WorthWatching"))
236
// {
237
// //do something
238
// }
239
//}
240
241
}
242
private void InitializeTypeInfrastructureManager()
243
{
244
if (typeInfrastructureManager == null)
245
{
246
typeInfrastructureManager = new TypeInfrastructureManager();
247
248
// This was auto-generated from ProxyGen with the /h:hostmapfile commandline argument.
249
250
global::System.Type hostType;
251
global::System.Type proxyType;
252
253
254
hostType = typeof(global::VSTASample.VSTAApplication);
255
proxyType = typeof(NonProxiableType<global::VSTASample.VSTAApplication>);
256
typeInfrastructureManager.CanonicalNameToTypeMap.Add("VSTASample, VSTASample.VSTAApplication", proxyType);
257
typeInfrastructureManager.TypeToCanonicalNa垃圾广告p.Add(hostType, "VSTASample, VSTASample.VSTAApplication");
258
}
259
}
260
}
261
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

这里,我们为了方便不同的项目调用,用一个操作类来发布,添加一个VSTAHelper.cs,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Reflection;
5
using EnvDTE;
6
using System.Collections;
7
8
namespace VSTASample
9
{
10
///
11
/// VSTA操作类
12
///
13
public class VSTAHelper
14
{
15
private static VSTAHelper instance;
16
17
///
18
/// VSTAHelper类单一实例
19
///
20
public static VSTAHelper Instance
21
{
22
get
23
{
24
if(VSTAHelper.instance == null)
25
{
26
VSTAHelper.instance = new VSTAHelper();
27
}
28
29
return VSTAHelper.instance;
30
}
31
}
32
33
private VSTAApplication app;
34
///
35
/// 初始化类的实例。
36
///
37
private VSTAHelper()
38
{
39
{
40
app = new VSTAApplication();
41
}
42
}
43
44
///
45
/// 打开脚本编程环境
46
///
47
///
48
/// 脚本程序所在目录(如:C:\ShapeAppSamples\MyVSTADLLTest\Macros)
49
/// 脚本程序工程文件名称(*.vbproj)
50
///
51
/// private VSTAHelper vstaHelper = new VSTAHelper();
52
/// vstaHelper.StartIDE(@"..\Solutions\自动计量\script\Demo","Demo.vbproj");
53
///
54
public void StartIDE( string projectDirectory, string projectFilename )
55
{
56
//using(MessageFilter messageFilter = new MessageFilter())
57
{
58
app.IDEManagement.StartIDE(projectDirectory, projectFilename);
59
}
60
}
61
62
///
63
/// 关闭IDE
64
///
65
///
66
/// private VSTAHelper vstaHelper = new VSTAHelper();
67
/// vstaHelper.ExitIDE();
68
///
69
public void ExitIDE()
70
{
71
app.IDEManagement.ExitIDE();
72
}
73
74
}
75
internal partial class VSTAApplication
76
{
77
private IDEManagement ideManagement;
78
///
79
/// 操作方法类
80
///
81
public IDEManagement IDEManagement
82
{
83
get
84
{
85
if(this.ideManagement == null)
86
{
87
ideManagement = new IDEManagement();
88
ideManagement.Connect(this, "VSTAHelper", "dlladdin.zip");
89
}
90
return ideManagement;
91
}
92
set
93
{
94
ideManagement = value;
95
}
96
}
97
98
}
99
}
100

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

编译生成。
下面就是新建个winform项目,使用操作类即可。