-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSDKManifest.cs
621 lines (532 loc) · 24.1 KB
/
SDKManifest.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Xml;
namespace EnumSDKs.Extracted
{
/// <summary>
/// Type of SDK
/// </summary>
public enum SDKType
{
/// <summary>
/// Not specified
/// </summary>
Unspecified,
/// <summary>
/// Traditional 3rd party SDK
/// </summary>
External,
/// <summary>
/// Platform extension SDK
/// </summary>
Platform,
/// <summary>
/// Framework extension SDK
/// </summary>
Framework
}
/// <summary>
/// What should happen if multiple versions of a given productfamily or sdk name are found
/// </summary>
public enum MultipleVersionSupport
{
/// <summary>
/// No action should be taken if multiple versions are detected
/// </summary>
Allow = 0,
/// <summary>
/// Log warning
/// </summary>
Warning = 1,
/// <summary>
/// Log an error
/// </summary>
Error = 2
}
/// <summary>
/// Structure to represent the information contained in SDKManifest.xml
/// </summary>
public class SDKManifest
{
/// <summary>
/// Pattern in path to extension SDK used to help determine if manifest is from a framework SDK
/// </summary>
private static readonly string s_extensionSDKPathPattern = @"\MICROSOFT SDKS\WINDOWS\V8.0\EXTENSIONSDKS";
/// <summary>
/// Default version of MaxPlatformVersion in framework extension SDKs with manifest not containing such a property
/// </summary>
private static readonly string s_defaultMaxPlatformVersion = "8.0";
/// <summary>
/// Default version of MinOSVersion in framework extension SDKs with manifest not containing such a property
/// </summary>
private static readonly string s_defaultMinOSVersion = "6.2.1";
/// <summary>
/// Default version of MaxOSVersionTested in framework extension SDKs with manifest not containing such a property
/// </summary>
private static readonly string s_defaultMaxOSVersionTested = "6.2.1";
/// <summary>
/// What should happen if this sdk is resolved with other sdks of the same productfamily or same sdk name.
/// </summary>
private MultipleVersionSupport _supportsMultipleVersions;
/// <summary>
/// Path to where the file SDKManifest.xml is stored
/// </summary>
private readonly string _pathToSdk;
/// <summary>
/// Whatever appx locations we found in the manifest
/// </summary>
private IDictionary<string, string> _appxLocations;
/// <summary>
/// Whatever framework identities we found in the manifest.
/// </summary>
private IDictionary<string, string> _frameworkIdentities;
/// <summary>
/// Whatever MaxOSVersionTested we found in the manifest.
/// </summary>
private string _maxOSVersionTested;
/// <summary>
/// Whatever MinOSVersion we found in the manifest
/// </summary>
private string _minOSVersion;
/// <summary>
/// Whatever MaxPlatformVersion we found in the manifest
/// </summary>
private string _maxPlatformVersion;
/// <summary>
/// The SDKType, default of unspecified
/// </summary>
private SDKType _sdkType = SDKType.Unspecified;
/// <summary>
/// Constructor
/// Takes the path to SDKManifest.xml and populates the structure with manifest data
/// </summary>
public SDKManifest(string pathToSdk)
{
//ErrorUtilities.VerifyThrowArgumentLength(pathToSdk, nameof(pathToSdk));
_pathToSdk = pathToSdk;
LoadManifestFile();
}
/// <summary>
/// Whatever information regarding support for multiple versions is found in the manifest
/// </summary>
public MultipleVersionSupport SupportsMultipleVersions => _supportsMultipleVersions;
/// <summary>
/// Whatever framework identities we found in the manifest.
/// </summary>
public IDictionary<string, string> FrameworkIdentities => _frameworkIdentities != null ? new ReadOnlyDictionary<string, string>(_frameworkIdentities) : null;
/// <summary>
/// Whatever appx locations we found in the manifest
/// </summary>
public IDictionary<string, string> AppxLocations => _appxLocations != null ? new ReadOnlyDictionary<string, string>(_appxLocations) : null;
/// <summary>
/// PlatformIdentity if it exists in the appx manifest for this sdk.
/// </summary>
public string PlatformIdentity { get; private set; }
/// <summary>
/// The FrameworkIdentity for the sdk, this may be a single name or a | delimited name
/// </summary>
public string FrameworkIdentity { get; private set; }
/// <summary>
/// Support Prefer32bit found in the sdk manifest
/// </summary>
public string SupportPrefer32Bit { get; private set; }
/// <summary>
/// SDKType found in the sdk manifest
/// </summary>
public SDKType SDKType => _sdkType;
/// <summary>
/// CopyRedistToSubDirectory specifies where the redist files should be copied to relative to the root of the package.
/// </summary>
public string CopyRedistToSubDirectory { get; private set; }
/// <summary>
/// Supported Architectures is a semicolon delimited list of architectures that the SDK supports.
/// </summary>
public string SupportedArchitectures { get; private set; }
/// <summary>
/// DependsOnSDK is a semicolon delimited list of SDK identities that the SDK requires be resolved in order to function.
/// </summary>
public string DependsOnSDK { get; private set; }
/// <summary>
/// ProductFamilyName specifies the product family for the SDK. This is offered up as metadata on the resolved sdkreference and is used to detect sdk conflicts.
/// </summary>
public string ProductFamilyName { get; private set; }
/// <summary>
/// The platform the SDK targets.
/// </summary>
public string TargetPlatform { get; private set; }
/// <summary>
/// Minimum version of the platform the SDK supports.
/// </summary>
public string TargetPlatformMinVersion { get; private set; }
/// <summary>
/// Maximum version of the platform that the SDK supports.
/// </summary>
public string TargetPlatformVersion { get; private set; }
/// <summary>
/// DisplayName found in the sdk manifest
/// </summary>
public string DisplayName { get; private set; }
/// <summary>
/// MinVSVersion found in the sdk manifest
/// </summary>
public string MinVSVersion { get; private set; }
/// <summary>
/// MinOSVersion found in the sdk manifest, defaults to 6.2.1 for framework extension SDKs when manifest does not have this property set
/// </summary>
public string MinOSVersion => _minOSVersion == null && IsFrameworkExtensionSdkManifest
? s_defaultMinOSVersion
: _minOSVersion;
/// <summary>
/// MaxPlatformVersion found in the sdk manifest, defaults to 8.0 for framework extension SDKs when manifest does not have this property set
/// </summary>
public string MaxPlatformVersion => _maxPlatformVersion == null && IsFrameworkExtensionSdkManifest
? s_defaultMaxPlatformVersion
: _maxPlatformVersion;
/// <summary>
/// MaxOSVersionTested found in the sdk manifest, defaults to 6.2.1 for framework extension SDKs when manifest does not have this property set
/// </summary>
public string MaxOSVersionTested => _maxOSVersionTested == null && IsFrameworkExtensionSdkManifest
? s_defaultMaxOSVersionTested
: _maxOSVersionTested;
/// <summary>
/// MoreInfo as found in the sdk manifest
/// </summary>
public string MoreInfo { get; private set; }
/// <summary>
/// Flag set to true if an exception occurred while reading the manifest
/// </summary>
public bool ReadError { get; private set; }
/// <summary>
/// Message from exception thrown while reading manifest
/// </summary>
public string ReadErrorMessage { get; private set; }
/// <summary>
/// The contracts contained by this manifest, if any
/// Item1: Contract name
/// Item2: Contract version
/// </summary>
internal ICollection<ApiContract> ApiContracts { get; private set; }
/// <summary>
/// Decide on whether it is a framework extension sdk based on manifest's FrameworkIdentify and path
/// </summary>
private bool IsFrameworkExtensionSdkManifest => _frameworkIdentities?.Count > 0
&& _pathToSdk?.ToUpperInvariant().Contains(s_extensionSDKPathPattern) == true;
/// <summary>
/// Load content of SDKManifest.xml
/// </summary>
private void LoadManifestFile()
{
/*
Extension SDK Manifest:
<FileList
TargetPlatform="UAP"
TargetPlatformMinVersion="1.0.0.0"
TargetPlatformVersion="1.0.0.0"
SDKType = "Platform" | "Framework" | "External"
DisplayName = ""My SDK""
ProductFamilyName = ""UnitTest SDKs""
FrameworkIdentity-Debug = ""Name=MySDK.10.Debug, MinVersion=1.0.0.0""
FrameworkIdentity-Retail = ""Name=MySDK.10, MinVersion=1.0.0.0""
TargetFramework = "".NETCore, version=v4.5; .NETFramework, version=v4.5""
MinVSVersion = ""11.0""
AppliesTo = ""WindowsAppContainer + WindowsXAML""
SupportPrefer32Bit = ""True""
SupportedArchitectures = ""x86;x64;ARM""
SupportsMultipleVersions = ""Error""
AppX-Debug-x86 = "".\AppX\Debug\x86\Microsoft.MySDK.x86.Debug.1.0.appx""
AppX-Debug-x64 = "".\AppX\Debug\x64\Microsoft.MySDK.x64.Debug.1.0.appx""
AppX-Debug-ARM = "".\AppX\Debug\ARM\Microsoft.MySDK.ARM.Debug.1.0.appx""
AppX-Retail-x86 = "".\AppX\Retail\x86\Microsoft.MySDK.x86.1.0.appx""
AppX-Retail-x64 = "".\AppX\Retail\x64\Microsoft.MySDK.x64.1.0.appx""
AppX-Retail-ARM = "".\AppX\Retail\ARM\Microsoft.MySDK.ARM.1.0.appx""
CopyRedistToSubDirectory = "".""
DependsOn = ""SDKB, version=2.0""
MoreInfo = ""http://msdn.microsoft.com/MySDK""
MaxPlatformVersion = ""8.0""
MinOSVersion = ""6.2.1""
MaxOSVersionTested = ""6.2.1"">
<!-- New Style -->
<ContainedApiContracts>
<ApiContractCopy name="UAP" version="1.0.0.0" />
</ContainedApiContracts>
<File Reference = ""MySDK.Sprint.winmd"" Implementation = ""XNASprintImpl.dll"">
<Registration Type = ""Flipper"" Implementation = ""XNASprintFlipperImpl.dll"" />
<Registration Type = ""Flexer"" Implementation = ""XNASprintFlexerImpl.dll"" />
<ToolboxItems VSCategory = ""Toolbox.Default"" />
</File>
</FileList>
Platform SDK Manifest:
<FileList
DisplayName = ""Windows""
PlatformIdentity = ""Windows, version=8.0""
TargetFramework = "".NETCore, version=v4.5; .NETFramework, version=v4.5""
MinVSVersion = ""11.0""
MinOSVersion = ""6.2.1""
MaxOSVersionTested = ""6.2.1""
UnsupportedDowntarget = ""Windows, version=8.0"">
<File Reference = ""Windows"">
<ToolboxItems VSCategory = ""Toolbox.Default""/>
</File>
</FileList>
*/
string sdkManifestPath = Path.Combine(_pathToSdk, "SDKManifest.xml");
try
{
if (File.Exists(sdkManifestPath))
{
XmlDocument doc = new XmlDocument();
XmlReaderSettings readerSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore };
using (XmlReader xmlReader = XmlReader.Create(sdkManifestPath, readerSettings))
{
doc.Load(xmlReader);
}
XmlElement rootElement = null;
foreach (XmlNode childNode in doc.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Element &&
string.Equals(childNode.Name, Elements.FileList, StringComparison.Ordinal))
{
rootElement = (XmlElement)childNode;
break;
}
}
if (rootElement != null)
{
ReadFileListAttributes(rootElement.Attributes);
foreach (XmlNode childNode in rootElement.ChildNodes)
{
if (!(childNode is XmlElement childElement))
{
continue;
}
if (ApiContract.IsContainedApiContractsElement(childElement.Name))
{
ApiContracts = new List<ApiContract>();
ApiContract.ReadContractsElement(childElement, ApiContracts);
}
}
}
}
}
catch (Exception e)
{
ReadError = true;
ReadErrorMessage = e.Message;
}
}
/// <summary>
/// Reads the attributes from the "FileList" element of the SDK manifest.
/// </summary>
private void ReadFileListAttributes(XmlAttributeCollection attributes)
{
foreach (XmlAttribute attribute in attributes.OfType<XmlAttribute>())
{
string value = attribute.Value.Trim();
if (value.Length > 0)
{
if (attribute.Name.StartsWith(Attributes.FrameworkIdentity, StringComparison.OrdinalIgnoreCase))
{
if (_frameworkIdentities == null)
{
_frameworkIdentities = new Dictionary<string, string>();
}
_frameworkIdentities.Add(attribute.Name, value);
continue;
}
if (attribute.Name.StartsWith(Attributes.APPX, StringComparison.OrdinalIgnoreCase))
{
if (_appxLocations == null)
{
_appxLocations = new Dictionary<string, string>();
}
_appxLocations.Add(attribute.Name, value);
continue;
}
switch (attribute.Name)
{
case Attributes.TargetPlatform:
TargetPlatform = value;
break;
case Attributes.TargetPlatformMinVersion:
TargetPlatformMinVersion = value;
break;
case Attributes.TargetPlatformVersion:
TargetPlatformVersion = value;
break;
case Attributes.MinVSVersion:
MinVSVersion = value;
break;
case Attributes.MinOSVersion:
_minOSVersion = value;
break;
case Attributes.MaxOSVersionTested:
_maxOSVersionTested = value;
break;
case Attributes.MaxPlatformVersion:
_maxPlatformVersion = value;
break;
case Attributes.PlatformIdentity:
PlatformIdentity = value;
break;
case Attributes.SupportPrefer32Bit:
SupportPrefer32Bit = value;
break;
case Attributes.SupportsMultipleVersions:
_supportsMultipleVersions = ParseSupportMultipleVersions(value);
break;
case Attributes.SDKType:
Enum.TryParse(value, out _sdkType);
break;
case Attributes.DisplayName:
DisplayName = value;
break;
case Attributes.MoreInfo:
MoreInfo = value;
break;
case Attributes.CopyRedistToSubDirectory:
CopyRedistToSubDirectory = value;
break;
case Attributes.SupportedArchitectures:
SupportedArchitectures = value;
break;
case Attributes.DependsOnSDK:
DependsOnSDK = value;
break;
case Attributes.ProductFamilyName:
ProductFamilyName = value;
break;
}
}
}
}
/// <summary>
/// Parse the multipleversions string. Returns MultipleVersionSupport.Allow if it cannot be parsed correctly.
/// </summary>
private static MultipleVersionSupport ParseSupportMultipleVersions(string multipleVersionsValue)
=> !string.IsNullOrEmpty(multipleVersionsValue) && Enum.TryParse(multipleVersionsValue, /*ignoreCase*/true, out MultipleVersionSupport supportsMultipleVersions)
? supportsMultipleVersions
: MultipleVersionSupport.Allow;
/// <summary>
/// Helper class with attributes of SDKManifest.xml
/// </summary>
public static class Attributes
{
/// <summary>
/// Platform that the SDK targets
/// </summary>
public const string TargetPlatform = "TargetPlatform";
/// <summary>
/// The minimum version of the platform that the SDK targets
/// </summary>
public const string TargetPlatformMinVersion = "TargetPlatformMinVersion";
/// <summary>
/// The max version of the platform that the SDK targets
/// </summary>
public const string TargetPlatformVersion = "TargetPlatformVersion";
/// <summary>
/// Framework Identity metadata name and manifest attribute
/// </summary>
public const string FrameworkIdentity = "FrameworkIdentity";
/// <summary>
/// Supported Architectures metadata name and manifest attribute
/// </summary>
public const string SupportedArchitectures = "SupportedArchitectures";
/// <summary>
/// Prefer32BitSupport metadata name and manifest attribute
/// </summary>
public const string SupportPrefer32Bit = "SupportPrefer32Bit";
/// <summary>
/// AppxLocation metadata
/// </summary>
public const string AppxLocation = "AppxLocation";
/// <summary>
/// APPX manifest attribute
/// </summary>
public const string APPX = "APPX";
/// <summary>
/// PlatformIdentity metadata name and manifest attribute
/// </summary>
public const string PlatformIdentity = "PlatformIdentity";
/// <summary>
/// SDKType metadata name and manifest attribute
/// </summary>
public const string SDKType = "SDKType";
/// <summary>
/// DisplayName metadata name and manifest attribute
/// </summary>
public const string DisplayName = "DisplayName";
/// <summary>
/// CopyRedistToSubDirectory metadata name and manifest attribute
/// </summary>
public const string CopyRedistToSubDirectory = "CopyRedistToSubDirectory";
/// <summary>
/// ProductFamilyName metadata name and manifest attribute
/// </summary>
public const string ProductFamilyName = "ProductFamilyName";
/// <summary>
/// SupportsMultipleVersions metadata name and manifest attribute
/// </summary>
public const string SupportsMultipleVersions = "SupportsMultipleVersions";
/// <summary>
/// TargetedSDKArchitecture metadata name
/// </summary>
public const string TargetedSDK = "TargetedSDKArchitecture";
/// <summary>
/// TargetedSDKConfiguration metadata name
/// </summary>
public const string TargetedSDKConfiguration = "TargetedSDKConfiguration";
/// <summary>
/// ExpandReferenceAssemblies metadata name
/// </summary>
public const string ExpandReferenceAssemblies = "ExpandReferenceAssemblies";
/// <summary>
/// DependsOn metadata name
/// </summary>
public const string DependsOnSDK = "DependsOn";
/// <summary>
/// CopyRedist metadata name
/// </summary>
public const string CopyRedist = "CopyRedist";
/// <summary>
/// CopyLocalExpandedReferenceAssemblies metadata name
/// </summary>
public const string CopyLocalExpandedReferenceAssemblies = "CopyLocalExpandedReferenceAssemblies";
// Dev 12 new attributes
/// <summary>
/// MinOSVersion metadata name
/// </summary>
public const string MinOSVersion = "MinOSVersion";
/// <summary>
/// MinVSVersion metadata name
/// </summary>
public const string MinVSVersion = "MinVSVersion";
/// <summary>
/// MaxPlatformVersionAttribute metadata name
/// </summary>
public const string MaxPlatformVersion = "MaxPlatformVersion";
/// <summary>
/// MoreInfoAttribute metadata name
/// </summary>
public const string MoreInfo = "MoreInfo";
/// <summary>
/// MaxOSVersionTestedAttribute metadata name
/// </summary>
public const string MaxOSVersionTested = "MaxOSVersionTested";
}
/// <summary>
/// Helper class with elements of SDKManifest.xml
/// </summary>
private static class Elements
{
/// <summary>
/// Root element
/// </summary>
public const string FileList = "FileList";
}
}
}