From ef6a1dda0a1869b52810e76922f008bc16737e1f Mon Sep 17 00:00:00 2001 From: dahall Date: Sun, 26 Jul 2020 13:12:33 -0600 Subject: [PATCH] Added improved registry key closing to registration classes --- Windows.Shell/Registration/FileTypeAssociation.cs | 7 ++++--- Windows.Shell/Registration/ProgId.cs | 9 ++++++--- Windows.Shell/Registration/RegBasedKeyCollection.cs | 18 +++++++++++------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Windows.Shell/Registration/FileTypeAssociation.cs b/Windows.Shell/Registration/FileTypeAssociation.cs index 7ba14598..ff512a0c 100644 --- a/Windows.Shell/Registration/FileTypeAssociation.cs +++ b/Windows.Shell/Registration/FileTypeAssociation.cs @@ -11,7 +11,8 @@ namespace Vanara.Windows.Shell.Registration internal FileTypeAssociation(string ext, RegistryKey key, bool readOnly) : base(key, readOnly) { Extension = ext; - OpenWithProgIds = new RegBasedKeyCollection(key.OpenSubKey("OpenWithProgIds", !readOnly), readOnly); + var owpi = readOnly ? key.OpenSubKey("OpenWithProgIds", false) : key.CreateSubKey("OpenWithProgIds", RegistryKeyPermissionCheck.ReadWriteSubTree); + OpenWithProgIds = new RegBasedKeyCollection(owpi, readOnly); } /// Gets or sets the Content Type value to the file type's MIME content type. @@ -120,8 +121,8 @@ namespace Vanara.Windows.Shell.Registration { if (extension is null) throw new ArgumentNullException(nameof(extension)); if (!extension.StartsWith(".")) throw new ArgumentException("The value must be in the format \".ext\"", nameof(extension)); - using var sk = ShellRegistrar.GetRoot(systemWide, true); - try { sk.DeleteSubKeyTree(extension); } catch { sk.DeleteSubKey(extension, false); } + using (var sk = ShellRegistrar.GetRoot(systemWide, true)) + try { sk.DeleteSubKeyTree(extension); } catch { sk.DeleteSubKey(extension, false); } ShellRegistrar.NotifyShell(); } diff --git a/Windows.Shell/Registration/ProgId.cs b/Windows.Shell/Registration/ProgId.cs index 0023932f..db0a03b6 100644 --- a/Windows.Shell/Registration/ProgId.cs +++ b/Windows.Shell/Registration/ProgId.cs @@ -292,8 +292,10 @@ namespace Vanara.Windows.Shell using var root = ShellRegistrar.GetRoot(systemWide, false); foreach (var ext in root.GetSubKeyNames().Where(ext => ext.StartsWith("."))) { - using var openWithKey = root.OpenSubKey(Path.Combine(ext, OpenWithProgIds)); - if (openWithKey?.HasValue(progId) == true) + var hasValue = false; + using (var openWithKey = root.OpenSubKey(Path.Combine(ext, OpenWithProgIds))) + hasValue = openWithKey?.HasValue(progId) ?? false; + if (hasValue) yield return ext; } } @@ -332,7 +334,8 @@ namespace Vanara.Windows.Shell public void Add(string ext) { EnsureWritable(); - FileTypeAssociation.Register(ext, IsSystemWide).OpenWithProgIds.Add(progId); + using var assoc = FileTypeAssociation.Register(ext, IsSystemWide); + assoc.OpenWithProgIds.Add(progId); } /// Clears this instance. diff --git a/Windows.Shell/Registration/RegBasedKeyCollection.cs b/Windows.Shell/Registration/RegBasedKeyCollection.cs index 05cec76c..309098bd 100644 --- a/Windows.Shell/Registration/RegBasedKeyCollection.cs +++ b/Windows.Shell/Registration/RegBasedKeyCollection.cs @@ -8,7 +8,7 @@ namespace Vanara.Windows.Shell.Registration { /// A collection of values under a key that is treated as a collection of strings. /// - internal class RegBasedKeyCollection : ICollection + internal class RegBasedKeyCollection : ICollection, IDisposable { /// The base key from which to perform all queries. protected internal RegistryKey key; @@ -18,13 +18,14 @@ namespace Vanara.Windows.Shell.Registration /// if set to true the supplied was opened read-only. protected internal RegBasedKeyCollection(RegistryKey key, bool readOnly) { - this.key = key ?? throw new ArgumentNullException(nameof(key)); + if (key is null && !readOnly) throw new ArgumentNullException(nameof(key)); + this.key = key; IsReadOnly = readOnly; } /// Gets the count. /// The count. - public int Count => key.ValueCount; + public int Count => key?.ValueCount ?? 0; /// Gets or sets a value indicating whether these settings are read-only. public bool IsReadOnly { get; } @@ -34,21 +35,24 @@ namespace Vanara.Windows.Shell.Registration public void Add(string item) { EnsureWritable(); key.SetValue(item, string.Empty, RegistryValueKind.String); } /// Clears this instance. - public void Clear() => key.DeleteAllSubItems(); + public void Clear() { EnsureWritable(); key.DeleteAllSubItems(); } /// Determines whether this instance contains the object. /// The item. /// if [contains] [the specified item]; otherwise, . - public bool Contains(string item) => key.HasValue(item); + public bool Contains(string item) => key?.HasValue(item) ?? false; /// Copies to. /// The array. /// Index of the array. - public void CopyTo(string[] array, int arrayIndex) => Array.Copy(key.GetValueNames(), 0, array, arrayIndex, Count); + public void CopyTo(string[] array, int arrayIndex) { if (key != null) Array.Copy(key.GetValueNames(), 0, array, arrayIndex, Count); } + + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + public void Dispose() => key?.Close(); /// Gets the enumerator. /// - public IEnumerator GetEnumerator() => key.GetValueNames().Cast().GetEnumerator(); + public IEnumerator GetEnumerator() => (key?.GetValueNames().Cast() ?? new string[0]).GetEnumerator(); /// Removes the specified item. /// The item.