Как получить 64-битный каталог "программных файлов" в 32-разрядном приложении

У меня есть приложение, скомпилированное в режиме x86 (в С#), из которого мне нужно получить доступ к определенному файлу, который существует в 64-разрядной папке программных файлов (конечно, 64-разрядной Windows). Я не хочу просто hardcode C:\Program Files как строку в приложении, потому что несколько целевых компьютеров могут иметь Windows, установленные на другом диске, или могут быть на других языках.

Проблема, с которой я сталкиваюсь, заключается в том, что использование Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) возвращает х86-вкус вместо желаемого каталога, если я не скомпилирую свою программу в 64-разрядном режиме. Из любопытства, что я могу сделать, чтобы не делать этого?

Ответ 1

В свойствах проекта была опция "Предпочтительно 32-бит". Отмена этой опции сделала трюк. Тем не менее, я все еще интересуюсь программным решением, а не тем.

На самом деле я думаю, что отключить Prefer 32bit на вариантах сборки - лучший способ пойти. Если вы не хотите, чтобы ваша программа обрабатывалась как 32-битный процесс, почему бы не сделать ее 64-битным процессом и избавить себя от каких-либо проблем.

См. также эту статью по этому вопросу Раймондом Ченом.

Сказав, что переменная среды ProgramW6432, предложенная griddoor, отлично справилась со мной, когда я попробовал ее.

Ответ 2

В настройках сборки снимите флажок Prefer 32-bit. Теперь Environment.SpecialFolder.ProgramFilesX86 вернет 32-битный путь, а Environment.SpecialFolder.ProgramFiles вернет 64-битный путь.

Ответ 3

Я боюсь, что WinAPI не поддерживает то, что вам нужно. Из-за виртуализации 32-битное приложение не может получить путь к 64-разрядным каталогам.

Обратитесь к: https://social.msdn.microsoft.com/Forums/vstudio/en-US/37e798f5-1b9b-42ce-89af-486ee3531c0b/32-bit-app-how-to-get-cprogram-files-directory-using-environmentgetfolderpath?forum=csharpgeneral

Любая попытка "угадать" правильный путь или использовать реестр может вызвать проблему в будущем...

Ответ 4

Учитывая, что вы можете быть разумно уверены:

  • Каталог программных файлов существует на том же диске, на котором установлена ​​система.
  • Они называются Program Files для x64 и x86 и Program Files (x86) для x64.

Тогда вы можете сделать что-то вроде этого:

    public static void Main(string[] args)
    {
        string baseDirectory = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System));
        string programFiles = "Program Files";
        string programFilesX86 = "Program Files (x86)";

        Console.WriteLine(Environment.Is64BitProcess ? "64-Bit Process" : "32-Bit Process");

        if (Environment.Is64BitOperatingSystem)
        {
            Console.WriteLine("64-bit operating system");
            Console.WriteLine("Program Files Directory: " + Path.Combine(baseDirectory, programFiles));
            Console.WriteLine("Program Files x86 Directory: " + Path.Combine(baseDirectory, programFilesX86));
        }
        else
        {
            Console.WriteLine("32-bit operating system");
            Console.WriteLine("Program Files Directory: " + Path.Combine(baseDirectory, programFiles));
        }

        Console.ReadKey(true);
    }

Однако следует отметить одно:

Каталоги программных файлов могут быть изменены, хотя Microsoft не поддерживается и может привести к другим проблемам системы.

Итак, я буду следовать за ними с хорошим Directory.Exists, и если вы их не найдете, вы можете посмотреть в реестре. Ключи, которые вы ищете:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\

  • ProgramFilesDir
  • ProgramFilesDir (x86)

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

Также обратите внимание, что это работает только с Windows Vista и выше, я не помню, как справлялись с ней странная Windows XP-64 или более старые версии Windows Server.

И последнее примечание: Linux/Android/iOS (ака, совместимая с Mono OS или Micro Framework) не имеют каталога "Program Files", поэтому убедитесь, что вы понимаете, что здесь вы указываете код ОС. Если вы хотите сделать это немного более агрессивным для ОС, подумайте о написании функции, которая может возвращать массив строк на основе текущей ОС для каталогов установки по умолчанию.