/// <summary>
        ///     Start shell watcher.
        /// </summary>
        public void Start()
        {
            if (this.Running)
            {
                return;
            }

            var entry = new SHChangeNotifyEntry
            {
                fRecursive = this.recursive,
                pidl       = this.shellObject.ShellItem.PIDL
            };

            const Int32 flags = SHCNRF.SHCNRF_ShellLevel |
                                SHCNRF.SHCNRF_InterruptLevel |
                                SHCNRF.SHCNRF_NewDelivery;

            this.registrationId = ShellWatcherNativeMethods.SHChangeNotifyRegister(
                this.ListenerWindow.Handle,
                flags,
                this.eventManager.RegisteredTypes,
                this.Message,
                1,
                ref entry);
            if (this.registrationId == 0)
            {
                throw new Win32Exception(ErrorMessages.ShellWatcherRegisterFailed);
            }

            this.Running = true;
        }
        /// <summary>
        ///     Stop shell watcher.
        /// </summary>
        public void Stop()
        {
            if (!this.Running)
            {
                return;
            }

            if (this.registrationId > 0)
            {
                ShellWatcherNativeMethods.SHChangeNotifyDeregister(this.registrationId);
                this.registrationId = 0;
            }
        }
        /// <summary>
        ///     Initialize a instance of the <see cref="ShellChangeNotify"/> class.
        /// </summary>
        /// <param name="wParam"><c>WPARAM</c>.</param>
        /// <param name="lParam"><c>LPARAM</c>.</param>
        internal ShellChangeNotify(IntPtr wParam, IntPtr lParam)
        {
            var    hwnd      = wParam;
            var    processId = (UInt32)lParam.ToInt64();
            IntPtr pidl;
            uint   lEvent;
            var    lockId = ShellWatcherNativeMethods.SHChangeNotification_Lock(hwnd, processId, out pidl, out lEvent);

            try
            {
                this.ChangeType = (ShellChangeTypes)lEvent;
                var notifyStruct = (ShellNotifyStruct)Marshal.PtrToStructure(pidl, typeof(ShellNotifyStruct));

                var guid = new Guid(ShellIID.IShellItem2);

                // dwItem1
                if (notifyStruct.item1 != IntPtr.Zero &&
                    (this.ChangeType & ShellChangeTypes.SystemImageUpdate) == ShellChangeTypes.None)
                {
                    var shellObject = CreateShellObject(notifyStruct.item1, ref guid);
                    if (shellObject != null)
                    {
                        this.ShellObject = shellObject;
                    }
                }
                else
                {
                    ImageIndex = notifyStruct.item1.ToInt32();
                }

                // dwItem2
                if (notifyStruct.item2 != IntPtr.Zero)
                {
                    var shellObject = CreateShellObject(notifyStruct.item2, ref guid);
                    if (shellObject != null)
                    {
                        this.ShellObject2 = shellObject;
                    }
                }
            }
            finally
            {
                if (lockId != IntPtr.Zero)
                {
                    ShellWatcherNativeMethods.SHChangeNotification_Unlock(lockId);
                }
            }
        }