GetThreadLocale возвращает другое значение, чем GetUserDefaultLCID?

Вот CASE примеры оператора из документов PostgreSQL (Пост-ГРЭС следует стандарту SQL здесь):

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

или

SELECT a,
   CASE a WHEN 1 THEN 'one'
          WHEN 2 THEN 'two'
          ELSE 'other'
   END
FROM test;

, Очевидно, вторая форма является более чистой, когда Вы просто проверяете одно поле по списку возможных значений. Первая форма позволяет более сложные выражения.

16
задан Mick 20 November 2009 в 02:26
поделиться

4 ответа

Ты не единственный. Я тоже видел это с Windows 7 здесь, в Новой Зеландии, и, насколько я могу судить, по какой-то причине это только сбивает приложения Delphi.

Странная вещь, которую мы обнаружили, - это переключение на другие региональные настройки через Control Panel и последующее переключение обратно на NZ решает проблему. Мне было бы любопытно узнать, разрешит ли это тот же обходной путь вы, просто чтобы убедиться, что мы наблюдаем то же явление.

Мне интересно, не совсем ли не подходит выбор региональных настроек за пределами США в процессе установки Windows 7 «делать правильные вещи» каким-то тонким способом, который по какой-то причине только сбивает с толку приложения Delphi.

Я пришел к тесту, похожему на код JP, пытаясь отследить его и найти программный обходной путь, но у нашего специалиста по контролю качества был с тех пор как нашел '

15
ответ дан 30 November 2019 в 16:19
поделиться

Я заметил ту же проблему, когда начал использовать новый компьютер с Windows 7. Я потратил некоторое время, пытаясь найти причины этого, но ничего не нашел. Поэтому я просто добавил эти две строки в раздел инициализации некоторых модулей.

initialization
  SetThreadLocale(LOCALE_USER_DEFAULT);
  GetFormatSettings;

Странно то, что такое поведение наблюдается только на моем компьютере, так как у нас в офисе также мало других компьютеров с Win7.

6
ответ дан 30 November 2019 в 16:19
поделиться

Я только что протестировал новую установку Windows 7 Starter Edition, и у меня возникла та же проблема, но я обнаружил, что локаль, которую возвращает GetThreadLocale, именно та, которую возвращает программа установки Windows, но я изменил ее во время установки на другую, ту, которую возвращает GetUserDefaultLCID, тоже ту, которую я хотел использовать (я создал небольшую программу именно для этого). Итак, локаль изменилась для пользователя, но где-то все же была указана первая локаль, и она была возвращена GetThreadLocale. Как прокомментировал JP, на самом деле есть проблема с установкой, она не меняет локали во всех местах, где ее можно найти. Похоже, что изменение локали через Control Panel отлично справляется с задачей, и это может объяснить wy изменение локали, как это предлагается, кстати, это объясняет, почему другие компьютеры не могут иметь такую же проблему (если вы не сменили локаль во время установки). Надеюсь, это поможет.

1
ответ дан 30 November 2019 в 16:19
поделиться

Некоторую справочную информацию можно найти здесь:

http://www.siao2.com/2010/03/19/9980203.aspx

Итак, похоже, что эта проблема проявляется как в Vista, так и в Windows 7. Она возникает потому, что Microsoft, похоже, находится в процессе устаревания Locale ID в пользу Locale Name.

Подведем итоги: Все соответствующие вызовы API работают со значениями реестра, которые можно найти в HKCU\Control Panel\International. Значение "Locale" поддерживается для обратной совместимости и при нормальных обстоятельствах синхронизируется со своим новым аналогом под названием "LocaleName". Однако этот процесс синхронизации не работает при некоторых обстоятельствах.

В любом случае, вызов API GetThreadLocale получает возвращаемое значение из упомянутой выше записи реестра "Locale", в то время как другие (GetUserDefaultLCID, GetSystemDefaultLCID и т.д.) используют запись реестра "LocaleName".

Отсюда и путаница.

BTW, решение, упомянутое JP в предыдущем сообщении, вероятно, должно быть расширено до

initialization
  SetThreadLocale(GetUserDefaultLCID);
  GetFormatSettings;

потому что (если я правильно понял!) согласно docco вызов GetUserDefaultLCID будет учитывать пользовательские настройки.

После небольшого дополнительного исследования выяснилось, что Vista вообще не затронута. У меня тоже есть некоторые подробности ...

Все соответствующие вызовы API работают со значениями реестра, которые можно найти в HKCU\Control Panel\International. Значение " Locale " поддерживается в целях обратной совместимости и при нормальных обстоятельствах синхронизируется со своим более новым аналогом под названием " LocaleName ". В Windows 7, по крайней мере, этот процесс синхронизации не работает, когда процессы запускаются от имени другого пользователя (т.е. RunAs или Impersonation). Похоже, это происходит во время установки, когда программа установки запускается из существующей сессии windows. Однако она работает правильно, если вы загрузились с установочного компакт-диска.

  • GetThreadLocale получает свое значение из Thread Information Block или Thread Environment Block (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. Вызовы API SetThreadLocale(LOCALE_USER_DEFAULT) и SetThreadLocale(GetUserDefaultLCID) функционально эквивалентны. Они оба извлекают исходную локаль, как описано выше в вызове API GetUserDefaultLCID.

18
ответ дан 30 November 2019 в 16:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: