32-битный OpenFileDialog -> 64-битный System32? - PullRequest
1 голос
/ 09 марта 2011

В 32-битной программе как я могу получить диалоги открытия / сохранения файлов для отображения файлов в папке System32 64-битной системы?

(Wow64DisableWow64FsRedirection не работает, потому что по какой-то причине он не работает для диалога, я предполагаю, потому что он находится в другом потоке. И, конечно, использование SysNative не работает, потому что пользователь не знает, что происходит внутри, он просто хочет видеть «настоящие» файлы на компьютере.)


Вот еще один способ задать вопрос:

Любая ли 32-битная программа просматривает 64-битную папку System32 из диалога открытия файла?

Ответы [ 3 ]

4 голосов
/ 09 марта 2011

Я считаю, что это просто невозможно.

Даже если бы вы могли получить диалоговое окно для отображения файлов, какими бы они были, когда они были возвращены в ваш 32-битный процесс?Sysnative - это что-то вроде хака, и в любом случае он недоступен в XP 64. Это всего лишь следствие перегрузки имени system32.

Еще один мысленный эксперимент.Если бы это было возможно, вам нужен поток, который выполняет перечисление, чтобы отключить перенаправление.Так как этот поток находится вне вашего контроля, тогда должна быть опубликованная опция, чтобы отключить его.НетБыло бы бесполезно разрешать вам отключать перенаправление снаружи, потому что это приводило бы к сбоям загрузки DLL, когда 32-битный процесс пытался загрузить расширения оболочки - вы не можете отключить перенаправление, если собираетесь загружать DLL, потому что вы получитенеправильные

Я предполагаю, что вы должны написать 64-битную программу, если хотите обойти это ограничение.

1 голос
/ 09 марта 2011

У меня есть рабочее решение для этого.Это что-то вроде хака, но это работает.

Краткий отказ от ответственности, прежде чем я покажу решение.Я в основном согласен с Хефферманом.Не судьба.Я на самом деле не рекомендую делать это для доставки кода.Это то, что не поддерживает ни 32-битный текстовый редактор, ни текстовый процессор (включая 32-битный Office), ни обычное приложение.Обычные пользователи в 64-битных системах не открывают и не сохраняют файлы непосредственно в системных каталогах.И большинство пользователей, не являющихся администраторами, в любом случае не имеют соответствующих прав для доступа к файлам.Microsoft перенаправляет файловую систему с очень веской причиной для 32-битных приложений.Не пытайтесь бороться с этим.

Теперь перейдем к решению.

Хитрость заключается в том, чтобы иметь вызов DLL Wow64DisableWow64FsRedirection в DllMain для каждого обратного вызова DLL_THREAD_ATTACH.

Первое созданиепростая 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 (для текущего потока).

Я специально сделал функцию «Пуск», чтобы все 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);

}
0 голосов
/ 09 марта 2011

Это общая проблема с установщиками.Люди хотят поставлять один исполняемый файл установщика для 32-разрядных и 64-разрядных систем, то есть он должен быть 32-разрядным.Однако 32-разрядный установщик не может разместить 64-разрядные исполняемые файлы в нужном месте.Решение , описанное Раймондом Ченом , заключается в наличии отдельного 64-разрядного установщика, который вызывается 32-разрядной версией на 64-разрядных компьютерах.

Вы должны создать 64-Битовая программа, задача которой - открыть общий диалог с окном вашего приложения в качестве владельца.В 64-битной системе вы просто создаете процесс, который открывает диалоговое окно, передавая ему параметры, которые вы передадите GetOpenFileName или как угодно.Вы можете прослушивать имена файлов на stdout или использовать какой-то другой механизм IPC.Не забудьте использовать Wow64DisableWow64FsRedirection при открытии возвращенных файлов!Может показаться неуклюжим, что пользовательский интерфейс работает в другом процессе, но это будет беспрепятственно для пользователей, и многие веб-браузеры запускают разные вкладки или плагины в разных процессах.

Если вы хорошо используете Vista иливыше, вы можете использовать интерфейс IFileDialog, который позволит вам добавить «Place» для каталога SysNative.Таким образом, ваши пользователи могут получить доступ к файлам, если им это необходимо.Может даже существовать простой способ перенаправить вещи, чтобы, когда кто-то щелкнул по каталогу System32, вы взяли его вместо SysNative.

...