GetThreadLocale возвращает другое значение, чем GetUserDefaultLCID?
Чтобы получить настройки локали, например, краткий формат даты, мы всегда использовали GetLocaleFormatSettings с GetThreadLocale. Это всегда работало без проблем до сих пор.
Несколько наших пользователей получают разные значения для GetThreadLocale, которые не соответствуют тому, что они настроили в региональных настройках Windows 7. Мы не смогли воспроизвести это независимо от того, что мы пытаемся, но я отправил одному пользователю тест программа для получения информации о локали, и, конечно, GetThreadLocale возвращает LCID (1033), отличный от GetUserDefaultLCID (2057). Таким образом, вместо получения настроек локали в Великобритании, они заканчиваются настройками локали в США.
Мы получаем информацию о локали неправильно? Должны ли мы использовать GetUserDefaultLCID вместо GetThreadLocale?
Спасибо
5 ответов
Ты не единственный. Я видел это и в Windows 7 здесь, в Новой Зеландии, и, насколько я могу судить, кажется, что по какой-то причине он только запутывает приложения Delphi.
Странная вещь, которую мы обнаружили, заключается в том, что переключение на другие региональные настройки через панель управления, а затем переключение обратно в NZ решает проблему. Мне было бы любопытно узнать, разрешит ли тот же обходной путь это для вас, просто чтобы убедиться, что мы видим то же явление.
Мне интересно, если выбор региональных настроек за пределами США через процесс установки Windows 7 не совсем "делает правильные вещи" каким-то тонким способом, который по какой-то причине только запускает приложения Delphi.
Я пришел к тестовому коду, аналогичному JP, в попытке отследить его и найти обходной путь программного обеспечения, но наш специалист по обеспечению качества с тех пор нашел обходной путь "региональных настроек переключения", и ему не хотелось полностью переустанавливать Windows 7 снова, чтобы вернуться в оригинальное состояние фанки по какой-то причине:-)
Для некоторой справочной информации посмотрите здесь:
http://www.siao2.com/2010/03/19/9980203.aspx
Таким образом, кажется, что эта проблема проявляется как в Vista, так и в Windows 7. Это происходит потому, что Microsoft, кажется, находится в процессе устаревания идентификатора локали в пользу названия локали.
Подводя итог: все соответствующие вызовы API работают со значениями реестра, которые можно найти по адресу HKCU\Control Panel\International
, Значение " Locale " поддерживается по причинам обратной совместимости и при нормальных обстоятельствах синхронизируется с его более новым аналогом, называемым " LocaleName ". Этот процесс синхронизации, однако, не работает при некоторых обстоятельствах.
Во всяком случае, GetThreadLocale
Вызов API получает свое возвращаемое значение из записи реестра " Locale ", упомянутой выше, а остальные (GetUserDefaultLCID
, GetSystemDefaultLCID
и т. д.) используйте запись реестра " LocaleName ".
Отсюда и путаница.
Кстати, решение, упомянутое JP в предыдущем посте, вероятно, должно быть расширено до
initialization
SetThreadLocale(GetUserDefaultLCID);
GetFormatSettings;
потому что (если я читаю это правильно!) в соответствии с docco, вызов GetUserDefaultLCID будет учитывать пользовательские настройки.
После нескольких дополнительных исследований Vista не пострадала вообще. У меня есть еще немного деталей...
Все соответствующие вызовы API работают со значениями реестра, которые можно найти по адресу HKCU\Control Panel\International
, Значение " Locale " поддерживается по причинам обратной совместимости и при нормальных обстоятельствах синхронизируется с его более новым аналогом, называемым " LocaleName ". По крайней мере, в Windows 7 этот процесс синхронизации не работает, когда процессы запускаются от имени другого пользователя (например, RunAs или Impersonation). Это похоже на случай во время установки, когда установщик запускается из существующего сеанса Windows. Однако, похоже, что он работает правильно, если вы загрузились с установочного компакт-диска.
GetThreadLocale
получает значение из блока информации о потоке или блока среды потока (TIB или TEB). См.: http://en.wikipedia.org/wiki/Thread_Environment_Block для Vista, и для Windows 7 TIB инициализируется с помощьюHKCU\Control Panel\International\Locale
запись в реестре при входе в систему. Это становится языковым стандартом по умолчанию для всех потоков, созданных во время сеанса. Изменение этого значения реестра во время сеанса не влияет на значение, возвращаемое вызовом API GetThreadLocale. Пользователь должен выйти и снова войти, чтобы увидеть изменения. Это вызов API, который Delphi использует в качестве основы для инициализации всех строк формата локали (см.SysUtils.GetFormatSettings
метод), из которого отформатированы все поля даты.GetUserDefaultLCID
: в Vista основывает свое возвращаемое значение наHKCU\Control Panel\International\Locale
запись в реестре. В Windows 7 его возвращаемое значение основывается наHKCU\Control Panel\International\LocaleName
запись в реестре. Соответствующая запись реестра может быть изменена во время сеанса, и результат немедленно отражается в этом возвращаемом значении вызова API.SetThreadLocale
обновляет TIB для отображения локали, указанной в параметре для этого вызова. Обратите внимание, что это влияет только на поток, из которого выполняется вызов API. Вызовы APISetThreadLocale(LOCALE_USER_DEFAULT)
а такжеSetThreadLocale(GetUserDefaultLCID)
функционально эквивалентны. Они оба получают исходный язык, как описано вGetUserDefaultLCID
Вызов API выше.
Я заметил ту же проблему, когда начал использовать новый компьютер с Windows 7. Я потратил некоторое время, пытаясь найти причину этого, но ничего не нашел. Поэтому я просто добавил эти две строки в раздел инициализации некоторых модулей.
initialization
SetThreadLocale(LOCALE_USER_DEFAULT);
GetFormatSettings;
Странно, что такое поведение происходит только на моем компьютере, так как у нас в офисе также есть несколько других компьютеров Win7.
Новое сообщение на форуме RTL предлагает это исправить в SysUtils->InitSysLocale:
SetThreadLocale(LOCALE_USER_DEFAULT);
SysLocale.DefaultLCID := LOCALE_USER_DEFAULT;
GetFormatSettings;
И далее объясняет:
По умолчанию он должен быть установлен в LOCALE_USER_DEFAULT, а не в 0x409! Эта ошибка в 2010 году, XE и XE2
Я только что протестировал новую установку Windows 7 Starter Edition, и у меня возникла та же проблема, но я обнаружил, что локаль, которую возвращает GetThreadLocale, в точности совпадает с локалью, предложенной программой установки Windows, но я изменил ее во время установки на другую, которая это тот, который возвращает GetUserDefaultLCID, также тот, который я хотел использовать (для этого я создал небольшую программу). Итак, языковой стандарт изменился для пользователя, но где-то еще был указан первый языковой стандарт, и он был возвращен GetThreadLocale. Как прокомментировал JP, действительно существует проблема с установкой, она не меняет локаль во всех местах, где ее можно найти. Кажется, что смена языкового стандарта через панель управления делает свою работу хорошо, и это может объяснить, почему мы изменили его в соответствии с предлагаемыми работами, кстати, это объясняет, почему другие компьютеры не могут иметь такую же проблему (если вы не меняли языковой стандарт во время монтаж). Надеюсь, это поможет.