Overview
I am using SHChangeNotify
with SHCNE_RMDIR
to notify the shell of a folder that has been removed from within my shell namespace extension. My expectation is that this will cause any explorer (or other shell) windows which have their folder view navigated into the removed folder (or any of its sub folders) to be navigated to the parent folder of the removed folder. This expected behavior is occurring on Windows 10. However, on Windows 7 those windows are being navigated to the removed folder.
Question
Is this behavior on Windows 7 a bug, and/or is there something I can do (without having special code for Windows 7) to get the same behavior for both OSes?
Detailed steps to reproduce the issue
Here is a walk through of how to create and observe the issue from scratch. This involves using a "built in" Microsoft namespace extension called a Shell Instance Object (rather than my real namespace extension). I used this for simplicity as well as to show that it is not related to my specific namespace extension. All this sample namespace extension does is creates an icon under "My Computer" that will browse into your %TEMP% directory.
Install the namespace extension and register it under "My Computer". To do this, enter the following into the registry:
HKEY_CURRENT_USER\Software\Classes\CLSID {0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}=REG_SZ_EXPAND:"My Namespace Extension" DescriptionID=REG_DWORD:0x00000008 System.IsPinnedToNameSpaceTree=REG_DWORD:0x00000001 DefaultIcon=REG_EXPAND_SZ:"%SystemRoot%\system32\main.cpl,9" InProcServer32=REG_EXPAND_SZ:"%SystemRoot%\system32\shdocvw.dll" ThreadingModel=REG_SZ:"Apartment" ShellFolder Attributes=REG_DWORD:0x60000000 Instance CLSID=REG_SZ:"{0AFACED1-E828-11D1-9187-B532F1E9575D}" InitPropertyBag Attributes=REG_DWORD:0x00000011 Target=REG_SZ_EXPAND:"%TEMP%"
Here is a .reg file that will automate that for you:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}] @="My Namespace Extension" "System.IsPinnedToNameSpaceTree"=dword:00000001 "DescriptionID"=dword:00000008 [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\DefaultIcon] @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ 00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,6d,00,61,00,\ 69,00,6e,00,2e,00,63,00,70,00,6c,00,2c,00,39,00,00,00 [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\InProcServer32] @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ 00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,68,00,\ 64,00,6f,00,63,00,76,00,77,00,2e,00,64,00,6c,00,6c,00,00,00 "ThreadingModel"="Apartment" [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\Instance] "CLSID"="{0AFACED1-E828-11D1-9187-B532F1E9575D}" [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\Instance\InitPropertyBag] "Attributes"=dword:00000011 "Target"=hex(2):25,00,54,00,45,00,4d,00,50,00,25,00,00,00 [HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\ShellFolder] "Attributes"=dword:60000000 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Namespace\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}] @="My Namespace Extension"
The following .reg file will allow you to easily remove the above registry entries:
Windows Registry Editor Version 5.00 [-HKEY_CURRENT_USER\Software\Classes\CLSID\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}] [-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Namespace\{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}]
At this point, when you open an explorer Window and navigate through "My Computer", you should see the "My Namespace Extension". Browsing into it should reveal your %TEMP% directory folders/files.
Create a directory in your
%TEMP%
folder calledFolderToRemove
. WithinFolderToRemove
create a sub folder calledsubFolder
.Open 3 explorer windows and browse to the following locations:
- My Computer\My Namespace Extension
- My Computer\My Namespace Extension\FolderToRemove
- My Computer\My Namespace Extension\FolderToRemove\subFolder
On Windows 7, Execute the following C++ code:
// This path represents My Computer\My Namespace Extension\FolderToRemove const wchar_t * pPath = L"::{20d04fe0-3aea-1069-a2d8-08002b30309d}\\::{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}\\FolderToRemove"; SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pPath, NULL);
After having executed the above code, you'll notice that the only explorer window that changed was the one that was originally navigated into
My Computer\My Namespace Extension\FolderToRemove\subFolder
. Notice that it is now pointing toMy Computer\My Namespace Extension\FolderToRemove
:The expectation is for two of the explorer windows to have changed, such that they are all navigated to
My Computer\My Namespace Extension
(the parent folder of the the removed folder). Here is an image of the expected behavior (which is what happens on Windows 10):
Additional notes
I found that I can get the behavior I want for Windows 7 by specifying the parent folder of the removed folder in the
SHChangeNotify
. E.g.:// This path represents My Computer\My Namespace Extension const wchar_t * pPath = L"::{20d04fe0-3aea-1069-a2d8-08002b30309d}\\::{0672A6D1-A6E0-40FE-AB16-F25BADC6D9E4}"; SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pPath, NULL);
But when I execute this code on Windows 10 it, of course, causes the windows to be navigated back to
My Computer
which is undesired. If I went with this workaround I would need different code for different OSes.