SHCreateItemFromParsingName return FILE_NOT_FOUND 指定文件名时
SHCreateItemFromParsingName return FILE_NOT_FOUND when filename specified
我尝试获取文件的 IShellItem,以使用 IFileOperation COM 接口将其从系统目录复制到另一个目录。为此,我必须完全使用 IFileOperation COM 接口。
当我指定完整文件名时 - SHCreateItemFromParsingName()
中的 return 值是 ERROR_FILE_NOT_FOUND
,但文件存在于目录中。当我从下面的路径中删除文件名并仅使用文件夹路径时 - 一切似乎都很好,return 值为 S_OK
.
//...
CoInitialize(NULL);
//...
WCHAR szSourceDll[MAX_PATH * 2];
wcscpy_s(szSourceDll, MAX_PATH, L"C:\Windows\System32\sysprep\cryptbase.dll");
r = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_HANDLER, &IID_IFileOperation, &FileOperation1);
if (r != S_OK) return;
FileOperation1->lpVtbl->SetOperationFlags(FileOperation1, FOF_NOCONFIRMATION | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION);
r = SHCreateItemFromParsingName(szSourceDll, NULL, &IID_IShellItem, &isrc);
//...
CoUninitialize();
//...
为什么用 C
编写的代码不能处理文件名。如何为系统文件夹中的文件创建 IShellItem
实例以复制它?
P.S.
Windows 7 x64,C,Visual Studio 2015,v140 平台工具集,附加依赖项:Msi.lib;Wuguid.lib;ole32.lib;ntdll.lib
P.P.S
它可以正确处理用户目录中的文件...
假设您的应用程序被编译为 32 位应用程序并且 运行 在 64 位 OS 上,找不到文件错误可能是正确的,因为您的应用程序被重定向到 32-位系统目录(%WinDir%\SysWoW64
).
In most cases, whenever a 32-bit application attempts to access %windir%\System32, %windir%\lastgood\system32, or %windir%\regedit.exe, the access is redirected to an architecture-specific path.
有关详细信息,请参阅 MSDN 上的 File System Redirector。
您可以暂时关闭线程中的重定向,但在调用 shell 函数时这样做并不安全,仅在 kernel32 中起作用。如果您在内部调用的 API 使用 LoadLibrary
and/or COM,则 API 可能会失败,因为在禁用重定向时它将无法从 system32 加载。
您还可以使用 %WinDir%\SysNative
后门访问本机 system32 目录。这仅适用于 64 位 Vista+ 上的 32 位应用程序,因此您必须进行一些版本检测。
我尝试获取文件的 IShellItem,以使用 IFileOperation COM 接口将其从系统目录复制到另一个目录。为此,我必须完全使用 IFileOperation COM 接口。
当我指定完整文件名时 - SHCreateItemFromParsingName()
中的 return 值是 ERROR_FILE_NOT_FOUND
,但文件存在于目录中。当我从下面的路径中删除文件名并仅使用文件夹路径时 - 一切似乎都很好,return 值为 S_OK
.
//...
CoInitialize(NULL);
//...
WCHAR szSourceDll[MAX_PATH * 2];
wcscpy_s(szSourceDll, MAX_PATH, L"C:\Windows\System32\sysprep\cryptbase.dll");
r = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_HANDLER, &IID_IFileOperation, &FileOperation1);
if (r != S_OK) return;
FileOperation1->lpVtbl->SetOperationFlags(FileOperation1, FOF_NOCONFIRMATION | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION);
r = SHCreateItemFromParsingName(szSourceDll, NULL, &IID_IShellItem, &isrc);
//...
CoUninitialize();
//...
为什么用 C
编写的代码不能处理文件名。如何为系统文件夹中的文件创建 IShellItem
实例以复制它?
P.S.
Windows 7 x64,C,Visual Studio 2015,v140 平台工具集,附加依赖项:Msi.lib;Wuguid.lib;ole32.lib;ntdll.lib
P.P.S
它可以正确处理用户目录中的文件...
假设您的应用程序被编译为 32 位应用程序并且 运行 在 64 位 OS 上,找不到文件错误可能是正确的,因为您的应用程序被重定向到 32-位系统目录(%WinDir%\SysWoW64
).
In most cases, whenever a 32-bit application attempts to access %windir%\System32, %windir%\lastgood\system32, or %windir%\regedit.exe, the access is redirected to an architecture-specific path.
有关详细信息,请参阅 MSDN 上的 File System Redirector。
您可以暂时关闭线程中的重定向,但在调用 shell 函数时这样做并不安全,仅在 kernel32 中起作用。如果您在内部调用的 API 使用 LoadLibrary
and/or COM,则 API 可能会失败,因为在禁用重定向时它将无法从 system32 加载。
您还可以使用 %WinDir%\SysNative
后门访问本机 system32 目录。这仅适用于 64 位 Vista+ 上的 32 位应用程序,因此您必须进行一些版本检测。