Datei: NDOPackage/ProjectDescription.cs

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