32位OpenFileDialog - > 64位System32?

时间:2011-03-09 04:47:29

标签: c# .net winapi openfiledialog wow64

在32位程序中,如何获取打开/保存文件对话框以显示64位系统的System32文件夹中的文件?

Wow64DisableWow64FsRedirection不起作用,因为由于某种原因它不适用于对话框,我猜是因为它在不同的线程上。当然使用SysNative不会工作,因为用户不知道内部发生了什么;他只是想看到计算机上的“实际”文件。)


这是提出问题的另一种方式:

任何 32位程序是否从打开的文件对话框中浏览64位System32文件夹?

3 个答案:

答案 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

相关问题