- Understanding Shell Extension Handlers
- Creating Our Shell Extension
- Registering the Extension
- Where Are We?
Before this extension will actually work, we need to make some changes to the registry to tell the shell about ourselves.
To accomplish this, I suggest using the Register and Un-register methods:
[System.Runtime.InteropServices.ComRegisterFunctionAttribute()] static void RegisterServer(String zRegKey) { try { RegistryKey root; RegistryKey rk; root = Registry.CurrentUser; rk = root.OpenSubKey("Software\\Microsoft\\Windows\\" + "CurrentVersion\\Explorer", true); rk.SetValue("DesktopProcess", 1); rk.Close(); // For Winnt set me as an approved shellex root = Registry.LocalMachine; rk = root.OpenSubKey("Software\\Microsoft\\Windows\\" + "CurrentVersion\\Shell Extensions\\" + "Approved", true); rk.SetValue(clsid, "CleanVS Shell Extension"); rk.Close(); root = Registry.ClassesRoot; rk = root.CreateSubKey("Folder\\shellex\\" + "ContextMenuHandlers\\CleanVS"); rk.SetValue("", clsid); rk.Close(); } catch(Exception e) { System.Console.Error.WriteLine(e.ToString()); } } [System.Runtime.InteropServices.ComUnregisterFunctionAttribute()] static void UnregisterServer(String zRegKey) { try { RegistryKey root; RegistryKey rk; // Remove ShellExtenstions registration root = Registry.LocalMachine; rk = root.OpenSubKey("Software\\Microsoft\\Windows\\" + "CurrentVersion\\Shell Extensions\\" + "Approved", true); rk.DeleteValue(clsid); rk.Close(); // Delete ShellCmd regkey root = Registry.ClassesRoot; root.DeleteSubKey("Folder\\shellex\\ContextMenuHandlers\\" + "CleanVS"); } catch(Exception e) { System.Console.Error.WriteLine(e.ToString()); } }
These methods both have attributes added to them to tell the COM Interop layer that they are the functional methods to use when registering and un-registering this assembly with COM. If we were to register our assembly with regsvr32.exe or other standard registration system, they would call these methods when registering and un-registering. The bulk of the work here is adding or removing registry entries.
NOTE
The "Creating Shell Extension Handlers" article on the MSDN site explains in detail which registry settings are required.
Our project is an executable. We should support registering and un-registering from the command line. With the registration functionality added, our Main method will look like this:
public static int Main(string[] args) { bool unregister = false; try { Console.WriteLine("CleanVS.exe - Windows explorer " + "namespace extension for cleaning up " + "of temporary files from Visual Studio " + "Project Directories\n" + "Copyright (C) Shawn Wildermuth 2003. " + "All rights reserved."); if(args.Length == 1) { string a = args[0].Replace('-', '/').ToLower(CultureInfo.InvariantCulture); if (a == "/?" || args[0] == "/help") { Usage(); return 0; } else if (a == "/u") { unregister = true; } else { Console.WriteLine("Invalid option: " + args[0]); Usage(); return 1; } } // (Un)Register if necessary Assembly asm = Assembly.GetExecutingAssembly(); RegistrationServices reg = new RegistrationServices(); if(unregister) { reg.UnregisterAssembly(asm); CleanVS.UnregisterServer(""); } else { reg.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase); CleanVS.RegisterServer(""); } return 0; } catch(Exception e) { Console.WriteLine("An exception was thrown : " + e); return 1; } }
The Main method simply determines whether the user wants to register and un-register and then does the work to do the registration. The RegisterServer and UnregisterServer calls are only part of the work. The assembly needs to be registered as a COM server as well. To do this, we can use the RegistrationServices object to do this standard registration. In this way, the assembly will register itself when called directly and un-register itself if called with the /u flag.