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…“)
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:
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!