using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Microsoft.Win32; namespace RobvanderWoude { internal class ListVerbs { static readonly string progver = "1.01"; static int rc = 0; static int Main( string[] args ) { rc = 0; bool verbose = false; if ( args.Length == 0 || args.Length > 2 || args.Contains( "/?" ) ) { return ShowHelp( ); } string ext = args[0]; if ( args.Length == 2 ) { if ( args[1].ToUpper( ).StartsWith( "/V" ) ) { verbose = true; } else { return ShowHelp( "Invalid command line argument \"{0}\"", args[1] ); } } if ( ext[0] != '.' ) { verbose = true; } if ( verbose ) { GetVerbsVerbose( args[0] ); } else { GetVerbs( args[0] ); } return rc; } static void GetVerbs( string ext ) { ProcessStartInfo startinfo = new ProcessStartInfo( string.Format( "fakefilename{0}", ext ) ); foreach ( string verb in startinfo.Verbs ) { if ( rc == 0 ) { Console.WriteLine( "Verbs for {0}", ext ); Console.WriteLine( "=========={0}", new String( '=', ext.Length ) ); } rc++; Console.WriteLine( verb ); } } static void GetVerbsVerbose( string ext ) { string doctype = string.Empty; string docname = string.Empty; string regkeypath = string.Format( "Software\\Classes\\{0}", ext ); if ( ext[0] == '.' ) { // get document type for specified file extension Console.WriteLine( "Extension = {0}", ext ); using ( RegistryKey regkey = Registry.LocalMachine.OpenSubKey( regkeypath ) ) { if ( regkey != null ) { object doctypevalue = regkey.GetValue( "" ); if ( doctypevalue != null ) { doctype = doctypevalue.ToString( ); } } } } else { // assume document type is specified on the command line doctype = ext; } if ( !string.IsNullOrWhiteSpace( doctype ) ) { regkeypath = string.Format( "Software\\Classes\\{0}\\CurVer", doctype ); using ( RegistryKey regkey = Registry.LocalMachine.OpenSubKey( regkeypath ) ) { if ( regkey != null ) { object doctypevalue = regkey.GetValue( "" ); if ( doctypevalue != null ) { doctype = doctypevalue.ToString( ); } } } } if ( !string.IsNullOrWhiteSpace( doctype ) ) { // get proper casing of docyument type, as used in the registry string[] classes = Registry.LocalMachine.OpenSubKey( "Software\\Classes" ).GetSubKeyNames( ); foreach ( string classname in classes ) { if ( classname.ToLower( ) == doctype.ToLower( ) ) { doctype = classname; } } Registry.LocalMachine.Close( ); // get friendly name for document type regkeypath = string.Format( "Software\\Classes\\{0}", doctype ); using ( RegistryKey regkey = Registry.LocalMachine.OpenSubKey( regkeypath ) ) { if ( regkey != null ) { docname = regkey.GetValue( "" ).ToString( ); } } } if ( !string.IsNullOrWhiteSpace( doctype ) ) { Console.Write( "File Type = {0}", doctype ); if ( docname != null ) { Console.Write( " ({0})", docname ); } Console.WriteLine( ); // get all available verbs for this file type regkeypath = string.Format( "Software\\Classes\\{0}\\shell", doctype ); using ( RegistryKey regkey = Registry.LocalMachine.OpenSubKey( regkeypath ) ) { if ( regkey != null ) { int columnwidth = 0; Console.WriteLine( "Verbs:" ); // all verbs have a separate subkey foreach ( string verb in regkey.GetSubKeyNames( ) ) { columnwidth = Math.Max( columnwidth, verb.Length ); } foreach ( string verb in regkey.GetSubKeyNames( ) ) { columnwidth = Math.Max( columnwidth, verb.Length ); rc++; // get the command for this verb using ( RegistryKey regkeycommand = regkey.OpenSubKey( string.Format( "{0}\\command", verb ) ) ) { if ( regkeycommand != null ) { string command = regkeycommand.GetValue( "" ).ToString( ); Console.WriteLine( "\t{0,-" + columnwidth + "} {1}", verb.ToLower( ), command ); } } } } } } } static int ShowHelp( params string[] errmsg ) { #region Help Text /* ListVerbs.exe, Version 1.00 List all verbs for the specified file extension Usage: ListVerbs filetype [ /V ] Where: filetype is the file type to list the available verbs for /V Verbose output, i.e. not just the verbs, but the associated commands as well Notes: filetype can be specified as file extension including dot, e.g. ".odt", or as document type name associated with a file extension, e.g. "LibreOffice.WriterDocument"; in the latter case, output will be verbose whether /V switch is used or not. Verbose mode may sometimes find more verbs than normal mode. Return code ("errorlevel") equals the number of verbs found, or -1 in case of (command line) errors. Written by Rob van der Woude https://www.robvanderwoude.com */ #endregion Help Text #region Error Message if ( errmsg.Length > 0 ) { List errargs = new List( errmsg ); errargs.RemoveAt( 0 ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write( "ERROR:\t" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) ); Console.ResetColor( ); } #endregion Error Message #region Display Help Text Console.Error.WriteLine( ); Console.Error.WriteLine( "ListVerbs.exe, Version {0}", progver ); Console.Error.WriteLine( "List all verbs for the specified file extension" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "ListVerbs filetype [ /V ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "filetype" ); Console.ResetColor( ); Console.Error.WriteLine( " is the file type to list the available verbs for" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /V V" ); Console.ResetColor( ); Console.Error.WriteLine( "erbose output, i.e. not just the verbs, but the" ); Console.Error.WriteLine( " associated commands as well" ); Console.Error.WriteLine( ); Console.Error.Write( "Notes: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "filetype" ); Console.ResetColor( ); Console.Error.WriteLine( " can be specified as file extension including dot," ); Console.Error.WriteLine( " e.g. \".odt\", or as document type name associated with a file" ); Console.Error.WriteLine( " extension, e.g. \"LibreOffice.WriterDocument\"; in the latter" ); Console.Error.Write( " case, output will be verbose whether " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "/V" ); Console.ResetColor( ); Console.Error.WriteLine( " switch is used or not." ); Console.Error.WriteLine( " Verbose mode may sometimes find more verbs than normal mode." ); Console.Error.WriteLine( " Return code (\"errorlevel\") equals the number of verbs found," ); Console.Error.WriteLine( " or -1 in case of (command line) errors." ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "https://www.robvanderwoude.com" ); #endregion Display Help Text return -1; } } }