using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using Microsoft.Win32; using System.Windows.Forms; namespace CascadingFiletypeDemultiplexer { public static class Constants { public const string EXTENSION = ".cfd"; public const string PROG_ID = "CascadingFiletypeDemultiplexer"; public static string[] DEFAULT_VERBS ={ "open", "opennew", "edit", "print"}; } class Verb { public string Name; public string Command; public Verb(string name, string command) { Name = name; Command = command; } } class FileType { public string Extension; public string ProgId; public FileType(string extension) { Extension = extension; RegistryKey key = Registry.ClassesRoot.OpenSubKey(extension); if (key != null) { ProgId = (string)key.GetValue("");//default value } } public Hashtable Verbs { get { Hashtable verbs = new Hashtable(); RegistryKey key = Registry.ClassesRoot.OpenSubKey(string.Format("{0}\\shell", ProgId)); if (key != null) { foreach (string verbName in key.GetSubKeyNames()) { RegistryKey subKey = key.OpenSubKey(string.Format("{0}\\command", verbName)); if (subKey != null) { //strip out any command line arguments apart from %1 string command=Regex.Replace(((string)subKey.GetValue("")),"(%2|%3|%4|%5|%6|%7|%8|%9|%\\*)",""); Verb verb = new Verb(verbName, command); verbs.Add(verbName.ToUpper(), verb); } } } return (verbs); } } public void Trace() { Trace(System.Console.Out); } public void Trace(TextWriter writer) { writer.Write("{0} : {1}\n", Extension, ProgId); foreach (Verb verb in this.Verbs.Values) { writer.Write("\t[{0}] : {1}\n", verb.Name, verb.Command); } } } class Program { static IList ExtractCascadingFileTypes(string fileName) { ArrayList FileTypes = new ArrayList(); MatchCollection matches=Regex.Matches(fileName, "(\\.[^.]*)"); //skip over the the last match (which should be .CFD) for (int i=0;i0) { verbs+=", "; } verbs += "["+Constants.DEFAULT_VERBS[i]+"]"; } string usage = @" Parses a 'Cascading FileType' filename from right to left, looking for a registered file handler for each file extension. The first file handler that implements the specified DDE verb is then executed. USAGE: CFD /I associates " + Constants.EXTENSION + @" files with the Cascading FileType Demultiplexer registered verbs are "+verbs+@" CFD /U removes the file associations for file extension +" + Constants.EXTENSION + @" CFD filename verb finds and executes the best matching application to handle the specified DDE verb CFD filename finds and executes the best matching application to handle the default DDE verb ('open') CFD /T filename verb displays a trace showing what file handlers are found for specified filename, what verbs they implement, and the best match found. The best match application is NOT executed. "; System.Console.WriteLine(usage); } static void Execute(string commandLine) { Match m; if (commandLine[0]=='"') { m=Regex.Match(commandLine, "\"([^\"]*)\"\\s*(.*)"); } else { m = Regex.Match(commandLine, "(\\S*)\\s*(.*)"); } System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = m.Groups[1].Value; proc.StartInfo.Arguments = m.Groups[2].Value; proc.Start(); } [STAThread] static void Main(string[] args) { if (args.Length ==0 ) { Usage(); } else if (args[0].ToLower()=="/i") { Install(); System.Console.WriteLine("\nDDE verb handlers installed for file extension {0}", Constants.EXTENSION); } else if (args[0].ToLower() == "/u") { Uninstall(); System.Console.WriteLine("\nDDE verb handlers uninstalled for file extension {0}", Constants.EXTENSION); } else { string fileName = args[0]; string verbName = "open"; //default command if (args.Length >= 2) { verbName = args[1]; } if (args[0].ToLower()=="/t") { fileName = args[1]; foreach (FileType fileType in ExtractCascadingFileTypes(fileName)) { fileType.Trace(); } if (args.Length > 2) { verbName = args[2]; Verb verb = GetClosestMatchedVerb(fileName, verbName); if (verb != null) { string commandLine = verb.Command.Replace("%1", fileName); System.Console.WriteLine("\n\nBest fit for \"{0}\" [{1}]:", fileName, verbName); System.Console.WriteLine(commandLine); } } } else { Verb verb = GetClosestMatchedVerb(fileName, verbName); if (verb == null) { MessageBox.Show(string.Format("no registered handler found for verb [{0}] for file \"{1}\"", verbName, fileName)); } else { string commandLine = verb.Command.Replace("%1", fileName); Execute(commandLine); } } } } } }