在32位程序中,如何获取打开/保存文件对话框以显示64位系统的System32文件夹中的文件?
(Wow64DisableWow64FsRedirection
不起作用,因为由于某种原因它不适用于对话框,我猜是因为它在不同的线程上。当然使用SysNative
不会工作,因为用户不知道内部发生了什么;他只是想看到计算机上的“实际”文件。)
这是提出问题的另一种方式:
任何 32位程序是否从打开的文件对话框中浏览64位System32
文件夹?
答案 0 :(得分:4)
我认为这根本不可能。
即使您可以让对话框显示文件,当它们返回到32位进程时,它们的名称会是什么? Sysnative是一个黑客攻击,无论如何在XP 64上都不可用。这只是系统32名称重载的结果。
另一个思想实验。如果可能的话,您需要执行枚举的线程来禁用重定向。由于该线程不受您的控制,因此必须有一个已发布的选项来禁用它。没有。允许您从外部禁用重定向是不合适的,因为当32位进程尝试加载shell扩展时会导致DLL加载失败 - 如果您要加载DLL,则无法禁用重定向,因为您将获得错误的
我想如果你想绕过这个限制,你应该写一个64位程序。
答案 1 :(得分:1)
我有一个有效的解决方案。这是一种黑客行为,但它确实有效。
在我展示解决方案之前的简要免责声明。我大多同意赫弗曼的观点。这并不意味着。我实际上并不建议这样做以运送代码。这是没有32位文本编辑器,文字处理器(包括32位Office)或普通应用程序支持的东西。 64位系统上的普通用户不直接在系统目录中打开或保存文件。无论如何,大多数非管理员用户都没有适当的权限来触摸那里的文件。 Microsoft重定向文件系统的理由非常适合32位应用程序。不要试图打击它。
现在解决方案。
诀窍是在DllMain中为每个DLL_THREAD_ATTACH回调调用一个DLL Wow64DisableWow64FsRedirection。
首先创建一个只有DllMain的简单DLL并导出几个函数:“StartDisableRedirect”和“DisableRedirection”。
bool g_fDisableRedirect = false;
__declspec(dllexport)
int DisableRedirection()
{
void* pVoid = NULL;
Wow64DisableWow64FsRedirection(&pVoid);
return 0;
}
__declspec(dllexport)
int StartDisableRedirect()
{
g_fDisableRedirect = true;
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
{
void* pVoid = NULL;
if (g_fDisableRedirect)
{
DisableRedirection();
}
break;
}
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
让您的二进制文件(EXE或DLL)直接与此DLL链接。然后在调用GetOpenFileName之前,调用StartDisableRedirect(以便后续线程不被重定向)和DisableRedirect(用于当前线程)。
我故意制作一个“开始”函数,以便在钩子实际开始处理线程之前加载所有DLL(包括系统DLL)。我不想假设在我的DLL之前加载实现Wow64Disable的DLL。从DllMain调用代码时,你必须非常小心(读:不应该)。
extern int StartDisableRedirect();
extern int DisableRedirection();
void OnFile(HWND hwndParent)
{
StartDisableRedirect();
DisableRedirection();
OPENFILENAME ofn = {};
WCHAR szFile[MAX_PATH*2] = {};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndParent;
ofn.lpstrFilter = L"All Files\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = ARRAYSIZE(szFile);
ofn.Flags = OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
::GetOpenFileName(&ofn);
}
答案 2 :(得分:0)
这是安装程序的常见问题。人们希望为32位和64位系统提供单个安装程序可执行文件,这意味着它必须是32位。但是,32位安装程序无法将64位可执行文件放在正确的位置。解决方案as described by Raymond Chen是有一个单独的64位安装程序,可以在64位计算机上由32位版本调用。
您将创建一个64位程序,其作用是以您的应用程序窗口作为所有者打开一个公共对话框。在64位系统上,您只需创建打开对话框的过程,并将传递给GetOpenFileName
或其他任何内容的参数传递给它。您可以在stdout上侦听文件名或使用其他一些IPC机制。打开返回的文件时,请记得使用Wow64DisableWow64FsRedirection
!让UI在另一个进程中运行似乎很笨拙,但它对用户来说是无缝的,许多Web浏览器在不同的进程中运行不同的选项卡或插件。
如果您使用Vista或更高版本,则可以使用IFileDialog
界面,该界面允许您为SysNative
目录添加“地点”。这样,您的用户仍然可以在需要时访问这些文件。甚至可能有一种简单的方法来重定向事物,以便当有人点击System32
目录时,您可以将其转到SysNative
。