2011-03-09 172 views
1

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

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


这里是另一种方式来问这个问题:

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

+0

当你想在system32文件夹中显示文件时,不应该在对话框中设置正确的初始文件夹吗? – GolezTrol 2011-03-09 06:48:49

+0

@GolezTrol:这是一个文本编辑器(以及我制作的类似类型的应用程序),其中*我*不会对用户选择的内容有任何偏好,但是如果他想要在'System32'中选择一些东西,然后他不能。无论如何,这不是一个真正的解决方案,但只是一个解决方法,并不真正起作用。 (谢谢你的建议。) – Mehrdad 2011-03-09 06:50:29

+0

如果你使用C#,为什么不为'AnyCPU编译而不用担心呢? – Gabe 2011-03-09 08:32:28

回答

4

我相信这根本不可能。

即使您可以让对话框显示这些文件,当它们返回到您的32位进程时,它们的名称是什么? Sysnative有点破解,在任何情况下XP 64都不可用。这只是重载system32名称的结果。

另一个思想实验。如果可能的话,您需要执行枚举的线程禁用重定向。由于该线程超出了您的控制范围,因此必须有发布选项才能禁用该线程。没有。如果您要加载DLL,因为这会导致在32位进程尝试加载外壳扩展时导致DLL加载失败,因此您可以禁用外部重定向,因为您将获得加载DLL的权限错误的

我想你应该写一个64位的程序,如果你想解决这个限制。

+0

这与禁用重定向后使用标准FindFirstFile API枚举文件有什么不同?它会返回文件的真实名称,很简单。 .. – Mehrdad 2011-03-09 07:54:06

+0

如果它将system32返回到你的32位进程,那么当你访问该文件时,你会被重定向到syswow64。 – 2011-03-09 07:57:41

+0

@David:不,我不会,因为我会禁用重定向...这就是'Wow64DisableWow64FsRedirection'的全部重点。 – Mehrdad 2011-03-09 07:58:36

1

我对此有一个工作解决方案。这是一种黑客,但它的工作原理。

在我展示解决方案之前的简短声明。我主要同意Hefferman。这并不意味着。我实际上并不推荐这样做的代码。这是没有32位文本编辑器,文字处理器(包括32位Office),或正常的应用程序支持。 64位系统上的普通用户不直接在系统目录中打开或保存文件。而且,大多数非管理员用户无论如何都无权触摸文件。微软重新定向文件系统的原因非常好,适用于32位应用程序。不要试图与它战斗。

现在解决方案。

诀窍是在DllMain中为每个DLL_THREAD_ATTACH回调调用Wow64DisableWow64FsRedirection。

首先创建一个简单的DLL,它只有一个DllMain并导出一些函数:“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(用于当前线程)。

我故意做了一个“Start”函数,使得所有的DLL(包括系统DLL)都在钩子实际开始处理线程之前被加载。我不想假设实现Wow64Disable的DLL会在我的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); 

} 
+0

哇,真好! o__o所以......这是如何处理系统DLL在不同线程中延迟加载的情况(这种情况在第一次加载对话框时似乎几乎发生)? – Mehrdad 2011-03-09 09:36:50

+0

@Mehrdad它不会。外壳扩展将会杀死这个。 – 2011-03-09 09:39:41

+0

@David:我当时并没有真正在谈论shell扩展,我只是在讨论* regular * DLLs,比如'Ole32.dll',它们是windows的正常组成部分,并且在每一种情况下都会延迟加载。我很好奇这是如何处理的,因为@selbie显然说它是有效的。 :) – Mehrdad 2011-03-09 09:42:38

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

+0

跨进程的东西不适合我,但有趣的想法'IFileDialog'。 – Mehrdad 2011-03-09 10:26:22

+0

@Mehrdad:当你说它不起作用时,你的意思是你不能使用解决方案,或者它实际上失败了? – Gabe 2011-03-09 10:46:33

+0

我的意思是前者。 :\感谢您的想法,但。 – Mehrdad 2011-03-09 11:00:38