vbAccelerator - Contents of code file: IFilter_FileClasses.csusing System;
using System.Collections;
using Microsoft.Win32;
namespace vbAccelerator.Components.Shell
{
#region Public Enumerations
/// <summary>
/// Specifies registry hives for which ClassAssociations can be set
/// </summary>
public enum FileClassKeyHive : int
{
ClassesRoot,
LocalMachine,
CurrentUser
}
#endregion
#region FileClassUtility
public class FileClassUtility
{
public static Microsoft.Win32.RegistryKey GetRootKey(FileClassKeyHive
baseKey)
{
RegistryKey rootKey = null;
switch (baseKey)
{
case FileClassKeyHive.LocalMachine:
rootKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes");
break;
case FileClassKeyHive.ClassesRoot:
rootKey = Registry.ClassesRoot;
break;
case FileClassKeyHive.CurrentUser:
rootKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Classes");
break;
}
return rootKey;
}
}
#endregion
#region FileClasses
/// <summary>
/// A read-only collection of all the FileClasses currently installed
/// </summary>
public class FileClasseNames : ReadOnlyCollectionBase
{
private FileClassKeyHive m_baseKey;
public string this[int index]
{
get
{
return (string)this.InnerList[index];
}
}
public void Refresh()
{
this.InnerList.Clear();
RegistryKey rootKey = FileClassUtility.GetRootKey(m_baseKey);
string[] keys = rootKey.GetSubKeyNames();
Hashtable candidateClasses = new Hashtable();
int i = 0;
while (!keys[i].StartsWith("."))
{
i++;
}
while (keys[i].StartsWith("."))
{
RegistryKey extKey = rootKey.OpenSubKey(keys[i]);
string candidate = (string)extKey.GetValue("", "");
extKey.Close();
if (candidate.Trim().Length > 0)
{
if (!candidateClasses.ContainsKey(candidate))
{
candidateClasses.Add(candidate, keys[i]);
}
}
i++;
}
while (i < keys.Length)
{
if (candidateClasses.ContainsKey(keys[i]))
{
this.InnerList.Add(keys[i]);
}
i++;
}
rootKey.Close();
}
public FileClasseNames(FileClassKeyHive baseKey)
{
m_baseKey = baseKey;
Refresh();
}
}
#endregion
#region FileClass
/// <summary>
/// Provides an object which manages a FileClass in the registry
/// and each of the files associated with it
/// </summary>
public class FileClass : IComparable
{
private string m_className = "";
private string m_defaultIcon = "";
private bool m_isDirty = false;
private FileClassKeyHive m_baseKey;
private FileClassAssociations m_assoc;
private FileClassExtensions m_extensions;
/// <summary>
/// Compares this object to another instance of the same type
/// </summary>
/// <param name="obj">FileClass to compare to</param>
/// <returns>-1 if the item is less than this one, 0 if it is equal, 1 if
the item is greater</returns>
public virtual System.Int32 CompareTo ( System.Object obj )
{
return m_className.CompareTo( ((FileClass)obj).ClassName );
}
/// <summary>
/// The base key in the registry we're working in
/// </summary>
public FileClassKeyHive BaseKey
{
get
{
return m_baseKey;
}
}
/// <summary>
/// Collection of verbs associated with this class
/// in the "shell" subsection
/// </summary>
public FileClassAssociations Associations
{
get
{
return this.m_assoc;
}
}
public FileClassExtensions Extensions
{
get
{
return this.m_extensions;
}
}
/// <summary>
/// Gets the name of this file class
/// </summary>
public string ClassName
{
get
{
return this.m_className;
}
}
public string DefaultIcon
{
get
{
return this.m_defaultIcon;
}
set
{
this.m_defaultIcon = value;
this.m_isDirty = true;
}
}
/// <summary>
/// Returns whether this object is dirty (requires saving) or not.
/// </summary>
public bool IsDirty
{
get
{
return this.m_isDirty;
}
}
/// <summary>
/// Resets the object and reads all associated extensions
/// and verbs from the registry
/// </summary>
public void Refresh()
{
string compClassName = m_className.ToUpper();
RegistryKey rootKey = FileClassUtility.GetRootKey(m_baseKey);
RegistryKey classKey = rootKey.OpenSubKey(this.m_className);
if (classKey != null)
{
// existing item
RegistryKey defaultIconKey = classKey.OpenSubKey("DefaultIcon");
if (defaultIconKey != null)
{
this.m_defaultIcon = (string)defaultIconKey.GetValue("", "");
}
else
{
this.m_defaultIcon = "";
}
this.m_isDirty = false;
}
else
{
// new item
this.m_isDirty = true;
}
this.m_assoc = new FileClassAssociations(this);
this.m_extensions = new FileClassExtensions(this);
}
/// <summary>
/// saves this file class object, and all associated objects
/// </summary>
public void Save()
{
RegistryKey rootKey = FileClassUtility.GetRootKey(m_baseKey);
// Class Key:
RegistryKey classKey = rootKey.CreateSubKey(this.m_className);
if (classKey == null)
{
throw new InvalidOperationException(
String.Format("Could not create or open class key {0}",
this.m_className));
}
// associated icon:
if (this.m_defaultIcon.Length > 0)
{
RegistryKey defaultIconKey = classKey.CreateSubKey("DefaultIcon");
if (defaultIconKey == null)
{
throw new InvalidOperationException(
String.Format("Could not create or open DefaultIcon key for
class key {0}", this.m_className));
}
defaultIconKey.SetValue("", this.m_defaultIcon);
defaultIconKey.Close();
}
classKey.Close();
// associations:
if (this.m_assoc.IsDirty)
{
this.m_assoc.Save();
}
// file extensions:
if (this.m_extensions.IsDirty)
{
this.m_extensions.Save();
}
}
/// <summary>
/// Creates a new instance of the object for the specified
/// registry hive
/// </summary>
/// <param name="baseKey">Registry Hive</param>
/// <param name="className">Class Name to create for</param>
public FileClass(
FileClassKeyHive baseKey,
string className
)
{
if ((className.ToUpper().Equals("CLSID")) ||
(className.ToUpper().Equals("TYPELIB")))
{
throw new InvalidOperationException("Class name may not be CLSID or
TypeLib");
}
this.m_baseKey = baseKey;
this.m_className = className;
Refresh();
}
}
#endregion
#region FileClassExtensions
public class FileClassExtensions : CollectionBase
{
private FileClass m_owner = null;
private bool m_isDirty = false;
private Stack m_removeList = new Stack();
/// <summary>
/// Gets/sets whether this collection is dirty (requires saving) or not
/// </summary>
public bool IsDirty
{
get
{
return m_isDirty;
}
}
/// <summary>
/// Finds the index of the specified extension in the collection
/// </summary>
/// <param name="extension">Extension to search for, e.g. .cs</param>
/// <returns>Index of the FileExtension item if found, -1
otherwise</returns>
public int IndexOf(string extension)
{
FileExtension junk = new FileExtension(this.m_owner, extension);
return this.InnerList.IndexOf(junk);
}
/// <summary>
/// Gets the file extension with the specified index
/// </summary>
public FileExtension this[int index]
{
get
{
return (FileExtension)this.InnerList[index];
}
}
/// <summary>
/// Removes the extension with the specified index
/// </summary>
/// <param name="index">Index of item to remove</param>
public void Remove(int index)
{
FileExtension fe = (FileExtension)this.InnerList[index];
m_removeList.Push(fe);
this.InnerList.RemoveAt(index);
this.m_isDirty = true;
}
/// <summary>
/// Add a new file extension to the files associated with this class
/// </summary>
/// <param name="fe">File extension to add</param>
public void Add(FileExtension fe)
{
this.InnerList.Add(fe);
this.m_isDirty = true;
}
/// <summary>
/// Refreshes the list of extensions from the registry
/// </summary>
public void Refresh()
{
this.InnerList.Clear();
string compClassName = this.m_owner.ClassName.ToUpper();
RegistryKey rootKey = FileClassUtility.GetRootKey(m_owner.BaseKey);
foreach (string key in rootKey.GetSubKeyNames())
{
if (key.StartsWith("."))
{
RegistryKey assocKey = rootKey.OpenSubKey(key);
string className = (string)assocKey.GetValue("", "");
if (className.Length > 0)
{
if (className.ToUpper().Equals(compClassName))
{
FileExtension assoc = new FileExtension(this.m_owner, key);
this.InnerList.Add(assoc);
}
}
}
}
this.m_isDirty = false;
}
public void Save()
{
RegistryKey rootKey = FileClassUtility.GetRootKey(m_owner.BaseKey);
// remove any existing items:
while (m_removeList.Count > 0)
{
FileExtension fe = (FileExtension)m_removeList.Pop();
if ((fe.Extension.Trim().Length > 0) &&
(fe.Extension.StartsWith(".")))
{
rootKey.DeleteSubKeyTree(fe.Extension);
}
}
foreach (FileExtension fe in this.InnerList)
{
RegistryKey extKey = rootKey.CreateSubKey(fe.Extension);
if (extKey == null)
{
throw new InvalidOperationException(
String.Format("Could not open or create extension key {0}",
fe.Extension));
}
extKey.SetValue("", m_owner.ClassName);
extKey.Close();
}
rootKey.Close();
}
/// <summary>
/// Constructs a new file extensions list for the
/// specified file class.
/// </summary>
/// <param name="fileClass">Class to construct for</param>
public FileClassExtensions(FileClass fileClass)
{
this.m_owner = fileClass;
if (!m_owner.IsDirty) // not a new item
{
Refresh();
}
else
{
this.m_isDirty = true; // new item
}
}
internal FileClassExtensions(
FileClass fileClass,
string[] extensions
)
{
this.m_owner = fileClass;
foreach (string ext in extensions)
{
FileExtension extC = new FileExtension(fileClass, ext);
this.InnerList.Add(extC);
}
}
}
#endregion
#region FileExtension
/// <summary>
/// A Class which stores details of an file extension
/// </summary>
public class FileExtension : IComparable
{
private string m_extension = "";
private string m_displayName = "";
private FileClass m_owner = null;
private bool m_isDirty = false;
public virtual System.Int32 CompareTo ( System.Object obj )
{
return m_extension.CompareTo( ((FileExtension)obj).Extension);
}
/// <summary>
/// Gets/sets the display name for this file extension
/// </summary>
public string DisplayName
{
get
{
return this.m_displayName;
}
set
{
this.m_displayName = value;
this.m_isDirty = true;
}
}
public bool IsDirty
{
get
{
return this.m_isDirty;
}
}
/// <summary>
/// Gets the extension for this file extension
/// </summary>
public string Extension
{
get
{
return m_extension;
}
}
public void Refresh()
{
RegistryKey rootKey = FileClassUtility.GetRootKey(m_owner.BaseKey);
RegistryKey extensionKey = rootKey.OpenSubKey(this.m_extension);
if (extensionKey != null)
{
this.m_isDirty = false;
this.m_displayName = (string)extensionKey.GetValue("", "");
}
else
{
this.m_isDirty = true;
}
}
/// <summary>
/// Constructs a new instance of the file extension class
/// for the specified FileExtensions collection
/// </summary>
/// <param name="fileClass">Owning FileClass</param>
/// <param name="extension">Extension</param>
public FileExtension(
FileClass fileClass,
string extension
)
{
if (!extension.StartsWith("."))
{
throw new InvalidOperationException("File Extensions must start
with '.'");
}
this.m_owner = fileClass;
this.m_extension = extension;
// always refresh, we may exist independently of the fileclass
Refresh();
}
}
#endregion
#region FileClassAssociations
/// <summary>
/// Summary description for ClassAssociations.
/// </summary>
public class FileClassAssociations : CollectionBase
{
private FileClassKeyHive m_baseKey = FileClassKeyHive.LocalMachine;
private Stack m_removeList = new Stack();
private FileClass m_owner = null;
private bool m_isDirty = false;
/// <summary>
/// Gets/sets whether this collection is dirty (requires saving) or not
/// </summary>
public bool IsDirty
{
get
{
return m_isDirty;
}
}
/// <summary>
/// Gets/sets the ClassAssociation at the specified index
/// </summary>
public FileClassAssociation this[int index]
{
get
{
return (FileClassAssociation)this.InnerList[index];
}
set
{
this.InnerList[index] = value;
m_isDirty = true;
}
}
/// <summary>
/// Adds a new FileClassAssociation. Throws InvalidOperation
/// if the item already exists
/// </summary>
/// <param name="ca">FileClassAssociation to add</param>
/// <exception cref="InvalidOperationException">If the item already
exists</exception>
public void Add(FileClassAssociation ca)
{
foreach (FileClassAssociation a in this.InnerList)
{
if (ca.CompareTo(a) == 0)
{
throw new InvalidOperationException(
String.Format("The verb {0} is already a member of this
collection",
ca.Verb)
);
}
}
this.InnerList.Add(ca);
m_isDirty = true;
}
/// <summary>
/// Returns the index of the class association with the specified verb, or
/// -1 if it's not there
/// </summary>
/// <param name="verb">Verb to look for</param>
/// <returns>Index of item with the specified verb, or -1 if it's not
there</returns>
public int IndexOf(string verb)
{
int index = -1;
for (int i = 0; i < this.InnerList.Count; i++)
{
if (verb.Equals(((FileClassAssociation)this.InnerList[i]).Verb))
{
index = i;
break;
}
}
return index;
}
/// <summary>
/// Removes an existing FileClassAssociation
/// </summary>
/// <param name="index">Index of association to remove</param>
public void Remove(int index)
{
FileClassAssociation ca = this[index];
this.m_removeList.Push(ca);
this.InnerList.Remove(index);
m_isDirty = true;
}
/// <summary>
/// Refreshes the object's data from the registry
/// </summary>
public void Refresh()
{
this.InnerList.Clear();
RegistryKey rootKey = FileClassUtility.GetRootKey(m_baseKey);
RegistryKey items = rootKey.OpenSubKey(m_owner.ClassName);
RegistryKey shell = items.OpenSubKey("shell");
if (shell != null)
{
foreach (string verb in shell.GetSubKeyNames())
{
RegistryKey verbKey = shell.OpenSubKey(verb);
string menuText = (string)verbKey.GetValue("", "");
RegistryKey commandKey = verbKey.OpenSubKey("command");
string command = "";
if (commandKey != null)
{
command = (string)commandKey.GetValue("", "");
}
FileClassAssociation ca = new FileClassAssociation(
this, verb, menuText, command);
this.InnerList.Add(ca);
}
}
m_isDirty = false;
}
/// <summary>
/// Saves the specified FileClassAssociations to the registry
/// </summary>
/// <exception cref="InvalidOperationException">If creating any registry
keys fails</exception>
public void Save()
{
RegistryKey rootKey = FileClassUtility.GetRootKey(m_baseKey);
RegistryKey items = rootKey.OpenSubKey(m_owner.ClassName);
RegistryKey shell = items.OpenSubKey("shell", true);
if ((shell == null) && (this.InnerList.Count > 0))
{
// need to create the key
shell = rootKey.CreateSubKey("shell");
if (shell == null)
{
throw new InvalidOperationException("Unable to create shell
key");
}
}
while (m_removeList.Count > 0)
{
FileClassAssociation ca = (FileClassAssociation)m_removeList.Pop();
shell.DeleteSubKeyTree(ca.Verb);
}
foreach (FileClassAssociation ca in this.InnerList)
{
if (ca.IsDirty)
{
RegistryKey verbKey = shell.CreateSubKey(ca.Verb);
if (verbKey == null)
{
throw new InvalidOperationException(
String.Format("Unable to create verb key {0}", ca.Verb));
}
if (ca.MenuText.Trim().Length > 0)
{
verbKey.SetValue("", ca.MenuText);
}
RegistryKey commandKey = verbKey.CreateSubKey("command");
if (commandKey == null)
{
throw new InvalidOperationException(
String.Format("Unable to create command key for {0}",
ca.Command));
}
commandKey.SetValue("", ca.Command);
commandKey.Close();
verbKey.Close();
}
}
shell.Close();
items.Close();
rootKey.Close();
m_isDirty = false;
}
/// <summary>
/// Returns the registry key containing this ClassAssociation's
/// data
/// </summary>
/// <returns>Registry Key containing this ClassAssociation's
data</returns>
public Microsoft.Win32.RegistryKey RegistryKey()
{
RegistryKey key = FileClassUtility.GetRootKey(m_baseKey);
return key.OpenSubKey(m_owner.ClassName);
}
/// <summary>
/// Constructs a new instance of the class for the specified
/// file class
/// </summary>
/// <param name="fileClass">The class to read or modify verbs in</param>
public FileClassAssociations(FileClass fileClass)
{
m_owner = fileClass;
m_baseKey = m_owner.BaseKey;
// always refresh, we might exist regardless whether fileClass is new
Refresh();
}
}
#endregion
#region FileClassAssociation
/// <summary>
/// Returns details of a command association
/// </summary>
public class FileClassAssociation : IComparable
{
private string m_verb = "";
private string m_menuText = "";
private string m_command = "";
private bool m_dirty = true;
public virtual System.Int32 CompareTo ( System.Object obj )
{
return m_verb.CompareTo(((FileClassAssociation)obj).Verb);
}
public virtual System.Int32 CompareTo (FileClassAssociation ca)
{
return m_verb.CompareTo(ca.Verb);
}
/// <summary>
/// Gets/sets the verb (the keyname in the registry) for this command.
/// </summary>
public string Verb
{
get
{
return this.m_verb;
}
set
{
this.m_verb = value;
this.m_dirty = true;
}
}
/// <summary>
/// Gets/sets the menu text that will be displayed in the context menu
/// for this command
/// </summary>
public string MenuText
{
get
{
return this.m_menuText;
}
set
{
this.m_menuText = value;
this.m_dirty = true;
}
}
/// <summary>
/// Gets/sets the command to execute
/// </summary>
public string Command
{
get
{
return this.m_command;
}
set
{
this.m_command = value;
this.m_dirty = true;
}
}
/// <summary>
/// Gets/sets whether this item needs to be saved or not
/// </summary>
public bool IsDirty
{
get
{
return this.m_dirty;
}
}
/// <summary>
/// Creates a new class association
/// </summary>
/// <param name="verb">The verb (keyname in the registry) for this
command.</param>
/// <param name="menuText">The context menu text to display</param>
/// <param name="command">The command to execute</param>
public FileClassAssociation(string verb, string menuText, string command)
{
this.m_verb = verb;
this.m_menuText = menuText;
this.m_command = command;
this.m_dirty = true;
}
/// <summary>
/// Creates a existing class association associated with the
/// ClassAssociations Refresh method. Internal method.
/// </summary>
/// <param name="verb">The verb (keyname in the registry) for this
command.</param>
/// <param name="menuText">The context menu text to display</param>
/// <param name="command">The command to execute</param>
internal FileClassAssociation(FileClassAssociations owner, string verb,
string menuText, string command)
{
this.m_dirty = false;
this.m_verb = verb;
this.m_menuText = menuText;
this.m_command = command;
}
}
#endregion
}
|
|