/// <summary> /// Initializes a new instance of the <see cref="Instance"/> class. /// </summary> /// <param name="instance">The <see cref="ISetupInstance2"/> to adapt.</param> /// <exception cref="ArgumentNullException"><paramref name="instance"/> is null.</exception> internal Instance(ISetupInstance2 instance) { Validate.NotNull(instance, nameof(instance)); // The instance ID is required, but then try to set other properties to release the COM object and its resources ASAP. InstanceId = instance.GetInstanceId(); TrySet(ref installationName, nameof(InstallationName), instance.GetInstallationName); TrySet(ref installationPath, nameof(InstallationPath), instance.GetInstallationPath); TrySet(ref installationVersion, nameof(InstallationVersion), () => { Version version; var versionString = instance.GetInstallationVersion(); if (Version.TryParse(versionString, out version)) { return(version.Normalize()); } return(null); }); TrySet(ref installDate, nameof(InstallDate), () => { var ft = instance.GetInstallDate(); var l = ((long)ft.dwHighDateTime << 32) + ft.dwLowDateTime; return(DateTime.FromFileTime(l)); }); TrySet(ref state, nameof(State), instance.GetState); var lcid = CultureInfo.CurrentUICulture.LCID; TrySet(ref displayName, nameof(DisplayName), () => { return(instance.GetDisplayName(lcid)); }); TrySet(ref description, nameof(Description), () => { return(instance.GetDescription(lcid)); }); TrySet(ref productPath, nameof(ProductPath), () => { var path = instance.GetProductPath(); return(instance.ResolvePath(path)); }); TrySet(ref product, nameof(Product), () => { var reference = instance.GetProduct(); if (reference != null) { return(new PackageReference(reference)); } return(null); }); TrySet(ref packages, nameof(Packages), () => { return(new List <PackageReference>(GetPackages(instance))); }); if (packages != null && packages.Any()) { Packages = new ReadOnlyCollection <PackageReference>(packages); } TrySet(ref properties, nameof(Properties), () => { var properties = instance.GetProperties(); return(properties?.GetNames() .ToDictionary(name => name.ToPascalCase(), name => properties.GetValue(name), StringComparer.OrdinalIgnoreCase)); }); if (properties != null) { Properties = new ReadOnlyDictionary <string, object>(properties); } else { // While accessing properties on a null object succeeds in PowerShell, accessing the indexer does not. Properties = ReadOnlyDictionary <string, object> .Empty; } TrySet(ref enginePath, nameof(EnginePath), instance.GetEnginePath); TrySet(ref isComplete, nameof(IsComplete), instance.IsComplete); TrySet(ref isLaunchable, nameof(IsLaunchable), instance.IsLaunchable); // Get all properties of the instance not explicitly declared. var store = (ISetupPropertyStore)instance; AdditionalProperties = store.GetNames() .Where(name => !DeclaredProperties.Contains(name)) .ToDictionary(name => name.ToPascalCase(), name => store.GetValue(name), StringComparer.OrdinalIgnoreCase); }