/* * Copyright (c) 2006, Brendan Grant (grantb@dahat.com) * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * All original and modified versions of this source code must include the * above copyright notice, this list of conditions and the following * disclaimer. * * This code may not be used with or within any modules or code that is * licensed in any way that that compels or requires users or modifiers * to release their source code or changes as a requirement for * the use, modification or distribution of binary, object or source code * based on the licensed source code. (ex: Cannot be used with GPL code.) * * The name of Brendan Grant may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRENDAN GRANT ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL BRENDAN GRANT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Collections.Generic; using Microsoft.Win32; using System.Xml.Serialization; namespace BrendanGrant.Helpers.FileAssociation { #region Public Enums /// /// Broad categories of system recognized file format types. /// public enum PerceivedTypes { /// /// No /// None, /// /// Image file /// Image, /// /// Text file /// Text, /// /// Audio file /// Audio, /// /// Video file /// Video, /// /// Compressed file /// Compressed, /// /// System file /// System, } #endregion /// /// Provides instance methods for the creation, modification, and deletion of file extension associations in the Windows registry. /// public class FileAssociationInfo { private RegistryWrapper registryWrapper = new RegistryWrapper(); /// /// Gets array containing known file extensions from HKEY_CLASSES_ROOT. /// /// String array containing extensions. public static string[] GetExtensions() { RegistryKey root = Registry.ClassesRoot; List extensionList = new List(); string[] subKeys = root.GetSubKeyNames(); foreach (string subKey in subKeys) { //TODO: Consider removing dot? if (subKey.StartsWith(".")) { extensionList.Add(subKey); } } return extensionList.ToArray(); ; } private string extension; /// /// Gets or sets a value that determines the MIME type of the file. /// public string ContentType { get { return GetContentType(this); } set { SetContentType(this, value); } } /// /// Gets a value indicating whether the extension exists. /// public bool Exists { get { RegistryKey root = Registry.ClassesRoot; try { RegistryKey key = root.OpenSubKey(extension); if (key == null) return false; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } return true; } } /// /// Gets the name of the extension. /// public string Extension { get { return extension; } set { extension = value; } } /// /// Gets or sets array of containing program file names which should be displayed in the Open With List. /// /// notepad.exe, wordpad.exe, othertexteditor.exe public string[] OpenWithList { get { return GetOpenWithList(this); } set { SetOpenWithList(this, value); } } /// /// Gets or sets a value that determines the of the file. /// public PerceivedTypes PerceivedType { get { return GetPerceivedType(this); } set { SetPerceivedType(this, value); } } /// /// Gets or sets a value that indicates the filter component that is used to search for text within documents of this type. /// public Guid PersistentHandler { get { return GetPersistentHandler(this); } set { SetPersistentHandler(this, value); } } /// /// Gets or set a value that indicates the name of the associated application with the behavior to handle this extension. /// [XmlAttribute()] public string ProgID { get { return GetProgID(this); } set { SetProgID(this, value); } } /// /// Creates the extension key. /// public void Create() { Create(this); } /// /// Deletes the extension key. /// public void Delete() { Delete(this); } /// /// Verifies that given extension exists and is associated with given program id /// /// Extension to be checked for. /// progId to be checked for. /// True if association exists, false if it does not. public bool IsValid(string extension, string progId) { FileAssociationInfo fai = new FileAssociationInfo(extension); if (!fai.Exists) return false; if (progId != fai.ProgID) return false; return true; } /// /// Initializes a new instance of the FileAssociationInfo class, which acts as a wrapper for a file extension within the registry. /// /// The dot prefixed extension. /// FileAssociationInfo(".mp3") /// FileAssociationInfo(".txt") /// FileAssociationInfo(".doc") public FileAssociationInfo(string extension) { this.extension = extension; } #region Public Functions - Creators /// /// Creates actual extension association key in registry for the specified extension and supplied attributes. /// /// Name of expected handling program. /// FileAssociationInfo instance referring to specified extension. public FileAssociationInfo Create(string progId) { return Create(progId, PerceivedTypes.None, string.Empty, null); } /// /// Creates actual extension association key in registry for the specified extension and supplied attributes. /// /// Name of expected handling program. /// PerceivedType of file type. /// FileAssociationInfo instance referring to specified extension. public FileAssociationInfo Create(string progId, PerceivedTypes perceivedType) { return Create(progId, perceivedType, string.Empty, null); } /// /// Creates actual extension association key in registry for the specified extension and supplied attributes. /// /// Name of expected handling program. /// PerceivedType of file type. /// MIME type of file type. /// FileAssociationInfo instance referring to specified extension. public FileAssociationInfo Create(string progId, PerceivedTypes perceivedType, string contentType) { return Create(progId, PerceivedTypes.None, contentType, null); } /// /// Creates actual extension association key in registry for the specified extension and supplied attributes. /// /// Name of expected handling program. /// PerceivedType of file type. /// MIME type of file type. /// /// FileAssociationInfo instance referring to specified extension. public FileAssociationInfo Create(string progId, PerceivedTypes perceivedType, string contentType, string[] openwithList) { FileAssociationInfo fai = new FileAssociationInfo(extension); if (fai.Exists) { fai.Delete(); } fai.Create(); fai.ProgID = progId; if (perceivedType != PerceivedTypes.None) fai.PerceivedType = perceivedType; if (contentType != string.Empty) fai.ContentType = contentType; if (openwithList != null) fai.OpenWithList = openwithList; return fai; } #endregion #region Private Functions - Property backend /// /// Gets array of containing program file names which should be displayed in the Open With List. /// /// that provides specifics of the extension to be changed. /// Program file names protected string[] GetOpenWithList(FileAssociationInfo file) { if (!file.Exists) throw new Exception("Extension does not exist"); RegistryKey root = Registry.ClassesRoot; RegistryKey key = root.OpenSubKey(file.extension); key = key.OpenSubKey("OpenWithList"); if (key == null) { return new string[0]; } return key.GetSubKeyNames(); } /// /// Sets array of containing program file names which should be displayed in the Open With List. /// /// that provides specifics of the extension to be changed. /// Program file names protected void SetOpenWithList(FileAssociationInfo file, string[] programList) { if (!file.Exists) throw new Exception("Extension does not exist"); RegistryKey root = Registry.ClassesRoot; RegistryKey key = root.OpenSubKey(file.extension, true); RegistryKey tmpkey = key.OpenSubKey("OpenWithList", true); if (tmpkey != null) { key.DeleteSubKeyTree("OpenWithList"); } key = key.CreateSubKey("OpenWithList"); foreach (string s in programList) { key.CreateSubKey(s); } ShellNotification.NotifyOfChange(); } /// /// Gets or value that determines the PerceivedType of the file. /// /// that provides specifics of the extension to be changed. /// that specifies Perceived Type of extension. protected PerceivedTypes GetPerceivedType(FileAssociationInfo file) { if (!file.Exists) throw new Exception("Extension does not exist"); object val = registryWrapper.Read(file.extension, "PerceivedType"); PerceivedTypes actualType = PerceivedTypes.None; if (val == null) return actualType; try { actualType = (PerceivedTypes)Enum.Parse(typeof(PerceivedTypes), val.ToString(), true); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return actualType; } /// /// Sets a value that determines the PerceivedType of the file. /// /// that provides specifics of the extension to be changed. /// to be set that specifies Perceived Type of extension. protected void SetPerceivedType(FileAssociationInfo file, PerceivedTypes type) { if (!file.Exists) throw new Exception("Extension does not exist"); registryWrapper.Write(file.extension, "PerceivedType", type.ToString()); ShellNotification.NotifyOfChange(); } /// /// Gets a value that indicates the filter component that is used to search for text within documents of this type. /// /// that provides specifics of the extension to be changed. /// Guid of filter component. protected Guid GetPersistentHandler(FileAssociationInfo file) { if (!file.Exists) throw new Exception("Extension does not exist"); object val = registryWrapper.Read(file.extension + "\\PersistentHandler", string.Empty); if (val == null) return new Guid(); else return new Guid(val.ToString()); } /// /// Sets a value that indicates the filter component that is used to search for text within documents of this type. /// /// that provides specifics of the extension to be changed. /// Guid of filter component. protected void SetPersistentHandler(FileAssociationInfo file, Guid persistentHandler) { if (!file.Exists) throw new Exception("Extension does not exist"); if (persistentHandler == Guid.Empty) return; this.registryWrapper.Write(file.extension + "\\" + PersistentHandler, string.Empty, persistentHandler); ShellNotification.NotifyOfChange(); } /// /// Gets a value that determines the MIME type of the file. /// /// that provides specifics of the extension to be changed. /// MIME content type of extension. protected string GetContentType(FileAssociationInfo file) { if (!file.Exists) throw new Exception("Extension does not exist"); object val = registryWrapper.Read(file.extension, "Content Type"); if (val == null) { return string.Empty; } else { return val.ToString(); } } /// /// Sets a value that determines the MIME type of the file. /// /// that provides specifics of the extension to be changed. /// MIME content type of extension. protected void SetContentType(FileAssociationInfo file, string type) { if (!file.Exists) throw new Exception("Extension does not exist"); registryWrapper.Write(file.extension, "Content Type", type); ShellNotification.NotifyOfChange(); } /// /// Gets a value that indicates the name of the associated application with the behavior to handle this extension. /// /// that provides specifics of the extension to be changed. /// Associated Program ID of handling program. protected string GetProgID(FileAssociationInfo file) { if (!file.Exists) throw new Exception("Extension does not exist"); object val = registryWrapper.Read(file.extension, string.Empty); if (val == null) return string.Empty; return val.ToString(); } /// /// Set a value that indicates the name of the associated application with the behavior to handle this extension. /// /// that provides specifics of the extension to be changed. /// Associated Program ID of handling program. protected void SetProgID(FileAssociationInfo file, string progId) { if (!file.Exists) throw new Exception("Extension does not exist"); registryWrapper.Write(file.extension, string.Empty, progId); ShellNotification.NotifyOfChange(); } #endregion /// /// Creates actual file extension entry in registry. /// /// instance that contains specifics on extension to be created. protected void Create(FileAssociationInfo file) { if (file.Exists) { file.Delete(); } RegistryKey root = Registry.ClassesRoot; root.CreateSubKey(file.extension); } /// /// Deletes actual file extension entry in registry. /// /// instance that contains specifics on extension to be deleted. protected void Delete(FileAssociationInfo file) { if (!file.Exists) { throw new Exception("Key not found."); } RegistryKey root = Registry.ClassesRoot; root.DeleteSubKeyTree(file.extension); } } }