OLD | NEW |
| (Empty) |
1 /// Copyright (c) Microsoft Corporation. All rights reserved. | |
2 | |
3 using System; | |
4 using System.Diagnostics; | |
5 using System.Diagnostics.CodeAnalysis; | |
6 using System.Globalization; | |
7 using System.IO; | |
8 using System.Runtime.InteropServices; | |
9 using Microsoft.VisualStudio; | |
10 using Microsoft.VisualStudio.Shell.Interop; | |
11 using Microsoft.Win32; | |
12 | |
13 namespace Microsoft.VisualStudio.Project | |
14 { | |
15 /// <summary> | |
16 /// This type of node is used for references to COM components. | |
17 /// </summary> | |
18 [CLSCompliant(false)] | |
19 [ComVisible(true)] | |
20 public class ComReferenceNode : ReferenceNode | |
21 { | |
22 #region fields | |
23 private string typeName; | |
24 private Guid typeGuid; | |
25 private string projectRelativeFilePath; | |
26 private string installedFilePath; | |
27 private string minorVersionNumber; | |
28 private string majorVersionNumber; | |
29 private string lcid; | |
30 #endregion | |
31 | |
32 #region properties | |
33 public override string Caption | |
34 { | |
35 get { return this.typeName; } | |
36 } | |
37 | |
38 public override string Url | |
39 { | |
40 get | |
41 { | |
42 return this.projectRelativeFilePath; | |
43 } | |
44 } | |
45 | |
46 /// <summary> | |
47 /// Returns the Guid of the COM object. | |
48 /// </summary> | |
49 public Guid TypeGuid | |
50 { | |
51 get { return this.typeGuid; } | |
52 } | |
53 | |
54 /// <summary> | |
55 /// Returns the path where the COM object is installed. | |
56 /// </summary> | |
57 public string InstalledFilePath | |
58 { | |
59 get { return this.installedFilePath; } | |
60 } | |
61 | |
62 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBe
CasedCorrectly", MessageId = "LCID")] | |
63 public string LCID | |
64 { | |
65 get { return lcid; } | |
66 } | |
67 | |
68 public int MajorVersionNumber | |
69 { | |
70 get | |
71 { | |
72 if(string.IsNullOrEmpty(majorVersionNumber)) | |
73 { | |
74 return 0; | |
75 } | |
76 return int.Parse(majorVersionNumber, CultureInfo
.CurrentCulture); | |
77 } | |
78 } | |
79 public int MinorVersionNumber | |
80 { | |
81 get | |
82 { | |
83 if(string.IsNullOrEmpty(minorVersionNumber)) | |
84 { | |
85 return 0; | |
86 } | |
87 return int.Parse(minorVersionNumber, CultureInfo
.CurrentCulture); | |
88 } | |
89 } | |
90 private Automation.OAComReference comReference; | |
91 internal override object Object | |
92 { | |
93 get | |
94 { | |
95 if(null == comReference) | |
96 { | |
97 comReference = new Automation.OAComRefer
ence(this); | |
98 } | |
99 return comReference; | |
100 } | |
101 } | |
102 #endregion | |
103 | |
104 #region ctors | |
105 /// <summary> | |
106 /// Constructor for the ComReferenceNode. | |
107 /// </summary> | |
108 public ComReferenceNode(ProjectNode root, ProjectElement element
) | |
109 : base(root, element) | |
110 { | |
111 this.typeName = this.ItemNode.GetMetadata(ProjectFileCon
stants.Include); | |
112 string typeGuidAsString = this.ItemNode.GetMetadata(Proj
ectFileConstants.Guid); | |
113 if(typeGuidAsString != null) | |
114 { | |
115 this.typeGuid = new Guid(typeGuidAsString); | |
116 } | |
117 | |
118 this.majorVersionNumber = this.ItemNode.GetMetadata(Proj
ectFileConstants.VersionMajor); | |
119 this.minorVersionNumber = this.ItemNode.GetMetadata(Proj
ectFileConstants.VersionMinor); | |
120 this.lcid = this.ItemNode.GetMetadata(ProjectFileConstan
ts.Lcid); | |
121 this.SetProjectItemsThatRelyOnReferencesToBeResolved(fal
se); | |
122 this.SetInstalledFilePath(); | |
123 } | |
124 | |
125 /// <summary> | |
126 /// Overloaded constructor for creating a ComReferenceNode from
selector data | |
127 /// </summary> | |
128 /// <param name="root">The Project node</param> | |
129 /// <param name="selectorData">The component selctor data.</para
m> | |
130 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usag
e", "CA2201:DoNotRaiseReservedExceptionTypes")] | |
131 public ComReferenceNode(ProjectNode root, VSCOMPONENTSELECTORDAT
A selectorData) | |
132 : base(root) | |
133 { | |
134 if(root == null) | |
135 { | |
136 throw new ArgumentNullException("root"); | |
137 } | |
138 if(selectorData.type == VSCOMPONENTTYPE.VSCOMPONENTTYPE_
Project | |
139 || selectorData.type == VSCOMPONENTTYPE.VSCOMPON
ENTTYPE_ComPlus) | |
140 { | |
141 throw new ArgumentException("SelectorData cannot
be of type VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project or VSCOMPONENTTYPE.VSCOMPONE
NTTYPE_ComPlus", "selectorData"); | |
142 } | |
143 | |
144 // Initialize private state | |
145 this.typeName = selectorData.bstrTitle; | |
146 this.typeGuid = selectorData.guidTypeLibrary; | |
147 this.majorVersionNumber = selectorData.wTypeLibraryMajor
Version.ToString(CultureInfo.InvariantCulture); | |
148 this.minorVersionNumber = selectorData.wTypeLibraryMinor
Version.ToString(CultureInfo.InvariantCulture); | |
149 this.lcid = selectorData.lcidTypeLibrary.ToString(Cultur
eInfo.InvariantCulture); | |
150 | |
151 // Check to see if the COM object actually exists. | |
152 this.SetInstalledFilePath(); | |
153 // If the value cannot be set throw. | |
154 if(String.IsNullOrEmpty(this.installedFilePath)) | |
155 { | |
156 throw new NullReferenceException("The InstalledF
ilePath is null"); | |
157 } | |
158 } | |
159 #endregion | |
160 | |
161 #region methods | |
162 /// <summary> | |
163 /// Links a reference node to the project and hierarchy. | |
164 /// </summary> | |
165 protected override void BindReferenceData() | |
166 { | |
167 Debug.Assert(this.ItemNode != null, "The AssemblyName fi
eld has not been initialized"); | |
168 | |
169 // We need to create the project element at this point i
f it has not been created. | |
170 // We cannot do that from the ctor if input comes from a
component selector data, since had we been doing that we would have added a pro
ject element to the project file. | |
171 // The problem with that approach is that we would need
to remove the project element if the item cannot be added to the hierachy (E.g.
It already exists). | |
172 // It is just safer to update the project file now. This
is the intent of this method. | |
173 // Call MSBuild to build the target ResolveComReferences | |
174 if(this.ItemNode == null || this.ItemNode.Item == null) | |
175 { | |
176 this.ItemNode = this.GetProjectElementBasedOnInp
utFromComponentSelectorData(); | |
177 } | |
178 | |
179 this.SetProjectItemsThatRelyOnReferencesToBeResolved(tru
e); | |
180 } | |
181 | |
182 /// <summary> | |
183 /// Checks if a reference is already added. The method parses al
l references and compares the the FinalItemSpec and the Guid. | |
184 /// </summary> | |
185 /// <returns>true if the assembly has already been added.</retur
ns> | |
186 protected override bool IsAlreadyAdded() | |
187 { | |
188 ReferenceContainerNode referencesFolder = this.ProjectMg
r.FindChild(ReferenceContainerNode.ReferencesNodeVirtualName) as ReferenceContai
nerNode; | |
189 Debug.Assert(referencesFolder != null, "Could not find t
he References node"); | |
190 | |
191 for(HierarchyNode n = referencesFolder.FirstChild; n !=
null; n = n.NextSibling) | |
192 { | |
193 ComReferenceNode refererenceNode = n as ComRefer
enceNode; | |
194 | |
195 if(refererenceNode != null) | |
196 { | |
197 // We check if the name and guids are th
e same | |
198 if(refererenceNode.TypeGuid == this.Type
Guid && String.Compare(refererenceNode.Caption, this.Caption, StringComparison.O
rdinalIgnoreCase) == 0) | |
199 { | |
200 return true; | |
201 } | |
202 } | |
203 } | |
204 | |
205 return false; | |
206 } | |
207 | |
208 /// <summary> | |
209 /// Determines if this is node a valid node for painting the def
ault reference icon. | |
210 /// </summary> | |
211 /// <returns></returns> | |
212 protected override bool CanShowDefaultIcon() | |
213 { | |
214 return !String.IsNullOrEmpty(this.installedFilePath); | |
215 } | |
216 | |
217 /// <summary> | |
218 /// This is an helper method to convert the VSCOMPONENTSELECTORD
ATA recieved by the | |
219 /// implementer of IVsComponentUser into a ProjectElement that c
an be used to create | |
220 /// an instance of this class. | |
221 /// This should not be called for project reference or reference
to managed assemblies. | |
222 /// </summary> | |
223 /// <returns>ProjectElement corresponding to the COM component p
assed in</returns> | |
224 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Glob
alization", "CA1308:NormalizeStringsToUppercase")] | |
225 private ProjectElement GetProjectElementBasedOnInputFromComponen
tSelectorData() | |
226 { | |
227 | |
228 ProjectElement element = new ProjectElement(this.Project
Mgr, this.typeName, ProjectFileConstants.COMReference); | |
229 | |
230 // Set the basic information regarding this COM componen
t | |
231 element.SetMetadata(ProjectFileConstants.Guid, this.type
Guid.ToString("B")); | |
232 element.SetMetadata(ProjectFileConstants.VersionMajor, t
his.majorVersionNumber); | |
233 element.SetMetadata(ProjectFileConstants.VersionMinor, t
his.minorVersionNumber); | |
234 element.SetMetadata(ProjectFileConstants.Lcid, this.lcid
); | |
235 element.SetMetadata(ProjectFileConstants.Isolated, false
.ToString()); | |
236 | |
237 // See if a PIA exist for this component | |
238 TypeLibConverter typelib = new TypeLibConverter(); | |
239 string assemblyName; | |
240 string assemblyCodeBase; | |
241 if(typelib.GetPrimaryInteropAssembly(this.typeGuid, Int3
2.Parse(this.majorVersionNumber, CultureInfo.InvariantCulture), Int32.Parse(this
.minorVersionNumber, CultureInfo.InvariantCulture), Int32.Parse(this.lcid, Cultu
reInfo.InvariantCulture), out assemblyName, out assemblyCodeBase)) | |
242 { | |
243 element.SetMetadata(ProjectFileConstants.Wrapper
Tool, WrapperToolAttributeValue.Primary.ToString().ToLowerInvariant()); | |
244 } | |
245 else | |
246 { | |
247 // MSBuild will have to generate an interop asse
mbly | |
248 element.SetMetadata(ProjectFileConstants.Wrapper
Tool, WrapperToolAttributeValue.TlbImp.ToString().ToLowerInvariant()); | |
249 element.SetMetadata(ProjectFileConstants.Private
, true.ToString()); | |
250 } | |
251 return element; | |
252 } | |
253 | |
254 private void SetProjectItemsThatRelyOnReferencesToBeResolved(boo
l renameItemNode) | |
255 { | |
256 // Call MSBuild to build the target ResolveComReferences | |
257 bool success; | |
258 ErrorHandler.ThrowOnFailure(this.ProjectMgr.BuildTarget(
MsBuildTarget.ResolveComReferences, out success)); | |
259 if(!success) | |
260 throw new InvalidOperationException(); | |
261 | |
262 // Now loop through the generated COM References to find
the corresponding one | |
263 Microsoft.Build.BuildEngine.BuildItemGroup comReferences
= this.ProjectMgr.BuildProject.GetEvaluatedItemsByName(MsBuildGeneratedItemType
.ComReferenceWrappers); | |
264 foreach(Microsoft.Build.BuildEngine.BuildItem reference
in comReferences) | |
265 { | |
266 if(String.Compare(reference.GetMetadata(ProjectF
ileConstants.Guid), this.typeGuid.ToString("B"), StringComparison.OrdinalIgnoreC
ase) == 0 | |
267 && String.Compare(reference.GetMetadata(
ProjectFileConstants.VersionMajor), this.majorVersionNumber, StringComparison.Or
dinalIgnoreCase) == 0 | |
268 && String.Compare(reference.GetMetadata(
ProjectFileConstants.VersionMinor), this.minorVersionNumber, StringComparison.Or
dinalIgnoreCase) == 0 | |
269 && String.Compare(reference.GetMetadata(
ProjectFileConstants.Lcid), this.lcid, StringComparison.OrdinalIgnoreCase) == 0) | |
270 { | |
271 string name = reference.FinalItemSpec; | |
272 if(Path.IsPathRooted(name)) | |
273 { | |
274 this.projectRelativeFilePath = n
ame; | |
275 } | |
276 else | |
277 { | |
278 this.projectRelativeFilePath = P
ath.Combine(this.ProjectMgr.ProjectFolder, name); | |
279 } | |
280 | |
281 if(renameItemNode) | |
282 { | |
283 this.ItemNode.Rename(Path.GetFil
eNameWithoutExtension(name)); | |
284 } | |
285 break; | |
286 } | |
287 } | |
288 } | |
289 | |
290 /// <summary> | |
291 /// Verify that the TypeLib is registered and set the the instal
led file path of the com reference. | |
292 /// </summary> | |
293 /// <returns></returns> | |
294 private void SetInstalledFilePath() | |
295 { | |
296 string registryPath = string.Format(CultureInfo.Invarian
tCulture, @"TYPELIB\{0}\{1}.{2}", this.typeGuid.ToString("B"), this.majorVersion
Number, this.minorVersionNumber); | |
297 using(RegistryKey typeLib = Registry.ClassesRoot.OpenSub
Key(registryPath)) | |
298 { | |
299 if(typeLib != null) | |
300 { | |
301 // Check if we need to set the name for
this type. | |
302 if(string.IsNullOrEmpty(this.typeName)) | |
303 { | |
304 this.typeName = typeLib.GetValue
(string.Empty) as string; | |
305 } | |
306 // Now get the path to the file that con
tains this type library. | |
307 using(RegistryKey installKey = typeLib.O
penSubKey(@"0\win32")) | |
308 { | |
309 this.installedFilePath = install
Key.GetValue(String.Empty) as String; | |
310 } | |
311 } | |
312 } | |
313 } | |
314 | |
315 #endregion | |
316 } | |
317 } | |
OLD | NEW |