Retrieving fully qualified assembly, module and type names

How often do you need to retrieve a fully qualified assembly or type name? If you are using a lot dependency injection, you need it often. Too often, actually.

There are multiple ways how to do it – using Reflector ILSpy to find out the fully qualified assembly name, and then to prepend the type name, or moving the DLL temporarily to GAC to read it from there, or, or…

Well, I got a kind of fed up. I have built a command line tool, with only one parameter: path to the DLL file. Result: fully qualified assembly name, module and type names will be displayed in the comand line window, as well as copied to the clipboard.

When the tool is run without any parameters, it installs itself as a shell extension in Windows Explorer, so that you can just right click the DLL file, and run the tool.

My dear friend Anreas Erben just gave me a hard time about the “autonistall” feature – and with right. So, if you run the tool without parameters it will not install in shell. Nothing will happen now if you run the tool without parameters (ok, a nice message will be displayed).

You can still install it in Windows Explorer shell, but you need to run it with /INSTALLSHELL parameters

getassemblyname /installshell

The same way, you can remove it from the shell:

getassemblyname /uninstallshell

Saves the the time, saves the nerves (“Did I get my fully qualified name and type name right? @#$!%$ No, I didn’t…“)

shell-extension

The result looks like:

[XML] Loaded Assembly:
PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf

Modules:
Module: PlanB.Core.dll
Fully Qualified Name: C:ProDevPlanBShareDoveConferenceOrganizationUILayerConsolebinDebugPlanB.Core.dll

Types in module:
PlanB.Core.Logging.Configuration, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.LoggingImplementation, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.LoggingSettings, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.LoggerParametersCollection, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.LoggingParameter, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Configuration.ConfigurationInformation, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.iLogger, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.EventServerity, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.InnerExceptionsLevel, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
PlanB.Core.Logging.MockLogger, PlanB.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79ea5ba3438af0bf
[/XML]

And the code is here:

–>  Download code

using System;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Text;

namespace PlanB.Tools.QualifiedNamesGetter
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            //check arguments
            if (args == null || args.Length == 0) return;

            //
            //install into windows explorer shell
            if (args[0].Trim().ToUpper().StartsWith("/INSTALLSHELL"))
            {
                registerShellExtension("dllfile", "ReadFullyQualifiedAssemblyName", "Read fully qualified assembly name, modules and types", Application.ExecutablePath);
                return;
            }

            //
            //uninstall from windows explorer shell
            if (args[0].Trim().ToUpper().StartsWith("/UNINSTALLSHELL"))
            {
                unregisterShellExtension("dllfile", "ReadFullyQualifiedAssemblyName");
                return;
            }

            string assemblyPath = args[0];

            StringBuilder output = new StringBuilder();

            //
            //Load assembly from path
            Assembly loadedAssembly = null;
            try
            {
                loadedAssembly = Assembly.LoadFile(assemblyPath);
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Error by loading assembly {0}. n Error Message: {1}", assemblyPath, ex.Message));
            }

            //
            //if assemblu successfully loaded...
            if (loadedAssembly != null)
            {
                try
                {
                    output.AppendLine("Loaded Assembly:");
                    output.AppendLine(loadedAssembly.FullName);
                    output.AppendLine("n");

                    //
                    //..get all modules from the assembly...
                    Module[] modules = loadedAssembly.GetModules();
                    if (modules.Length > 0)
                    {
                        output.AppendLine("Modules:");

                        foreach (Module module in modules)
                        {
                            output.AppendFormat("Module: {0}nFully Qualified Name: {1}nn", module.Name, module.FullyQualifiedName);
                            Type[] types = module.GetTypes();

                            //
                            //...and then all types from the module
                            if (types.Length > 0)
                            {
                                output.AppendLine("Types in module:");
                                foreach (Type type in types)
                                {
                                    string typeName = type.AssemblyQualifiedName;
                                    output.AppendLine(typeName);
                                }
                            }
                        }

                        output.AppendLine("-----------------------n");
                    }
                }
                catch (ReflectionTypeLoadException reflectionEx)
                {
                    output.AppendLine("Reflection Exception:" + reflectionEx.Message);
                    output.AppendLine("Loader Exceptions:");
                    foreach (Exception ex in reflectionEx.LoaderExceptions)
                    {
                        output.AppendLine(ex.Message);
                    }
                }
                catch (Exception ex)
                {
                    output.AppendLine("Generic Exception:" + ex.Message);
                    output.AppendLine("StackTraces:");
                    output.AppendLine(ex.StackTrace);
                }
            }

            //paste it to the console window
            Console.WriteLine(output.ToString());

            //and copy it to the clipboard, as well
            Clipboard.SetDataObject(output.ToString(), true);
        }

        /// <summary>
        /// Registers a Shell Extension for a given file type, sets the key and value, and sets it's command to a specified assembly
        /// </summary>
        /// <param name="fileType">File type for which we need to create a shell extension</param>
        /// <param name="extensionKey">Key we want to give to our shell extension</param>
        /// <param name="extensionValue">Text we want to display ny the shell extension</param>
        /// <param name="commandAssembly">Assembly we want to execute when clicked on the shell extension</param>
        private static void registerShellExtension(string fileType, string extensionKey, string extensionValue, string commandAssembly)
        {
            //
            //Open a registy key HKEY_CURRENT_USERSoftwareClasses  
            //this is where we are going to save the shell extension for the file type
            using (var classesRegistyKey = Registry.CurrentUser.OpenSubKey("Software\Classes", true))
            {
                if (classesRegistyKey == null) return;

                //
                //create subkey for DLL files
                using (var fileTypeKey = classesRegistyKey.CreateSubKey(fileType))
                {
                    if (fileTypeKey == null) return;

                    //
                    //add a shell extension for DLL files
                    using (var shellKey = fileTypeKey.CreateSubKey("shell"))
                    {
                        if (shellKey == null) return;

                        //
                        //create key
                        using (var shellExtensionKey = shellKey.CreateSubKey(extensionKey))
                        {
                            if (shellExtensionKey == null) return;

                            //and create a value for the key
                            shellExtensionKey.SetValue(string.Empty, extensionValue);

                            //
                            //and then create a command to be executed when extension clicked - 
                            //set it to the given command  assembly
                            using (var commandKey = shellExtensionKey.CreateSubKey("command"))
                            {
                                if (commandKey == null) return;
                                commandKey.SetValue("", string.Concat(""", commandAssembly, "" "%1""));
                            }
                        }
                    }
                }
            }
            return;
        }

        /// <summary>
        /// Unregisters a Shell Extension for a given file type and a given key
        /// </summary>
        /// <param name="fileType">File type for which we need to create a shell extension</param>
        /// <param name="extensionKey">Key we want to give to our shell extension</param>
        private static void unregisterShellExtension(string fileType, string extensionKey)
        {
            //
            //Open a registy key HKEY_CURRENT_USERSoftwareClasses  
            //this is where we are going to save the shell extension for the file type
            using (var classesRegistyKey = Registry.CurrentUser.OpenSubKey("Software\Classes", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl))
            {
                if (classesRegistyKey == null) return;

                //
                //navigate the nodes down to the key
                var fileTypeKey = classesRegistyKey.OpenSubKey(fileType, RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);
                if (fileTypeKey == null) return;


                var shellKey = fileTypeKey.OpenSubKey("shell", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl);
                if (shellKey == null) return;

                //
                //delete the key
                var commandKey = shellKey.OpenSubKey(extensionKey, RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.Delete);
                shellKey.DeleteSubKeyTree(extensionKey);

            }
            return;
        }
    }
}

Enjoy!