C# ICopyHook implementation based on CSShellExt*

Nov 3, 2010 at 5:16 PM
Edited Nov 3, 2010 at 5:19 PM

Hi,

Based on your various managed Shell Extension for C# I tried to do a sample for a CopyHook extension. Unfortunately it does not seem to work. regasm.exe etc. all works fine but copying/renaming a folder does not show the MessageBox. Any ideas what's wrong here? Registry entries, wrong interfaces? As soon as this sample is running we could add it to the AIO Code Framework. Thanks Yves

 

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace CopyHookExtension
{
    public enum eCOPYCALLBACK_STATUS : uint
    {
        IDCANCEL = 2,
        IDYES = 6,
        IDNO = 7
    }

    public enum eSHELL_FILE_OPERATIONS : uint
    {
        FO_MOVE = 1,
        FO_COPY = 2,
        FO_DELETE = 3,
        FO_RENAME = 4
    }

    /*
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214FC-0000-0000-C000-000000000046")]
    public interface ICopyHook
    {
        [PreserveSig]
        uint CopyCallback(IntPtr hwnd,
                          uint wFunc,
                          uint wFlags,
                          [MarshalAs(UnmanagedType.LPWStr)] string pszSrcFile,
                          uint dwSrcAttribs,
                          [MarshalAs(UnmanagedType.LPWStr)] string pszDestFile,
                          uint dwDestAttribs);
    }*/


    [ComVisible(false), ComImport, Guid("000214FC-0000-0000-C000-000000000046"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICopyHookW
    {
        [PreserveSig()]
        uint CopyCallback(IntPtr hwnd, uint wFunc, uint wFlags, String pszSrcFile, UInt32 dwSrcAttribs, String pszDestFile, UInt32 dwDestAttribs);
    }

    [StructLayout(LayoutKind.Sequential)]
    public class SHFILEOPSTRUCT
    {
        public int hwnd;

        public int wFunc;

        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;

        [MarshalAs(UnmanagedType.LPWStr)] public string pTo;

        public int fFlags;

        [MarshalAs(UnmanagedType.Bool)] public bool fAnyOperationsAborted;

        public int hNameMappings;

        [MarshalAs(UnmanagedType.LPWStr)] public string lpszProgressTitle;
    }

    [Guid("4B4E267C-5049-48E4-AE66-1400AE327804"), ComVisible(true)]
    public class MyCopyHook : ICopyHookW
    {
        public Object m_object_SynchronizationObject = new Object();

        #region Shell Extension Registration

        [ComRegisterFunction()]
        public static void Register(Type t)
        {
            try
            {
                ShellExtReg.RegisterShellExtCopyHookHandler(t);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); // Log the error
                throw;  // Re-throw the exception
            }
        }

        [ComUnregisterFunction()]
        public static void Unregister(Type t)
        {
            try
            {
                ShellExtReg.UnregisterShellExtContextMenuHandler(t);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); // Log the error
                throw;  // Re-throw the exception
            }
        }

        #endregion

        public uint CopyCallback(IntPtr hwnd, uint wFunc, uint wFlags, string pszSrcFile, uint dwSrcAttribs, string pszDestFile, uint dwDestAttribs)
        {
            System.Windows.Forms.MessageBox.Show("HUIUIUI");
            return (uint)eCOPYCALLBACK_STATUS.IDYES;
        }

        /*
        public uint CopyCallback(IntPtr hwnd,
                                 uint wFunc,
                                 uint wFlags,
                                 [MarshalAs(UnmanagedType.LPWStr)] string pszSrcFile,
                                 uint dwSrcAttribs,
                                 [MarshalAs(UnmanagedType.LPWStr)] string pszDestFile,
                                 uint dwDestAttribs)
        {
            System.Windows.Forms.MessageBox.Show("HUIUIUI");
            return (uint) eCOPYCALLBACK_STATUS.IDYES;
        }*/
    }
}

 

---

 

using System;
using Microsoft.Win32;

namespace CopyHookExtension
{
    internal class ShellExtReg
    {
        /// <summary>
        /// Register the context menu handler.
        /// </summary>
        /// <param name="t">COM class</param>
        /// <param name="fileType">
        /// The file type that the context menu handler is associated with. For 
        /// example, '*' means all file types; '.txt' means all .txt files. The 
        /// parameter must not be NULL or an empty string. 
        /// </param>
        /// <param name="friendlyName">Friendly name of the component</param>
        public static void RegisterShellExtCopyHookHandler(Type t)
        {            
            /*    
            string keyName = string.Format(@"Software\Classes\CLSID\{0}", t.GUID.ToString("B").ToUpper());
                using (RegistryKey key = Registry.CurrentUser.CreateSubKey(keyName))
                {                                        
                    key.SetValue(null, "Test Copy Hook Shell Extension");

                    RegistryKey inProcKey = key.CreateSubKey("InProcServer32");
                    if (inProcKey != null)
                    {
                        inProcKey.SetValue(null, @"C:\temp\CopyHookExtension\CopyHookExtension\bin\Debug\CopyHookExtension.dll");
                        inProcKey.SetValue("ThreadingModel", "Apartment");
                    }
                }
              */                      
            string keyName = string.Format(@"Software\Classes\Directory\shellex\CopyHookHandlers\Test");
            using (RegistryKey key = Registry.CurrentUser.CreateSubKey(keyName))
            {
                // Set the default value of the key.
                if (key != null)
                {
                    key.SetValue(null, string.Format(@"{0}", t.GUID.ToString("B").ToUpper()));
                }
            }
        }

        /// <summary>
        /// Unregister the context menu handler.
        /// </summary>
        /// <param name="t">COM class</param>
        /// <param name="fileType">
        /// The file type that the context menu handler is associated with. For 
        /// example, '*' means all file types; '.txt' means all .txt files. The 
        /// parameter must not be NULL or an empty string. 
        /// </param>
        public static void UnregisterShellExtContextMenuHandler(Type t)
        {
            /*
            string keyName = string.Format(@"Software\Classes\Directory\shellex\CopyHookHandlers\Cyberduck");
            Registry.CurrentUser.DeleteSubKeyTree(keyName);*/

            string keyName = string.Format(@"Directory\shellex\CopyHookHandlers\Test");
            Registry.ClassesRoot.DeleteSubKeyTree(keyName);

            keyName = string.Format(@"Software\Classes\CLSID\{0}", t.GUID.ToString("B").ToUpper());
            Registry.CurrentUser.DeleteSubKeyTree(keyName);
        }
    }
}

 

Nov 6, 2010 at 8:51 AM

Anybody?

Thanks!
Yves

Coordinator
Nov 7, 2010 at 2:08 PM

Hello

Sorry for my late response. I monitor the Issue Tracker page every day because of the new code sample request service
I suggest that you post a code sample request to us, and I will write this sample for you after I finish the preview handler sample requested by another community member.

Regards,
Jialiang Ge
Program Manager of All-In-One Code Framework

Nov 7, 2010 at 2:12 PM
Hi Jialiang,

Great to hear! Really looking forward to seeing a working example of a
CopyHook implementation in C#.

Thanks
Yves