Datei: NDOPackage/ProjectDescription.cs

Last Commit (f6f378a)
1 //
2 // Copyright (c) 2002-2022 Mirko Matytschak
3 // (www.netdataobjects.de)
4 //
5 // Author: Mirko Matytschak
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10 // Software, and to permit persons to whom the Software is furnished to do so, subject to the following
11 // conditions:
12
13 // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 // of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22
23 using System;
24 using SD = System.Diagnostics;
25 using System.Xml;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.IO;
29 using Microsoft.VisualStudio.Shell.Interop;
30 using Microsoft.VisualStudio.Shell;
31 using System.Linq;
32 using EnvDTE;
33 using Project = Community.VisualStudio.Toolkit.Project;
34 using Solution = Community.VisualStudio.Toolkit.Solution;
35
36 namespace NDOVsPackage
37 {
38
39 ····/// <summary>
40 ····/// ProjectDescription.
41 ····/// </summary>
42 ····[SD.CodeAnalysis.SuppressMessage( "Usage", "VSTHRD010:Invoke single-threaded types on Main thread", Justification = "This code always runs on the UI thread" )]
43 ····internal class ProjectDescription
44 ····{
45 ········Solution solution = null;
46 ········Project project = null;
47 ········Dictionary<string, NDOReference> references = null;
48 ········bool debug;
49 ········string binFile;
50 ········string objPath;
51 ········string projPath;
52 ········string assemblyName;
53 ········ConfigurationOptions options;
54 ········bool isWebProject;
55 ········string keyFile = string.Empty;
56 ········string platformTarget;
57 ········string targetFramework;
58
59 #if DEBUG
60 ········MessageAdapter messageAdapter;
61 ········public MessageAdapter MessageAdapter
62 ········{
63 ············get { return messageAdapter; }
64 ············set { messageAdapter = value; }
65 ········}
66 #endif
67
68 ········public string TargetFramework
69 ········{
70 ············get { return this.targetFramework; }
71 ········}
72
73 ········public string PlatformTarget
74 ········{
75 ············get { return this.platformTarget; }
76 ········}
77
78 ········public string KeyFile
79 ········{
80 ············get { return keyFile; }
81 ············set { keyFile = value; }
82 ········}
83
84 ········public bool IsWebProject
85 ········{
86 ············get { return isWebProject; }
87 ········}
88
89 ········public ConfigurationOptions ConfigurationOptions
90 ········{
91 ············get { return options; }
92 ········}
93
94 ········public string AssemblyName
95 ········{
96 ············get { return assemblyName; }
97 ············set { assemblyName = value; }
98 ········}
99
100 ········public ConfigurationOptions NewConfigurationOptions()
101 ········{
102 ············return new ConfigurationOptions(project);
103 ········}
104
105 ········public ProjectDescription()
106 ········{
107 ········}
108
109 ········public ProjectDescription(string fileName)
110 ········{
111 ············this.projPath = Path.GetDirectoryName(fileName) + Path.DirectorySeparatorChar;
112 ············XmlDocument doc = new XmlDocument();
113 ············try
114 ············{
115 ················doc.Load(fileName);
116 ············}
117 ············catch(XmlException ex)
118 ············{
119 ················throw new Exception("Parameter file '" + fileName + "' is not a valid Xml file. Line: " + ex.LineNumber.ToString() + " Position: " + ex.LinePosition.ToString());
120 ············}
121 ············XmlHelper.AddNamespace(doc);
122 ············Load(doc);
123 ············options = new ConfigurationOptions(doc);
124 ········}
125
126 ········string AbsolutePath(string path)
127 ········{
128 ············if (Path.IsPathRooted(path))
129 ················return path;
130 ············else
131 ················return Path.Combine(projPath, path);
132 ········}
133
134 ········void Load(XmlDocument doc)
135 ········{
136 ············string pns = XmlHelper.Pns(doc);
137
138 ············XmlNode node = doc.SelectSingleNode("//" + pns + "Enhancer/" + pns + "ProjectDescription", XmlHelper.Nsmgr);
139 ············if (node == null)
140 ················throw new Exception("Parameters must have at least one //Enhancer/ProjectDescription entry.");
141 ············
142 ············binFile = AbsolutePath((string) XmlHelper.GetNode(node, pns + "BinPath"));
143 ············objPath = AbsolutePath((string) XmlHelper.GetNode(node, pns + "ObjPath"));
144 ············keyFile = (string)XmlHelper.GetNode(node, pns + "KeyFile", string.Empty);
145 ············if (keyFile != string.Empty)
146 ················keyFile = AbsolutePath(keyFile);
147 ············assemblyName = (string)XmlHelper.GetNode(node, pns + "AssemblyName");
148 ············debug = (bool) XmlHelper.GetNode(node, pns + "Debug", false);
149 ············isWebProject = (bool) XmlHelper.GetNode(node, pns + "IsWebProject", false);
150 ············XmlNodeList refList = doc.SelectNodes("//" + pns + "Enhancer/" + pns + "ProjectDescription/" + pns + "References/" + pns + "Reference", XmlHelper.Nsmgr);
151 ············references = new Dictionary<string, NDOReference>();
152 ············foreach ( XmlNode rnode in refList )
153 ············{
154 ················string assName = (string) XmlHelper.GetAttribute(rnode, "AssemblyName");
155 ················string assPath = AbsolutePath((string) XmlHelper.GetAttribute(rnode, "AssemblyPath"));
156 ················bool processDLL = true;
157 ················XmlAttribute attr = rnode.Attributes["CheckThisDLL"];
158 ················if ( attr != null && string.Compare( attr.Value, "True", true ) != 0 )
159 ····················processDLL = false;
160
161 ················AddReference( assName, assPath, processDLL );
162 ············}
163 ········}
164
165
166 ········private XmlNode MakeNode(string name, object value, XmlNode parentNode, XmlDocument doc)
167 ········{
168 ············XmlElement el = doc.CreateElement(name);
169 ············parentNode.AppendChild(el);
170 ············if (value != null)
171 ················el.InnerText = value.ToString();
172 ············return el;
173 ········}
174
175
176 ········public void ToXml(XmlNode parent)
177 ········{
178 ············XmlDocument doc = (XmlDocument) parent.ParentNode;
179 ············XmlNode node = doc.CreateElement("ProjectDescription");
180 ············parent.AppendChild(node);
181 ············string reference = this.projPath;
182 ············if (reference.EndsWith("\\"))
183 ················reference = reference.Substring(0, reference.Length - 1);
184
185 ············MakeNode("BinPath", ExtendedPath.GetRelativePath(reference, binFile), node, doc);
186 ············MakeNode("ObjPath", ExtendedPath.GetRelativePath(reference, objPath), node, doc);
187 ············MakeNode("AssemblyName", assemblyName, node, doc);
188 ············MakeNode("Debug", debug, node, doc);
189 ············MakeNode("IsWebProject", isWebProject, node, doc);
190 ············MakeNode("KeyFile", keyFile, node, doc);
191 ············XmlNode refsNode = MakeNode("References", string.Empty, node, doc);
192 ············foreach ( string key in References.Keys )
193 ············{
194 ················NDOReference ndoreference = References[key];
195 ················if ( ndoreference.Path == binFile )
196 ····················continue;
197 ················XmlElement refNode = (XmlElement) MakeNode( "Reference", "", refsNode, doc );
198 ················refNode.SetAttribute( "AssemblyName", ndoreference.Name );
199 ················refNode.SetAttribute( "AssemblyPath", ExtendedPath.GetRelativePath( reference, ndoreference.Path ) );
200 ················if ( !ndoreference.CheckThisDLL )
201 ················{
202 ····················refNode.SetAttribute( "CheckThisDLL", "False" );
203 ················}
204 ············}
205 ········}
206
207 ········string GetBuildProperty(IVsBuildPropertyStorage propertyStorage, string key, string configuration = "")
208 ········{
209 ············string result = null;
210 ············if (propertyStorage != null)
211 ················propertyStorage.GetPropertyValue( key, configuration, (uint)_PersistStorageType.PST_PROJECT_FILE, out result );
212 ············return result;
213 ········}
214
215 ········public ProjectDescription( Project project )
216 ········{
217 ············this.solution = (Solution) project.Parent;
218 ············this.project = project;
219
220 ············ThreadHelper.ThrowIfNotOnUIThread();
221 ············var dteProj = project.DteProject();
222 ············EnvDTE.Configuration conf = dteProj.ConfigurationManager.ActiveConfiguration;
223 ············//foreach (Property item in conf.Properties)
224 ············//{
225 ············//····SD.Debug.WriteLine( $"{item.Name} = {item.Value}" );
226 ············//}
227
228
229 ············// Get the MSBuild property storage
230 ············IVsBuildPropertyStorage propertyStorage = GetPropertyStorage( project );
231
232 ············try
233 ············{
234 ················this.platformTarget = (string) conf.Properties.Item( "PlatformTarget" ).Value;
235 ············}
236 ············catch { }
237 ············try
238 ············{
239 ················this.targetFramework = (string) dteProj.Properties.Item( "TargetFrameworkMoniker" ).Value;
240 ············}
241 ············catch { }
242
243
244 ············string outputPath = (string) conf.Properties.Item( "OutputPath" ).Value;
245 ············string fullPath = dteProj.Properties.Item( "FullPath" ).Value as string;
246 ············string outputFileName = GetBuildProperty( propertyStorage, "TargetFileName" );
247
248 ············if (String.IsNullOrEmpty( outputFileName ))
249 ············{
250 ················int outputType = (int) dteProj.Properties.Item( "OutputType" ).Value;
251 ················// .NET Core Executables are dlls.
252 ················if (this.targetFramework.StartsWith( ".NETCoreApp" ))
253 ····················outputType = 2;
254 ················outputFileName = (string) dteProj.Properties.Item( "AssemblyName" ).Value + ( outputType == 2 ? ".dll" : ".exe" );
255 ············}
256
257 ············if (project.GetVsHierarchy().IsCapabilityMatch( "CPS" ))
258 ············{
259 ················// new .csproj format
260 ················objPath = GetBuildProperty( propertyStorage, "IntermediateOutputPath" );
261 ················string configuration = GetBuildProperty( propertyStorage, "Configuration" );
262 ················debug = configuration == "Debug";
263 ············}
264 ············else
265 ············{
266 ················// old .csproj format
267 ················string debugInfo = (string) conf.Properties.Item( "DebugInfo" ).Value;
268 ················debug = debugInfo == "full";
269 ················objPath = (string) conf.Properties.Item( "IntermediatePath" ).Value;
270 ············}
271 ············binFile = Path.Combine( fullPath, outputPath );
272 ············binFile = Path.Combine( binFile, outputFileName );
273 ············projPath = Path.GetDirectoryName( dteProj.FileName ) + "\\";
274 ············string sign = GetBuildProperty( propertyStorage, "SignAssembly" );
275 ············if (!String.IsNullOrEmpty( sign ) && String.Compare( sign, "true", true ) == 0)
276 ················keyFile = GetBuildProperty( propertyStorage, "AssemblyOriginatorKeyFile" );
277 ············else
278 ················keyFile = null;
279
280 ········}
281
282
283 ········private static IVsBuildPropertyStorage GetPropertyStorage( Project project )
284 ········{
285 ············ThreadHelper.ThrowIfNotOnUIThread();
286 ············IVsHierarchy projectHierarchy = project.GetVsHierarchy();
287
 
 
 
 
 
 
 
 
 
 
 
 
 
288 ············IVsBuildPropertyStorage propertyStorage = null;
289
290 ············if (projectHierarchy != null)
291 ············{
292 propertyStorage = ( IVsBuildPropertyStorage) projectHierarchy;
293 ············}
294
295 ············return propertyStorage;
296 ········}
297
298 ········public string ObjPath
299 ········{
300 ············get { return objPath; }
301 ············set { objPath = value; }
302 ········}
303
304 ········public string BinFile
305 ········{
306 ············get { return binFile; }
307 ············set { binFile = value; }
308 ········}
309
310 ········public bool Debug
311 ········{
312 ············get { return debug; }
313 ············set { debug = value; }
314 ········}
315
316 ········public string ProjPath
317 ········{
318 ············get { return projPath; }
319 ············set { projPath = value; }
320 ········}
321
322 ········private void AddReference( string name, string path, bool checkThisDLL )
323 ········{
324 ············if ( !references.ContainsKey( name ) )
325 ················references.Add( name, new NDOReference( name, path, checkThisDLL ) );
326 ········}
327
328
329 ········public void BuildReferences()
330 ········{
331 ············if (this.references != null)
332 ················return;
333
334 ············this.references = new Dictionary<string,NDOReference>();
335 ············var allProjects = new Dictionary<string, string>();
336 ············var solution = ApplicationObject.VisualStudioApplication.Solution;
337 ············
338 ············foreach(var p in new ProjectIterator(solution).Projects)
339 ············{
340 ················if (p.Name == project.Name) continue;
341 ················EnvDTE.ConfigurationManager cman = p.ConfigurationManager;
342 ················if (cman == null)
343 ····················continue;
344 ················var········ conf = cman.ActiveConfiguration;
345 ················if (conf.Properties == null)
346 ····················continue;
347 ················try // Skip the project, if a property is not present
348 ················{
349 ····················string outputPath = (string)conf.Properties.Item("OutputPath").Value;
350 ····················string fullPath = (string)p.Properties.Item("FullPath").Value;
351 string outputFileName = GetBuildProperty( GetPropertyStorage( this. project) , "TargetFileName" ) ;
352 ····················//messages.Output(fullPath + outputPath + outputFileName);
353 ····················if (!allProjects.ContainsKey(p.Name))
354 ························allProjects.Add(p.Name, fullPath + outputPath + outputFileName);
355 ················}
356 ················catch { }
357 ············}
358 ············
359
360 ············foreach ( var r in this.project.References )
361 ············{
362 ················string rname = "";
363 ················//if (r.SourceProject != null)
364 ················//····rname = r.SourceProject.Name;
365 ················//else
366 ················rname = r.Name;
367 ················if (rname == project.Name) continue;
368
369 ················if (allProjects.ContainsKey( rname ))
370 ················{
371 ····················AddReference( r.Name, (string) allProjects[rname], false );
372 ················}
373 ················else
374 ················{
375 ····················var vsRef = r.VsReference;
376 ····················var path = vsRef.FullPath;
377 ····················// Referenzen, die auf keine gültige DLL verweisen...
378 ····················if (!String.IsNullOrEmpty( path ) && NDOAssemblyChecker.IsEnhanced( path ))
379 ························AddReference( rname, path, false );
380 ················}
381 ············}
382 //············AddReference(project.Name, this.binFile);
383
384 ········}
385
386 ········ProjectItems GetItemCollection(string fileName)
387 ········{
388 ············string relPath = ExtendedPath.GetRelativePath(this.projPath, fileName);
389 ············var dteProj = project.DteProject();
390 ············ProjectItems result = dteProj.ProjectItems;
391 ············if (relPath.IndexOf(":\\") > -1)
392 ················return result;
393 ············string[] splittedName = relPath.Split(new char[] { '\\' });
394 ············for (int i = 0; i < splittedName.Length - 1; i++)
395 ············{
396 ················string name = splittedName[i];
397 ················ProjectItem pi = result.Item(name);
398 ················if (pi != null)
399 ····················result = pi.ProjectItems;
400 ················else
401 ····················break;
402 ············}
403 ············return result;
404 ········}
405
406 ········public void FixDllState()
407 ········{
408 ············// The package works with a transient version of the ProjectDescription, which will be saved
409 ············// after a successful Build. But we need the CheckThisDLL state from the saved version for the UI.
410
411 ············var fileName = ConfigurationOptions.GetNdoProjFileName( project.FullPath );
412
413 ············if (!String.IsNullOrEmpty( fileName ) && File.Exists( fileName ))
414 ············{
415 ················ProjectDescription storedDescription = new ProjectDescription( fileName );
416 ················var storedReferences = storedDescription.references.Values.ToArray();
417 ················foreach (var reference in this.references.Values)
418 ················{
419 ····················var storedReference = storedReferences.FirstOrDefault( r => r.Name == reference.Name );
420 ····················if (storedReference != null)
421 ····················{
422 ························reference.CheckThisDLL = storedReference.CheckThisDLL;
423 ····················}
424 ················}
425 ············}
426 ········}
427
428 ········public void AddFileToProject(string fileName)
429 ········{
430 ············//TODO: Make the search hierarchical
431 ············if (project == null)
432 ················return;
433 ············if (!File.Exists(fileName))
434 ················return;
435 ············bool found = false;
436
437 ············ProjectItems itemCollection = GetItemCollection(fileName);
438
439 ············foreach (ProjectItem pi in itemCollection)
440 ············{
441 ················if (string.Compare(Path.GetFileName(pi.Name), Path.GetFileName(fileName), true) == 0)
442 ················{
443 ····················found = true;
444 ····················break;
445 ················}
446 ············}
447 ············if (!found)
448 ············{
449 #if DEBUG
450 ················messageAdapter.WriteLine("··Adding file to project: " + fileName);
451 #endif
452 ················this.project.DteProject().ProjectItems.AddFromFile(fileName);
453 ············}
454 ········}
455
456
457 ········public Dictionary<string, NDOReference> References
458 ········{
459 ············get
460 ············{
461 ················BuildReferences();
462 ················return references;
463 ············}
464 ········}
465
466 ····}
467 }
468
New Commit (d9e842e)
1 //
2 // Copyright (c) 2002-2022 Mirko Matytschak
3 // (www.netdataobjects.de)
4 //
5 // Author: Mirko Matytschak
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10 // Software, and to permit persons to whom the Software is furnished to do so, subject to the following
11 // conditions:
12
13 // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 // of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22
23 using System;
24 using SD = System.Diagnostics;
25 using System.Xml;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.IO;
29 using Microsoft.VisualStudio.Shell.Interop;
30 using Microsoft.VisualStudio.Shell;
31 using System.Linq;
32 using EnvDTE;
33 using Project = Community.VisualStudio.Toolkit.Project;
34 using Solution = Community.VisualStudio.Toolkit.Solution;
35
36 namespace NDOVsPackage
37 {
38
39 ····/// <summary>
40 ····/// ProjectDescription.
41 ····/// </summary>
42 ····[SD.CodeAnalysis.SuppressMessage( "Usage", "VSTHRD010:Invoke single-threaded types on Main thread", Justification = "This code always runs on the UI thread" )]
43 ····internal class ProjectDescription
44 ····{
45 ········Solution solution = null;
46 ········Project project = null;
47 ········Dictionary<string, NDOReference> references = null;
48 ········bool debug;
49 ········string binFile;
50 ········string objPath;
51 ········string projPath;
52 ········string assemblyName;
53 ········ConfigurationOptions options;
54 ········bool isWebProject;
55 ········string keyFile = string.Empty;
56 ········string platformTarget;
57 ········string targetFramework;
58
59 #if DEBUG
60 ········MessageAdapter messageAdapter;
61 ········public MessageAdapter MessageAdapter
62 ········{
63 ············get { return messageAdapter; }
64 ············set { messageAdapter = value; }
65 ········}
66 #endif
67
68 ········public string TargetFramework
69 ········{
70 ············get { return this.targetFramework; }
71 ········}
72
73 ········public string PlatformTarget
74 ········{
75 ············get { return this.platformTarget; }
76 ········}
77
78 ········public string KeyFile
79 ········{
80 ············get { return keyFile; }
81 ············set { keyFile = value; }
82 ········}
83
84 ········public bool IsWebProject
85 ········{
86 ············get { return isWebProject; }
87 ········}
88
89 ········public ConfigurationOptions ConfigurationOptions
90 ········{
91 ············get { return options; }
92 ········}
93
94 ········public string AssemblyName
95 ········{
96 ············get { return assemblyName; }
97 ············set { assemblyName = value; }
98 ········}
99
100 ········public ConfigurationOptions NewConfigurationOptions()
101 ········{
102 ············return new ConfigurationOptions(project);
103 ········}
104
105 ········public ProjectDescription()
106 ········{
107 ········}
108
109 ········public ProjectDescription(string fileName)
110 ········{
111 ············this.projPath = Path.GetDirectoryName(fileName) + Path.DirectorySeparatorChar;
112 ············XmlDocument doc = new XmlDocument();
113 ············try
114 ············{
115 ················doc.Load(fileName);
116 ············}
117 ············catch(XmlException ex)
118 ············{
119 ················throw new Exception("Parameter file '" + fileName + "' is not a valid Xml file. Line: " + ex.LineNumber.ToString() + " Position: " + ex.LinePosition.ToString());
120 ············}
121 ············XmlHelper.AddNamespace(doc);
122 ············Load(doc);
123 ············options = new ConfigurationOptions(doc);
124 ········}
125
126 ········string AbsolutePath(string path)
127 ········{
128 ············if (Path.IsPathRooted(path))
129 ················return path;
130 ············else
131 ················return Path.Combine(projPath, path);
132 ········}
133
134 ········void Load(XmlDocument doc)
135 ········{
136 ············string pns = XmlHelper.Pns(doc);
137
138 ············XmlNode node = doc.SelectSingleNode("//" + pns + "Enhancer/" + pns + "ProjectDescription", XmlHelper.Nsmgr);
139 ············if (node == null)
140 ················throw new Exception("Parameters must have at least one //Enhancer/ProjectDescription entry.");
141 ············
142 ············binFile = AbsolutePath((string) XmlHelper.GetNode(node, pns + "BinPath"));
143 ············objPath = AbsolutePath((string) XmlHelper.GetNode(node, pns + "ObjPath"));
144 ············keyFile = (string)XmlHelper.GetNode(node, pns + "KeyFile", string.Empty);
145 ············if (keyFile != string.Empty)
146 ················keyFile = AbsolutePath(keyFile);
147 ············assemblyName = (string)XmlHelper.GetNode(node, pns + "AssemblyName");
148 ············debug = (bool) XmlHelper.GetNode(node, pns + "Debug", false);
149 ············isWebProject = (bool) XmlHelper.GetNode(node, pns + "IsWebProject", false);
150 ············XmlNodeList refList = doc.SelectNodes("//" + pns + "Enhancer/" + pns + "ProjectDescription/" + pns + "References/" + pns + "Reference", XmlHelper.Nsmgr);
151 ············references = new Dictionary<string, NDOReference>();
152 ············foreach ( XmlNode rnode in refList )
153 ············{
154 ················string assName = (string) XmlHelper.GetAttribute(rnode, "AssemblyName");
155 ················string assPath = AbsolutePath((string) XmlHelper.GetAttribute(rnode, "AssemblyPath"));
156 ················bool processDLL = true;
157 ················XmlAttribute attr = rnode.Attributes["CheckThisDLL"];
158 ················if ( attr != null && string.Compare( attr.Value, "True", true ) != 0 )
159 ····················processDLL = false;
160
161 ················AddReference( assName, assPath, processDLL );
162 ············}
163 ········}
164
165
166 ········private XmlNode MakeNode(string name, object value, XmlNode parentNode, XmlDocument doc)
167 ········{
168 ············XmlElement el = doc.CreateElement(name);
169 ············parentNode.AppendChild(el);
170 ············if (value != null)
171 ················el.InnerText = value.ToString();
172 ············return el;
173 ········}
174
175
176 ········public void ToXml(XmlNode parent)
177 ········{
178 ············XmlDocument doc = (XmlDocument) parent.ParentNode;
179 ············XmlNode node = doc.CreateElement("ProjectDescription");
180 ············parent.AppendChild(node);
181 ············string reference = this.projPath;
182 ············if (reference.EndsWith("\\"))
183 ················reference = reference.Substring(0, reference.Length - 1);
184
185 ············MakeNode("BinPath", ExtendedPath.GetRelativePath(reference, binFile), node, doc);
186 ············MakeNode("ObjPath", ExtendedPath.GetRelativePath(reference, objPath), node, doc);
187 ············MakeNode("AssemblyName", assemblyName, node, doc);
188 ············MakeNode("Debug", debug, node, doc);
189 ············MakeNode("IsWebProject", isWebProject, node, doc);
190 ············MakeNode("KeyFile", keyFile, node, doc);
191 ············XmlNode refsNode = MakeNode("References", string.Empty, node, doc);
192 ············foreach ( string key in References.Keys )
193 ············{
194 ················NDOReference ndoreference = References[key];
195 ················if ( ndoreference.Path == binFile )
196 ····················continue;
197 ················XmlElement refNode = (XmlElement) MakeNode( "Reference", "", refsNode, doc );
198 ················refNode.SetAttribute( "AssemblyName", ndoreference.Name );
199 ················refNode.SetAttribute( "AssemblyPath", ExtendedPath.GetRelativePath( reference, ndoreference.Path ) );
200 ················if ( !ndoreference.CheckThisDLL )
201 ················{
202 ····················refNode.SetAttribute( "CheckThisDLL", "False" );
203 ················}
204 ············}
205 ········}
206
207 ········string GetBuildProperty(IVsBuildPropertyStorage propertyStorage, string key, string configuration = "")
208 ········{
209 ············string result = null;
210 ············if (propertyStorage != null)
211 ················propertyStorage.GetPropertyValue( key, configuration, (uint)_PersistStorageType.PST_PROJECT_FILE, out result );
212 ············return result;
213 ········}
214
215 ········public ProjectDescription( Project project )
216 ········{
217 ············this.solution = (Solution) project.Parent;
218 ············this.project = project;
219
220 ············ThreadHelper.ThrowIfNotOnUIThread();
221 ············var dteProj = project.DteProject();
222 ············EnvDTE.Configuration conf = dteProj.ConfigurationManager.ActiveConfiguration;
223 ············//foreach (Property item in conf.Properties)
224 ············//{
225 ············//····SD.Debug.WriteLine( $"{item.Name} = {item.Value}" );
226 ············//}
227
228
229 ············// Get the MSBuild property storage
230 ············IVsBuildPropertyStorage propertyStorage = GetPropertyStorage( project );
231
232 ············try
233 ············{
234 ················this.platformTarget = (string) conf.Properties.Item( "PlatformTarget" ).Value;
235 ············}
236 ············catch { }
237 ············try
238 ············{
239 ················this.targetFramework = (string) dteProj.Properties.Item( "TargetFrameworkMoniker" ).Value;
240 ············}
241 ············catch { }
242
243
244 ············string outputPath = (string) conf.Properties.Item( "OutputPath" ).Value;
245 ············string fullPath = dteProj.Properties.Item( "FullPath" ).Value as string;
246 ············string outputFileName = GetBuildProperty( propertyStorage, "TargetFileName" );
247
248 ············if (String.IsNullOrEmpty( outputFileName ))
249 ············{
250 ················int outputType = (int) dteProj.Properties.Item( "OutputType" ).Value;
251 ················// .NET Core Executables are dlls.
252 ················if (this.targetFramework.StartsWith( ".NETCoreApp" ))
253 ····················outputType = 2;
254 ················outputFileName = (string) dteProj.Properties.Item( "AssemblyName" ).Value + ( outputType == 2 ? ".dll" : ".exe" );
255 ············}
256
257 ············if (project.GetVsHierarchy().IsCapabilityMatch( "CPS" ))
258 ············{
259 ················// new .csproj format
260 ················objPath = GetBuildProperty( propertyStorage, "IntermediateOutputPath" );
261 ················string configuration = GetBuildProperty( propertyStorage, "Configuration" );
262 ················debug = configuration == "Debug";
263 ············}
264 ············else
265 ············{
266 ················// old .csproj format
267 ················string debugInfo = (string) conf.Properties.Item( "DebugInfo" ).Value;
268 ················debug = debugInfo == "full";
269 ················objPath = (string) conf.Properties.Item( "IntermediatePath" ).Value;
270 ············}
271 ············binFile = Path.Combine( fullPath, outputPath );
272 ············binFile = Path.Combine( binFile, outputFileName );
273 ············projPath = Path.GetDirectoryName( dteProj.FileName ) + "\\";
274 ············string sign = GetBuildProperty( propertyStorage, "SignAssembly" );
275 ············if (!String.IsNullOrEmpty( sign ) && String.Compare( sign, "true", true ) == 0)
276 ················keyFile = GetBuildProperty( propertyStorage, "AssemblyOriginatorKeyFile" );
277 ············else
278 ················keyFile = null;
279
280 ········}
281
282
283 ········private static IVsBuildPropertyStorage GetPropertyStorage( Project project )
284 ········{
285 ············ThreadHelper.ThrowIfNotOnUIThread();
286 ············IVsHierarchy projectHierarchy = project.GetVsHierarchy();
287
288 ············return GetPropertyStorage( projectHierarchy );
289 ········}
290
291 ········private static IVsBuildPropertyStorage GetPropertyStorage( EnvDTE.Project project )
292 ········{
293 ············ThreadHelper.ThrowIfNotOnUIThread();
294 ············IVsHierarchy projectHierarchy = project.GetVsHierarchy();
295
296 ············return GetPropertyStorage( projectHierarchy );
297 ········}
298
299 ········private static IVsBuildPropertyStorage GetPropertyStorage( IVsHierarchy projectHierarchy )
300 ········{
301 ············IVsBuildPropertyStorage propertyStorage = null;
302
303 ············if (projectHierarchy != null)
304 ············{
305 propertyStorage = ( IVsBuildPropertyStorage) projectHierarchy;
306 ············}
307
308 ············return propertyStorage;
309 ········}
310
311 ········public string ObjPath
312 ········{
313 ············get { return objPath; }
314 ············set { objPath = value; }
315 ········}
316
317 ········public string BinFile
318 ········{
319 ············get { return binFile; }
320 ············set { binFile = value; }
321 ········}
322
323 ········public bool Debug
324 ········{
325 ············get { return debug; }
326 ············set { debug = value; }
327 ········}
328
329 ········public string ProjPath
330 ········{
331 ············get { return projPath; }
332 ············set { projPath = value; }
333 ········}
334
335 ········private void AddReference( string name, string path, bool checkThisDLL )
336 ········{
337 ············if ( !references.ContainsKey( name ) )
338 ················references.Add( name, new NDOReference( name, path, checkThisDLL ) );
339 ········}
340
341
342 ········public void BuildReferences()
343 ········{
344 ············if (this.references != null)
345 ················return;
346
347 ············this.references = new Dictionary<string,NDOReference>();
348 ············var allProjects = new Dictionary<string, string>();
349 ············var solution = ApplicationObject.VisualStudioApplication.Solution;
350 ············
351 ············foreach(var p in new ProjectIterator(solution).Projects)
352 ············{
353 ················if (p.Name == project.Name) continue;
354 ················EnvDTE.ConfigurationManager cman = p.ConfigurationManager;
355 ················if (cman == null)
356 ····················continue;
357 ················var········ conf = cman.ActiveConfiguration;
358 ················if (conf.Properties == null)
359 ····················continue;
360 ················try // Skip the project, if a property is not present
361 ················{
362 ····················string outputPath = (string)conf.Properties.Item("OutputPath").Value;
363 ····················string fullPath = (string)p.Properties.Item("FullPath").Value;
364 string outputFileName = GetBuildProperty( GetPropertyStorage( p) , "TargetFileName" ) ;
365 ····················//messages.Output(fullPath + outputPath + outputFileName);
366 ····················if (!allProjects.ContainsKey(p.Name))
367 ························allProjects.Add(p.Name, fullPath + outputPath + outputFileName);
368 ················}
369 ················catch { }
370 ············}
371 ············
372
373 ············foreach ( var r in this.project.References )
374 ············{
375 ················string rname = "";
376 ················//if (r.SourceProject != null)
377 ················//····rname = r.SourceProject.Name;
378 ················//else
379 ················rname = r.Name;
380 ················if (rname == project.Name) continue;
381
382 ················if (allProjects.ContainsKey( rname ))
383 ················{
384 ····················AddReference( r.Name, (string) allProjects[rname], false );
385 ················}
386 ················else
387 ················{
388 ····················var vsRef = r.VsReference;
389 ····················var path = vsRef.FullPath;
390 ····················// Referenzen, die auf keine gültige DLL verweisen...
391 ····················if (!String.IsNullOrEmpty( path ) && NDOAssemblyChecker.IsEnhanced( path ))
392 ························AddReference( rname, path, false );
393 ················}
394 ············}
395 //············AddReference(project.Name, this.binFile);
396
397 ········}
398
399 ········ProjectItems GetItemCollection(string fileName)
400 ········{
401 ············string relPath = ExtendedPath.GetRelativePath(this.projPath, fileName);
402 ············var dteProj = project.DteProject();
403 ············ProjectItems result = dteProj.ProjectItems;
404 ············if (relPath.IndexOf(":\\") > -1)
405 ················return result;
406 ············string[] splittedName = relPath.Split(new char[] { '\\' });
407 ············for (int i = 0; i < splittedName.Length - 1; i++)
408 ············{
409 ················string name = splittedName[i];
410 ················ProjectItem pi = result.Item(name);
411 ················if (pi != null)
412 ····················result = pi.ProjectItems;
413 ················else
414 ····················break;
415 ············}
416 ············return result;
417 ········}
418
419 ········public void FixDllState()
420 ········{
421 ············// The package works with a transient version of the ProjectDescription, which will be saved
422 ············// after a successful Build. But we need the CheckThisDLL state from the saved version for the UI.
423
424 ············var fileName = ConfigurationOptions.GetNdoProjFileName( project.FullPath );
425
426 ············if (!String.IsNullOrEmpty( fileName ) && File.Exists( fileName ))
427 ············{
428 ················ProjectDescription storedDescription = new ProjectDescription( fileName );
429 ················var storedReferences = storedDescription.references.Values.ToArray();
430 ················foreach (var reference in this.references.Values)
431 ················{
432 ····················var storedReference = storedReferences.FirstOrDefault( r => r.Name == reference.Name );
433 ····················if (storedReference != null)
434 ····················{
435 ························reference.CheckThisDLL = storedReference.CheckThisDLL;
436 ····················}
437 ················}
438 ············}
439 ········}
440
441 ········public void AddFileToProject(string fileName)
442 ········{
443 ············//TODO: Make the search hierarchical
444 ············if (project == null)
445 ················return;
446 ············if (!File.Exists(fileName))
447 ················return;
448 ············bool found = false;
449
450 ············ProjectItems itemCollection = GetItemCollection(fileName);
451
452 ············foreach (ProjectItem pi in itemCollection)
453 ············{
454 ················if (string.Compare(Path.GetFileName(pi.Name), Path.GetFileName(fileName), true) == 0)
455 ················{
456 ····················found = true;
457 ····················break;
458 ················}
459 ············}
460 ············if (!found)
461 ············{
462 #if DEBUG
463 ················messageAdapter.WriteLine("··Adding file to project: " + fileName);
464 #endif
465 ················this.project.DteProject().ProjectItems.AddFromFile(fileName);
466 ············}
467 ········}
468
469
470 ········public Dictionary<string, NDOReference> References
471 ········{
472 ············get
473 ············{
474 ················BuildReferences();
475 ················return references;
476 ············}
477 ········}
478
479 ····}
480 }
481