【发布时间】:2017-05-03 03:29:30
【问题描述】:
概述
我正在使用SHChangeNotify 和SHCNE_RMDIR 来通知外壳程序已从我的shell namespace extension 中删除的文件夹。我的期望是,这将导致其文件夹视图导航到已删除文件夹(或其任何子文件夹)的任何资源管理器(或其他 shell)窗口被导航到已删除文件夹的父文件夹。此预期行为在 Windows 10 上发生。但是,在 Windows 7 上,这些窗口被导航到 removed 文件夹。
问题
Windows 7 上的这种行为是否是一个错误,和/或我可以做些什么(无需为 Windows 7 提供特殊代码)来获得两个操作系统的相同行为?
重现问题的详细步骤
这里介绍了如何从头开始创建和观察问题。这涉及使用名为Shell Instance Object 的“内置”Microsoft 命名空间扩展(而不是我真正的命名空间扩展)。为了简单起见,我使用它来表明它与我的特定命名空间扩展无关。这个示例命名空间扩展所做的只是在“我的电脑”下创建一个图标,该图标将浏览到您的 %TEMP% 目录。
-
安装命名空间扩展并在“我的电脑”下注册。为此,请在注册表中输入以下内容:
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%"这是一个 .reg 文件,它会为您自动执行该操作:
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"以下 .reg 文件可让您轻松删除上述注册表项:
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}] 此时,当您打开资源管理器窗口并浏览“我的电脑”时,您应该会看到“我的命名空间扩展”。浏览它应该会显示您的 %TEMP% 目录文件夹/文件。
在您的
%TEMP%文件夹中创建一个名为FolderToRemove的目录。在FolderToRemove中创建一个名为subFolder的子文件夹。-
打开 3 个资源管理器窗口并浏览到以下位置:
- 我的电脑\我的命名空间扩展
- 我的电脑\我的命名空间扩展\FolderToRemove
- 我的电脑\我的命名空间扩展\FolderToRemove\subFolder
-
在 Windows 7 上,执行以下 C++ 代码:
// 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); -
执行上述代码后,您会注意到唯一更改的浏览器窗口是最初导航到
My Computer\My Namespace Extension\FolderToRemove\subFolder的浏览器窗口。注意它现在指向My Computer\My Namespace Extension\FolderToRemove: 预计其中两个资源管理器窗口已更改,因此它们都导航到
My Computer\My Namespace Extension(已删除文件夹的父文件夹)。这是预期行为的图像(这是在 Windows 10 上发生的情况):
补充说明
-
我发现我可以通过在
SHChangeNotify中指定已删除文件夹的父 文件夹来获得我想要的Windows 7 行为。例如:// 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);但是,当我在 Windows 10 上执行此代码时,它当然会导致窗口导航回
My Computer,这是不希望的。如果我采用这种解决方法,我将需要针对不同操作系统的不同代码。
【问题讨论】:
-
您实际上并没有删除您告诉 Shell 您删除的文件夹,那么为什么您希望资源管理器在导航到的文件夹实际上没有消失时做出反应?当您实际删除文件夹时会发生什么?
-
您是否为已删除文件夹的父文件夹发送
SHCNE_UPDATEDIR?我还发现了这个花絮:verycomputer.com/137_8630153c209e1f9e_1.htm#p3 "例如,在处理 SHCNE_RMDIR 时,树可能会绑定到您传递给 SHChangeNotify 的 pidl 的父 IShellFolder 并使用您的文件夹的相对 pidl 调用 IShellFolder::CompareIDs正在发送更改通知和缓存在树视图中的相对 pidl 以查找匹配项。树还可能有其他 IShellFolder 方法,例如 GetAttributesOf。确保返回正确的值" -
上面关于实际上没有将该项目报告为已删除(在发送删除通知后)的评论是正确的,基于 Microsoft 的响应(在下面的答案中)。资源管理器尝试查找以报告为已删除的文件夹开头的有效文件夹。
标签: winapi shell-extensions shell32 shell-namespace-extension