OLD | NEW |
| (Empty) |
1 /// Copyright (c) Microsoft Corporation. All rights reserved. | |
2 | |
3 using System; | |
4 using System.Collections.Generic; | |
5 using System.Diagnostics; | |
6 using System.Globalization; | |
7 using System.IO; | |
8 using System.Reflection; | |
9 using System.Runtime.InteropServices; | |
10 using System.Text; | |
11 using Microsoft.VisualStudio; | |
12 using Microsoft.VisualStudio.Shell.Interop; | |
13 using MSBuild = Microsoft.Build.BuildEngine; | |
14 using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants; | |
15 using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID; | |
16 using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID; | |
17 | |
18 namespace Microsoft.VisualStudio.Project | |
19 { | |
20 [CLSCompliant(false), ComVisible(true)] | |
21 public class ReferenceContainerNode : HierarchyNode, IReferenceContainer | |
22 { | |
23 #region fields | |
24 internal const string ReferencesNodeVirtualName = "References"; | |
25 #endregion | |
26 | |
27 #region ctor | |
28 public ReferenceContainerNode(ProjectNode root) | |
29 : base(root) | |
30 { | |
31 this.VirtualNodeName = ReferencesNodeVirtualName; | |
32 this.ExcludeNodeFromScc = true; | |
33 } | |
34 #endregion | |
35 | |
36 #region Properties | |
37 private static string[] supportedReferenceTypes = new string[] { | |
38 ProjectFileConstants.ProjectReference, | |
39 ProjectFileConstants.Reference, | |
40 ProjectFileConstants.COMReference | |
41 }; | |
42 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Perf
ormance", "CA1819:PropertiesShouldNotReturnArrays")] | |
43 protected virtual string[] SupportedReferenceTypes | |
44 { | |
45 get { return supportedReferenceTypes; } | |
46 } | |
47 #endregion | |
48 | |
49 #region overridden properties | |
50 public override int SortPriority | |
51 { | |
52 get | |
53 { | |
54 return DefaultSortOrderNode.ReferenceContainerNo
de; | |
55 } | |
56 } | |
57 | |
58 public override int MenuCommandId | |
59 { | |
60 get { return VsMenus.IDM_VS_CTXT_REFERENCEROOT; } | |
61 } | |
62 | |
63 | |
64 public override Guid ItemTypeGuid | |
65 { | |
66 get { return VSConstants.GUID_ItemType_VirtualFolder; } | |
67 } | |
68 | |
69 | |
70 public override string Url | |
71 { | |
72 get { return this.VirtualNodeName; } | |
73 } | |
74 | |
75 public override string Caption | |
76 { | |
77 get | |
78 { | |
79 return SR.GetString(SR.ReferencesNodeName, Cultu
reInfo.CurrentUICulture); | |
80 } | |
81 } | |
82 | |
83 | |
84 private Automation.OAReferences references; | |
85 internal override object Object | |
86 { | |
87 get | |
88 { | |
89 if(null == references) | |
90 { | |
91 references = new Automation.OAReferences
(this); | |
92 } | |
93 return references; | |
94 } | |
95 } | |
96 | |
97 #endregion | |
98 | |
99 #region overridden methods | |
100 /// <summary> | |
101 /// Returns an instance of the automation object for ReferenceCo
ntainerNode | |
102 /// </summary> | |
103 /// <returns>An intance of the Automation.OAReferenceFolderItem
type if succeeeded</returns> | |
104 public override object GetAutomationObject() | |
105 { | |
106 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed) | |
107 { | |
108 return null; | |
109 } | |
110 | |
111 return new Automation.OAReferenceFolderItem(this.Project
Mgr.GetAutomationObject() as Automation.OAProject, this); | |
112 } | |
113 | |
114 /// <summary> | |
115 /// Disable inline editing of Caption of a ReferendeContainerNod
e | |
116 /// </summary> | |
117 /// <returns>null</returns> | |
118 public override string GetEditLabel() | |
119 { | |
120 return null; | |
121 } | |
122 | |
123 | |
124 public override object GetIconHandle(bool open) | |
125 { | |
126 return this.ProjectMgr.ImageHandler.GetIconHandle(open ?
(int)ProjectNode.ImageName.OpenReferenceFolder : (int)ProjectNode.ImageName.Ref
erenceFolder); | |
127 } | |
128 | |
129 | |
130 /// <summary> | |
131 /// References node cannot be dragged. | |
132 /// </summary> | |
133 /// <returns>A stringbuilder.</returns> | |
134 protected internal override StringBuilder PrepareSelectedNodesFo
rClipBoard() | |
135 { | |
136 return null; | |
137 } | |
138 | |
139 /// <summary> | |
140 /// Not supported. | |
141 /// </summary> | |
142 protected override int ExcludeFromProject() | |
143 { | |
144 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED; | |
145 } | |
146 | |
147 protected override int QueryStatusOnNode(Guid cmdGroup, uint cmd
, IntPtr pCmdText, ref QueryStatusResult result) | |
148 { | |
149 if(cmdGroup == VsMenus.guidStandardCommandSet97) | |
150 { | |
151 switch((VsCommands)cmd) | |
152 { | |
153 case VsCommands.AddNewItem: | |
154 case VsCommands.AddExistingItem: | |
155 result |= QueryStatusResult.SUPP
ORTED | QueryStatusResult.ENABLED; | |
156 return VSConstants.S_OK; | |
157 } | |
158 } | |
159 else if(cmdGroup == VsMenus.guidStandardCommandSet2K) | |
160 { | |
161 if((VsCommands2K)cmd == VsCommands2K.ADDREFERENC
E) | |
162 { | |
163 result |= QueryStatusResult.SUPPORTED |
QueryStatusResult.ENABLED; | |
164 return VSConstants.S_OK; | |
165 } | |
166 } | |
167 else | |
168 { | |
169 return (int)OleConstants.OLECMDERR_E_UNKNOWNGROU
P; | |
170 } | |
171 return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, r
ef result); | |
172 } | |
173 | |
174 protected override int ExecCommandOnNode(Guid cmdGroup, uint cmd
, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) | |
175 { | |
176 if(cmdGroup == VsMenus.guidStandardCommandSet2K) | |
177 { | |
178 switch((VsCommands2K)cmd) | |
179 { | |
180 case VsCommands2K.ADDREFERENCE: | |
181 return this.ProjectMgr.AddProjec
tReference(); | |
182 case VsCommands2K.ADDWEBREFERENCE: | |
183 return this.ProjectMgr.AddWebRef
erence(); | |
184 } | |
185 } | |
186 | |
187 return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt
, pvaIn, pvaOut); | |
188 } | |
189 | |
190 protected override bool CanDeleteItem(__VSDELETEITEMOPERATION de
leteOperation) | |
191 { | |
192 return false; | |
193 } | |
194 | |
195 /// <summary> | |
196 /// Defines whether this node is valid node for painting the ref
ererences icon. | |
197 /// </summary> | |
198 /// <returns></returns> | |
199 protected override bool CanShowDefaultIcon() | |
200 { | |
201 if(!String.IsNullOrEmpty(this.VirtualNodeName)) | |
202 { | |
203 return true; | |
204 } | |
205 return false; | |
206 } | |
207 | |
208 #endregion | |
209 | |
210 #region IReferenceContainer | |
211 public IList<ReferenceNode> EnumReferences() | |
212 { | |
213 List<ReferenceNode> refs = new List<ReferenceNode>(); | |
214 for(HierarchyNode node = this.FirstChild; node != null;
node = node.NextSibling) | |
215 { | |
216 ReferenceNode refNode = node as ReferenceNode; | |
217 if(refNode != null) | |
218 { | |
219 refs.Add(refNode); | |
220 } | |
221 } | |
222 | |
223 return refs; | |
224 } | |
225 /// <summary> | |
226 /// Adds references to this container from a MSBuild project. | |
227 /// </summary> | |
228 public void LoadReferencesFromBuildProject(MSBuild.Project build
Project) | |
229 { | |
230 foreach(string referenceType in SupportedReferenceTypes) | |
231 { | |
232 MSBuild.BuildItemGroup refererncesGroup = buildP
roject.GetEvaluatedItemsByName(referenceType); | |
233 | |
234 bool isAssemblyReference = referenceType == Proj
ectFileConstants.Reference; | |
235 // If the project was loaded for browsing we sho
uld still create the nodes but as not resolved. | |
236 if(this.ProjectMgr.HasPassedSecurityChecks && is
AssemblyReference && this.ProjectMgr.Build(MsBuildTarget.ResolveAssemblyReferenc
es) != MSBuildResult.Successful) | |
237 { | |
238 continue; | |
239 } | |
240 | |
241 foreach(MSBuild.BuildItem item in refererncesGro
up) | |
242 { | |
243 ProjectElement element = new ProjectElem
ent(this.ProjectMgr, item, false); | |
244 | |
245 ReferenceNode node = CreateReferenceNode
(referenceType, element); | |
246 | |
247 if(node != null) | |
248 { | |
249 // Make sure that we do not want
to add the item twice to the ui hierarchy | |
250 // We are using here the UI repr
esentation of the Node namely the Caption to find that out, in order to | |
251 // avoid different representatio
n problems. | |
252 // Example :<Reference Include="
EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | |
253 // <Reference Inc
lude="EnvDTE80" /> | |
254 bool found = false; | |
255 for(HierarchyNode n = this.First
Child; n != null && !found; n = n.NextSibling) | |
256 { | |
257 if(String.Compare(n.Capt
ion, node.Caption, StringComparison.OrdinalIgnoreCase) == 0) | |
258 { | |
259 found = true; | |
260 } | |
261 } | |
262 | |
263 if(!found) | |
264 { | |
265 this.AddChild(node); | |
266 } | |
267 } | |
268 } | |
269 } | |
270 } | |
271 | |
272 /// <summary> | |
273 /// Adds a reference to this container using the selector data s
tructure to identify it. | |
274 /// </summary> | |
275 /// <param name="selectorData">data describing selected componen
t</param> | |
276 /// <returns>Reference in case of a valid reference node has bee
n created. Otherwise null</returns> | |
277 public ReferenceNode AddReferenceFromSelectorData(VSCOMPONENTSEL
ECTORDATA selectorData) | |
278 { | |
279 //Make sure we can edit the project file | |
280 if(!this.ProjectMgr.QueryEditProjectFile(false)) | |
281 { | |
282 throw Marshal.GetExceptionForHR(VSConstants.OLE_
E_PROMPTSAVECANCELLED); | |
283 } | |
284 | |
285 //Create the reference node | |
286 ReferenceNode node = null; | |
287 try | |
288 { | |
289 node = CreateReferenceNode(selectorData); | |
290 } | |
291 catch(ArgumentException) | |
292 { | |
293 // Some selector data was not valid. | |
294 } | |
295 | |
296 //Add the reference node to the project if we have a val
id reference node | |
297 if(node != null) | |
298 { | |
299 // This call will find if the reference is in th
e project and, in this case | |
300 // will not add it again, so the parent node wil
l not be set. | |
301 node.AddReference(); | |
302 if(null == node.Parent) | |
303 { | |
304 // The reference was not added, so we ca
n not return this item because it | |
305 // is not inside the project. | |
306 return null; | |
307 } | |
308 } | |
309 | |
310 return node; | |
311 } | |
312 #endregion | |
313 | |
314 #region virtual methods | |
315 protected virtual ReferenceNode CreateReferenceNode(string refer
enceType, ProjectElement element) | |
316 { | |
317 ReferenceNode node = null; | |
318 if(referenceType == ProjectFileConstants.COMReference) | |
319 { | |
320 node = this.CreateComReferenceNode(element); | |
321 } | |
322 else if(referenceType == ProjectFileConstants.Reference) | |
323 { | |
324 node = this.CreateAssemblyReferenceNode(element)
; | |
325 } | |
326 else if(referenceType == ProjectFileConstants.ProjectRef
erence) | |
327 { | |
328 node = this.CreateProjectReferenceNode(element); | |
329 } | |
330 | |
331 return node; | |
332 } | |
333 | |
334 protected virtual ReferenceNode CreateReferenceNode(VSCOMPONENTS
ELECTORDATA selectorData) | |
335 { | |
336 ReferenceNode node = null; | |
337 switch(selectorData.type) | |
338 { | |
339 case VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project: | |
340 node = this.CreateProjectReferenceNode(s
electorData); | |
341 break; | |
342 case VSCOMPONENTTYPE.VSCOMPONENTTYPE_File: | |
343 // This is the case for managed assembly | |
344 case VSCOMPONENTTYPE.VSCOMPONENTTYPE_ComPlus: | |
345 node = this.CreateFileComponent(selector
Data); | |
346 break; | |
347 case VSCOMPONENTTYPE.VSCOMPONENTTYPE_Com2: | |
348 node = this.CreateComReferenceNode(selec
torData); | |
349 break; | |
350 } | |
351 | |
352 return node; | |
353 } | |
354 #endregion | |
355 | |
356 #region Helper functions to add references | |
357 /// <summary> | |
358 /// Creates a project reference node given an existing project e
lement. | |
359 /// </summary> | |
360 protected virtual ProjectReferenceNode CreateProjectReferenceNod
e(ProjectElement element) | |
361 { | |
362 return new ProjectReferenceNode(this.ProjectMgr, element
); | |
363 } | |
364 /// <summary> | |
365 /// Create a Project to Project reference given a VSCOMPONENTSEL
ECTORDATA structure | |
366 /// </summary> | |
367 protected virtual ProjectReferenceNode CreateProjectReferenceNod
e(VSCOMPONENTSELECTORDATA selectorData) | |
368 { | |
369 return new ProjectReferenceNode(this.ProjectMgr, selecto
rData.bstrTitle, selectorData.bstrFile, selectorData.bstrProjRef); | |
370 } | |
371 | |
372 /// <summary> | |
373 /// Creates an assemby or com reference node given a selector da
ta. | |
374 /// </summary> | |
375 protected virtual ReferenceNode CreateFileComponent(VSCOMPONENTS
ELECTORDATA selectorData) | |
376 { | |
377 if(null == selectorData.bstrFile) | |
378 { | |
379 throw new ArgumentNullException("selectorData"); | |
380 } | |
381 | |
382 // We have a path to a file, it could be anything | |
383 // First see if it is a managed assembly | |
384 bool tryToCreateAnAssemblyReference = true; | |
385 if(File.Exists(selectorData.bstrFile)) | |
386 { | |
387 try | |
388 { | |
389 // We should not load the assembly in th
e current appdomain. | |
390 // If we do not do it like that and we l
oad the assembly in the current appdomain then the assembly cannot be unloaded a
gain. | |
391 // The following problems might arose in
that case. | |
392 // 1. Assume that a user is extending th
e MPF and his project is creating a managed assembly dll. | |
393 // 2. The user opens VS and creates a pr
oject and builds it. | |
394 // 3. Then the user opens VS creates ano
ther project and adds a reference to the previously built assembly. This will lo
ad the assembly in the appdomain had we been using Assembly.ReflectionOnlyLoadFr
om. | |
395 // 4. Then he goes back to the first pro
ject modifies it an builds it. A build error is issued that the assembly is used
. | |
396 | |
397 // GetAssemblyName is assured not to loa
d the assembly. | |
398 tryToCreateAnAssemblyReference = (Assemb
lyName.GetAssemblyName(selectorData.bstrFile) != null); | |
399 } | |
400 catch(BadImageFormatException) | |
401 { | |
402 // We have found the file and it is not
a .NET assembly; no need to try to | |
403 // load it again. | |
404 tryToCreateAnAssemblyReference = false; | |
405 } | |
406 catch(FileLoadException) | |
407 { | |
408 // We must still try to load from here b
ecause this exception is thrown if we want | |
409 // to add the same assembly refererence
from different locations. | |
410 tryToCreateAnAssemblyReference = true; | |
411 } | |
412 } | |
413 | |
414 ReferenceNode node = null; | |
415 | |
416 if(tryToCreateAnAssemblyReference) | |
417 { | |
418 // This might be a candidate for an assembly ref
erence node. Try to load it. | |
419 // CreateAssemblyReferenceNode will suppress Bad
ImageFormatException if the node cannot be created. | |
420 node = this.CreateAssemblyReferenceNode(selector
Data.bstrFile); | |
421 } | |
422 | |
423 // If no node has been created try to create a com refer
ence node. | |
424 if(node == null) | |
425 { | |
426 if(!File.Exists(selectorData.bstrFile)) | |
427 { | |
428 return null; | |
429 } | |
430 node = this.CreateComReferenceNode(selectorData)
; | |
431 } | |
432 | |
433 return node; | |
434 } | |
435 | |
436 /// <summary> | |
437 /// Creates an assembly refernce node from a project element. | |
438 /// </summary> | |
439 protected virtual AssemblyReferenceNode CreateAssemblyReferenceN
ode(ProjectElement element) | |
440 { | |
441 AssemblyReferenceNode node = null; | |
442 try | |
443 { | |
444 node = new AssemblyReferenceNode(this.ProjectMgr
, element); | |
445 } | |
446 catch(ArgumentNullException e) | |
447 { | |
448 Trace.WriteLine("Exception : " + e.Message); | |
449 } | |
450 catch(FileNotFoundException e) | |
451 { | |
452 Trace.WriteLine("Exception : " + e.Message); | |
453 } | |
454 catch(BadImageFormatException e) | |
455 { | |
456 Trace.WriteLine("Exception : " + e.Message); | |
457 } | |
458 catch(FileLoadException e) | |
459 { | |
460 Trace.WriteLine("Exception : " + e.Message); | |
461 } | |
462 catch(System.Security.SecurityException e) | |
463 { | |
464 Trace.WriteLine("Exception : " + e.Message); | |
465 } | |
466 | |
467 return node; | |
468 } | |
469 /// <summary> | |
470 /// Creates an assembly reference node from a file path. | |
471 /// </summary> | |
472 protected virtual AssemblyReferenceNode CreateAssemblyReferenceN
ode(string fileName) | |
473 { | |
474 AssemblyReferenceNode node = null; | |
475 try | |
476 { | |
477 node = new AssemblyReferenceNode(this.ProjectMgr
, fileName); | |
478 } | |
479 catch(ArgumentNullException e) | |
480 { | |
481 Trace.WriteLine("Exception : " + e.Message); | |
482 } | |
483 catch(FileNotFoundException e) | |
484 { | |
485 Trace.WriteLine("Exception : " + e.Message); | |
486 } | |
487 catch(BadImageFormatException e) | |
488 { | |
489 Trace.WriteLine("Exception : " + e.Message); | |
490 } | |
491 catch(FileLoadException e) | |
492 { | |
493 Trace.WriteLine("Exception : " + e.Message); | |
494 } | |
495 catch(System.Security.SecurityException e) | |
496 { | |
497 Trace.WriteLine("Exception : " + e.Message); | |
498 } | |
499 | |
500 return node; | |
501 } | |
502 | |
503 /// <summary> | |
504 /// Creates a com reference node from the project element. | |
505 /// </summary> | |
506 protected virtual ComReferenceNode CreateComReferenceNode(Projec
tElement reference) | |
507 { | |
508 return new ComReferenceNode(this.ProjectMgr, reference); | |
509 } | |
510 /// <summary> | |
511 /// Creates a com reference node from a selector data. | |
512 /// </summary> | |
513 protected virtual ComReferenceNode CreateComReferenceNode(Micros
oft.VisualStudio.Shell.Interop.VSCOMPONENTSELECTORDATA selectorData) | |
514 { | |
515 ComReferenceNode node = new ComReferenceNode(this.Projec
tMgr, selectorData); | |
516 return node; | |
517 } | |
518 #endregion | |
519 | |
520 } | |
521 } | |
OLD | NEW |