Created
August 24, 2017 00:06
-
-
Save otuncelli/18209f687879616b2a045f06b92df04e to your computer and use it in GitHub Desktop.
Windows File Extension Association Helper Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Runtime.InteropServices; | |
using Microsoft.Win32; | |
namespace DiskCatalog.Classes | |
{ | |
public sealed class FileAssociation | |
{ | |
public string Extension { get; } | |
public string ProgId { get; } | |
public string Description { get; } | |
private readonly string _execPath = Assembly.GetExecutingAssembly().Location; | |
private readonly Scope _scope; | |
public FileAssociation(string extension, string progId, string description, Scope scope) | |
{ | |
Extension = extension; | |
ProgId = progId; | |
Description = description; | |
_scope = scope; | |
} | |
public void EnsureSet(bool editContext, bool resetExplorerOverride) | |
{ | |
var changeNotify = false; | |
RegistryKey classesKey = _scope == Scope.Root | |
? Registry.ClassesRoot | |
: Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Classes", true); | |
if (classesKey == null) | |
throw new NullReferenceException(); | |
try | |
{ | |
using (RegistryKey extensionKey = classesKey.CreateSubKey(Extension)) | |
{ | |
if (extensionKey == null) | |
throw new NullReferenceException(); | |
extensionKey.SetValue(null, ProgId); | |
} | |
using (RegistryKey progIdKey = classesKey.CreateSubKey(ProgId, | |
RegistryKeyPermissionCheck.ReadWriteSubTree)) | |
{ | |
if (progIdKey == null) | |
throw new NullReferenceException(); | |
progIdKey.SetValue(null, Description); | |
using (RegistryKey keyIcon = progIdKey.CreateSubKey("DefaultIcon")) | |
{ | |
if (keyIcon == null) | |
throw new NullReferenceException(); | |
keyIcon.SetValue(null, $"\"{_execPath}\",0"); | |
} | |
using (RegistryKey shellKey = progIdKey.CreateSubKey("Shell")) | |
{ | |
if (shellKey == null) | |
throw new NullReferenceException(); | |
if (SetShellCommand(shellKey, "open")) | |
changeNotify = true; | |
if (editContext) | |
{ | |
if (SetShellCommand(shellKey, "edit")) | |
changeNotify = true; | |
} | |
else | |
{ | |
try | |
{ | |
shellKey.DeleteSubKeyTree("edit", true); | |
changeNotify = true; | |
} | |
catch (ArgumentException) | |
{ | |
} | |
} | |
} | |
} | |
} | |
finally | |
{ | |
classesKey.Dispose(); | |
} | |
if (resetExplorerOverride && ResetExplorerOverride()) | |
changeNotify = true; | |
if (changeNotify) | |
NativeMethods.SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero); | |
} | |
public void UnSet(bool resetExplorerOverride) | |
{ | |
var changeNotify = false; | |
RegistryKey classesKey = _scope == Scope.Root | |
? Registry.ClassesRoot | |
: Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Classes", true); | |
if (classesKey == null) | |
throw new NullReferenceException(); | |
try | |
{ | |
try | |
{ | |
classesKey.DeleteSubKey(Extension, true); | |
changeNotify = true; | |
} | |
catch (ArgumentException) | |
{ | |
} | |
try | |
{ | |
classesKey.DeleteSubKeyTree(ProgId, true); | |
changeNotify = true; | |
} | |
catch (ArgumentException) | |
{ | |
} | |
} | |
finally | |
{ | |
classesKey.Dispose(); | |
} | |
if (resetExplorerOverride && ResetExplorerOverride()) | |
changeNotify = true; | |
if (changeNotify) | |
NativeMethods.SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero); | |
} | |
private bool SetShellCommand(RegistryKey shellKey, string cmdKeyName) | |
{ | |
var changeNotify = false; | |
using (RegistryKey cmdKey = shellKey.CreateSubKey(cmdKeyName)) | |
{ | |
if (cmdKey == null) | |
throw new NullReferenceException(); | |
using (RegistryKey commandKey = cmdKey.OpenSubKey("command")) | |
if (commandKey == null) | |
changeNotify = true; | |
using (RegistryKey commandKey = cmdKey.CreateSubKey("command")) | |
{ | |
if (commandKey == null) | |
throw new NullReferenceException(); | |
commandKey.SetValue(null, $"\"{_execPath}\" \"%1\""); | |
} | |
} | |
return changeNotify; | |
} | |
private bool ResetExplorerOverride() | |
{ | |
string keyPath = $@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{Extension}"; | |
using (RegistryKey currentUser = Registry.CurrentUser) | |
using (RegistryKey explorerOverride = currentUser.OpenSubKey(keyPath, true)) | |
{ | |
if (explorerOverride != null) | |
{ | |
try | |
{ | |
explorerOverride.DeleteSubKey("UserChoice", true); | |
return true; | |
} | |
catch (ArgumentException) | |
{ | |
} | |
} | |
} | |
return false; | |
} | |
public enum Scope | |
{ | |
CurrentUser, | |
Root | |
} | |
private const int SHCNE_ASSOCCHANGED = 0x8000000; | |
private const int SHCNF_FLUSH = 0x1000; | |
private static class NativeMethods | |
{ | |
[DllImport("shell32", CharSet = CharSet.Auto, SetLastError = true)] | |
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment