using Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; using Vanara.Collections; using Vanara.Windows.Shell.Registration; namespace Vanara.Windows.Shell { /// A virtual dictionary that is based on values in the Windows Registry. /// Type used to capture multiple values within the registry. /// public abstract class RegBasedDictionary : VirtualReadOnlyDictionary { /// Read-only flag. protected readonly bool readOnly; /// The base registry key for this dictionary. protected RegistryKey key; /// Initializes a new instance of the class. /// The base registry key. /// if set to render this dictionary read-only. protected RegBasedDictionary(RegistryKey baseKey, bool readOnly) { key = baseKey; this.readOnly = readOnly; } /// Get the filtered list of keys under the base. public override IEnumerable Keys => key?.GetSubKeyNames().Where(SubKeyFilter) ?? new string[0]; /// Determines if a specified key is in the filtered list of keys under the base. /// The name of the key to check. /// if the key is found; otherwise . public override bool ContainsKey(string key) => (this.key?.HasSubKey(key) ?? false) && SubKeyFilter(key); /// /// Returns a value that indicates if the provided value should be included in the list of available keys. /// /// Name of the key. /// if is an included key; otherwise . protected virtual bool SubKeyFilter(string keyName) => true; } internal class AppDictionary : RegBasedDictionary { public AppDictionary(bool readOnly) : base(Registry.ClassesRoot.OpenSubKey(AppRegistration.appsSubKey, !readOnly), readOnly) { } public override bool TryGetValue(string key, out AppRegistration value) { value = null; if (!ContainsKey(key)) return false; var sk = base.key.OpenSubKey(key, !readOnly); value = sk is null ? null : new AppRegistration(sk, null, readOnly); return !(value is null); } } internal class FileTypeDictionary : RegBasedDictionary { public FileTypeDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly) { } public override bool TryGetValue(string key, out FileTypeAssociation value) { value = null; if (!ContainsKey(key)) return false; value = FileTypeAssociation.Open(key, false, readOnly); return !(value is null); } protected override bool SubKeyFilter(string keyName) => keyName.StartsWith("."); } internal class ProgIdDictionary : RegBasedDictionary { private static readonly string[] badKeys = { "*", "AllFileSystemObjects", "AppID", "Applications", "AudioCD", "Briefcase", "CID", "CID.Local", "CLSID", "CompressedFolder", "ConflictFolder", "DVD", "DVDFile", "DesktopBackground", "DirectShow", "Directory", "Drive", "ExplorerCLSIDFlags", "Folder", "Interface", "LibraryFolder", "Local Settings", "MIME", "Media Servers", "Media Type", "MediaFoundation", "NetServer", "NetShare", "Network", "Printers", "Stack", "SystemFileAssociations", "TypeLib", "Unknown", "UserLibraryFolder", "VideoClipContainers", "VirtualStore" }; public ProgIdDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly) { } public override bool TryGetValue(string key, out ProgId value) { value = null; if (!ContainsKey(key)) return false; value = ProgId.Open(key, readOnly); return true; } protected override bool SubKeyFilter(string keyName) => !keyName.StartsWith(".") && !keyName.StartsWith("Kind.") && Array.BinarySearch(badKeys, keyName, StringComparer.OrdinalIgnoreCase) < 0; } internal class ShellAssociationDictionary : RegBasedDictionary { public ShellAssociationDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly) { } public override bool TryGetValue(string key, out ShellAssociation value) { value = null; if (!ContainsKey(key)) return false; value = ShellAssociation.FromFileExtension(key); return !(value is null); } protected override bool SubKeyFilter(string keyName) => keyName.StartsWith("."); } }