Сегодня я покажу приемы из личной практики. С этими ситуациями я сталкивался сам либо участники форума, которым я помогал. Я также расскажу о ценном дедовском методе применения региональных параметров одной командой, а в качестве бонуса – о нововведении в версии 20H1.
[+] Сегодня в программе
Замечание об учетной записи Microsoft
При работе с аккаунтом Microsoft есть возможность синхронизации языковых параметров. Если она включена, выполнение действий из этой статьи может привести к неоднозначным результатам.
Из облака могут подтягиваться параметры, настроенные на другом ПК или ранее сконфигурированные на этом же ПК. Второе возможно при многократном изменении настроек в короткий промежуток времени. Поэтому для чистоты эксперимента синхронизацию языковых настроек лучше отключить.
Теперь к делу!
Добавление и удаление языков
В форум пришел человек, который пользуется японским языком, но только периодически. Он установил японский язык и получил соответствующий метод ввода. Но поскольку этот язык нужен лишь изредка, большую часть времени он только мешает (раскладок и без него было три).
Время уходит на ручные действия и загрузку языкового пакета. Вопрос был в том, как оптимизировать процесс.
Для начала не нужно ставить языковой пакет, чтобы получить метод ввода. Достаточно добавить язык, а флажки с дополнительных компонентов можно снять.
В статье про неудаляемые языки я рассказывал, что список языков представляет собой массив. Там я оставлял только нужные языки, а здесь будет точечная работа с японским.
Добавление: скрипт добавляет японский язык и обновляет список языков.
$List = Get-WinUserLanguageList $List.Add("ja-JP") Set-WinUserLanguageList $List -Force $List
Удаление: скрипт получает список языков, находит там японский и удаляет его, после чего обновляет список языков.
$List = Get-WinUserLanguageList $remove = $List | where LanguageTag -eq "ja" $List.Remove($remove) Set-WinUserLanguageList $List -Force $List
В тему форума я доставил конфету – архив со скриптами и CMD-файлами для их простого запуска. Полить ее шоколадной глазурью можно, повесив на ярлыки сочетания клавиш.
Управление методами ввода (раскладками)
У меня на виртуальном десктопе клиента проявилась странная проблема. После перезагрузки из переключателя языков исчезала кастомная фонетическая раскладка, которой я пользуюсь очень много лет, так сложилось исторически ©
Переключатель методов ввода тоже исчезал, поскольку ради одного английского он не нужен. При этом раскладка корректно отображалась в свойствах русского языка. Вручную это решалось так: добавить стандартную раскладку – удалить фонетическую – добавить фонетическую – удалить стандартную.
Я автоматизировал это скриптом в автозагрузке. Каждый элемент языкового массива содержит набор свойств – языковых параметров. Ими тоже можно рулить в PowerShell.
$List = Get-WinUserLanguageList #очистить методы ввода у второго языка в списке (нумерация начинается с нуля) $List[1].InputMethodTips.Clear() #добавить "несуществующий" метод ввода $List[1].InputMethodTips.Add('0419:A0000419') Set-WinUserLanguageList $List -Force $List
Скрипт получает список языков и очищает методы ввода для стоящего вторым русского. Вообще, полная очистка не предусмотрена, потому что у языка всегда должен быть хотя бы один метод ввода. Поэтому в графическом интерфейсе невозможно удалить из языка единственную раскладку. Однако дальше добавляется раскладка с нужным идентификатором, а затем уже обновленный список раскладок применяется к языку.
Код 0419:A0000419
относится к моей фонетической раскладке. У вас она не установлена, поэтому скрипт просто удалит все раскладки из русского языка. Это к вопросу, как сделать язык без метода ввода ;)
Управление региональными форматами
В форум пришел человек, у которого в 20H1 после перезагрузки сбрасывался региональный формат с украинского на русский. У меня проблема воспроизвелась, поэтому я предложил обходной путь – при входе в систему задавать скриптом нужный формат региона.
Форматы не входят в сферу языков, поэтому способы выше не подходят. Выручает другой командлет – Set-Culture, задающий пользовательский регион с помощью идентификатора локали, LCID (в данном случае – украинской).
Set-Culture uk-UA
Управление различными языковыми настройками одной командой
На самом деле в форуме я предложил другой метод управления региональными форматами. Он мне вспомнился в рамках написания статьи о настройке языка ввода при входе в систему, но там его некуда было пристегнуть. Способ можно назвать «дедовским», потому что он работает еще со времен Windows Vista.
Создается специальный файл ответов в формате XML, который передается в качестве параметра командной строки элементу панели управления intl.cpl!
Делаем трюк два в одном! XML-файл добавляет украинский язык и задает регион, а русская стандартная раскладка заменяется на фонетическую.
<!-- control.exe intl.cpl,,/f:"C:\Scripts\lang.xml" https://support.microsoft.com/help/2764405/ --> <gs:GlobalizationServices xmlns:gs="urn:longhornGlobalizationUnattend"> <!-- Пользователи. Здесь текущий, но с правами администратора можно настроить систему и профиль Default, т.е. все будущие учетные записи --> <gs:UserList> <gs:User UserID="Current" CopySettingsToDefaultUserAcct="false" CopySettingsToSystemAcct="false"/> </gs:UserList> <!-- Регион, язык и раскладка клавиатуры в комплекте с ним --> <gs:UserLocale> <gs:Locale Name="uk-UA" SetAsCurrent="true" ResetAllSettings="false"> </gs:Locale> </gs:UserLocale> <!-- Добавление и удаление раскладок клавиатуры --> <gs:InputPreferences> <gs:InputLanguageID Action="add" ID="0419:A0000419"/> <gs:InputLanguageID Action="remove" ID="0419:00000419"/> </gs:InputPreferences> <!-- Язык для программ, не поддерживающих Юникод. Для этого параметра команду необходимо запускать с правами администратора. <gs:SystemLocale Name="ru-RU"/> --> </gs:GlobalizationServices>
Сохраненный файл можно применить одной командой из первой строки.
С помощью XML также можно установить системную кодовую страницу и скопировать параметры в системные аккаунты и профиль Default. В этом случае команду надо выполнять от имени администратора, а изменение локали применяется после перезагрузки.
Способ описан в KB2764405. Подробностей там немного, но есть пример точечной настройки форматов, а также ссылка на справку по XML. Судя по документу, когда-то метод затачивался под скрипты групповой политики в организациях, блокирующих доступ пользователей к региональным настройкам. В списке ОС статьи базы знаний отсутствует Windows 10, однако в целом технология в ней работает.
Более того, в ряде пограничных сценариев – это единственный метод автоматизации применения региональных настроек!
Международные команды DISM и командлеты PowerShell дополняют друг друга, но не покрывают всех ситуаций. Смотрите развесистый скрипт Проничкина на GitHub, где он комбинирует командлеты с файлом ответов для настройки системных учетных записей и удаленных сессий PowerShell.
Я не могу рекомендовать XML в качестве единственного способа применения региональных настроек, поскольку он обладает ограничениями (например, невозможно добавить несколько языков в один прием), а в некоторых сценариях ведет себя непоследовательно. Но если не извращаться и применять по делу, это вполне рабочий вариант.
Бонус: настройка предпочитаемого языка интерфейса в Windows 10 20H1
В блоге Майкла Нихауза недавно появилась запись с отсылкой к сессии Ignite 2019, которая привлекла мое внимание. В 20H1 придумали, как предотвратить проблему, с которой сталкивались многие международные организации и некоторые домашние пользователи.
Суть проблемы в том, что невозможно обновить ОС до новой версии или переустановить систему поверх, если язык дистрибутива не совпадает с языком установки системы.
Дома это решается обновлением посредством Windows Update, а при обновлении с диска – предварительной сменой языка из среды восстановления, о чем рассказывал в своем канале Telegram почти три года назад.
Однако 90% процентов организаций с многоязычной средой развертывают английский дистрибутив с языковыми пакетами, а необходимый пользователям язык задают параметром файла ответов UILanguage. Поскольку параметр в первую очередь задает язык установки ОС, впоследствии администраторы наступают на грабли, пытаясь обновить такую систему до новой версии с английского дистрибутива через WSUS/SCCM.
Суть изменения описывает слайд 12 презентации. В версии 20H1 предпочитаемый язык интерфейса ОС можно задать:
- как и прежде параметром UILanguage в файле ответов, но теперь он не задает язык установки ОС, т.е. не блокирует обновление
- новой командой DISM для автономных образов:
dism /image:c:\target /set-sysuilang:ru-ru
Это не решает проблем с уже установленными ОС, но позволяет их избежать в новых установках.
Заключение
Несмотря на многочисленные итерации графического интерфейса языковых настроек, способы автоматизации управления языками и методами ввода вполне стабильны. Да, в Windows 8 вместе с PowerShell 3.0 появились командлеты типа Get-WinUserLanguageList. Тогда же появились компоненты по требованию (features on demand), изменившие в том числе подход к управлению языковыми пакетами и компонентами. Но существенным изменением это было 8 лет назад, а сейчас лишь эволюционирует.
Andrew D
Глядя как вы в очередной раз показываете решение пользовательской задачи через PowerShell, возникает вопрос — а как этот самый PowerShell максимально эффективно и быстро изучить, и где смотреть справочник по командам, с информацией для каких версий ОС/PS оно актуально? Просто это выглядит очень интересно и удобно, но для того с чем сталкивался — обычно проще было сотворить cmd или найти и допилить что-то на базе vbs. Что-то сделанное через PS в основном вижу в этом блоге.
Vadim Sterkin
Хороший вопрос! CMD далеко не всегда проще, хотя бывает (тот же schtasks vs. scheduledtasks). Но если вы не осилили FOR (как я), то в CMD будет совсем тяжко :)
Изучать фундаментально — по книгам, например. Могу порекомендовать на английском:
• Windows PowerShell Cookbook (Lee Holmes)
• Learn Windows PowerShell in a Month of Lunches (Jeffery Hicks, Don Jones)
• Windows PowerShell in Action (Bruce Payette) — это рекомендация Василия Гусева и единственная книга по PS, которую он читал :) Он же настоятельно советует встроенную справку (Get-Help, Get-Command, Get-Member).
Помимо справки в документации удобно сделано https://docs.microsoft.com/powershell/
Есть браузер модулей, есть справка по командлетам, например, Get-WinUserLanguageList (версия PS в меню слева вверху).
Andrew D
Немного покопался, для понимания «с чего начать» мне кажется годным еще и этот ресурс:
http://get-powershell.ru/2015/vvedenie-v-powershell/
Lecron
Недавно на Хабре вышел небольшой цикл статей по PS. Для обзорного изучения, кмк достаточно. Детали и тонкости, после, по необходимости. Ибо лучшее изучение, это в процессе использования.
Valentina Lemiakina
Согласна с комментарием.
Внизу страницы у Вадима есть список «рекомендую ресурсы», там есть источники в том числе и по Powershell.
Vadim Sterkin
Да, там хорошие источники (иначе я бы их не рекомендовал), но изучать основы по ним не получится. Там можно найти относительно простые примеры/задачи, но уровень знания PS у этих людей на порядок выше моего и контент соответствующий:)
Lecron
Нужен командлет Get-WinLanguageList показывающий доступные коды с читаемым названием языка.
Тогда и работа происходила более консистентно
Оба параметра объект. Сейчас, при добавление строка, а при удалении объект
Еще одна неоднозанчность.
$List.Add(«ja-JP») — в кавычках, строка
Set-Culture uk-UA — без кавычек, как бы ссылка на объект.
Vadim Sterkin
Не совсем понял. Вот читаемые —
EnglishName
.Если речь про все возможные (а не установленные), то можно наверное заморочиться и извлечь все cultures. Но только не все совпадут с LanguageTag, что видно даже из вывода выше. Поэтому можно использовать EnglishName — вполне наглядно.
Vadim Sterkin
Видимо, речь об этом https://habr.com/ru/company/ruvds/blog/503818/ (одна из частей). Может для начинающих он ок, но как по мне — там в основном список командлетов и примеры вывода. Даже в решении практических задач таковых задач фактически нет:)
Думаю, так людей на пошик не вдохновить, поэтому у меня другой подход ;)
Lecron
Да, все возможные. Хотя бы просто на посмотреть, даже если не будет участвовать в скрипте. А то захочу поставить например голландский, иди броди по сети, ищи коды.
Про englishName не понял. Хотя возможную проблему с languageTag заметил. По полю аккуратно разложены грабли? Или есть рецепт чтобы вход и выход совпадал? Хочется такого
LangCode даже можно принять извне параметром. Set-WinUserLanguageList строки на вход принимает. В вашем примере в список языков кладется обычная строка. Значит можно оперировать только строками языковых кодов. Но никак. Не логично.
Vadim Sterkin
Зайдете сюда, а ссылка есть в статье, правда в другом разделе: LCID. Думаю, что ИД локали и языков одинаковые.
В примере я удаляю по LanguageTag, но можно и по имени. Но добавить так не получится, да.
Да, я тоже наступил на эти грабли, поэтому такой вот скрипт удаления и получился :) Объяснить затрудняюсь, это уже к гуру пошика.
Lecron
Все равно что-то царапает. Даже не разница кода, а что пользователю нужно подставлять разные параметры. ja-Jp и (ja или Japanese). То есть вначале выполнить комманду, посмотреть на ее вывод, и только потом отредактировать скрипт.
Как понимаю, отброс суффикса JP происходит, если существует только одна культура с префиксом ja. Для hr такого не произойдет, ибо BA и HR. Список языков нашел как
[System.Globalization.Cultureinfo]::GetCultures("AllCulture")
. В идеале, поведение должно быть таким (пример на Питоне):дальше, как в статье. Кто захочет прокачать скиллы в PS может заняться.
artem
Вообще, строго говоря, в обоих случаях объект. (И даже не только потому, что строка — на самом деле тоже объект. Объект типа «строка», System.String.)
В справке по Get-WinUserLanguageList написано, что коммандлет возвращает объект вот этого типа:
(https://docs.microsoft.com/powershell/module/international/Get-WinUserLanguageList)
Т.е. это объект, который представляет собой коллекцию (List) объектов типа «WinUserLanguage»
Точно такой же объект принимает параметр -LanguageList коммандлета Set-WinUserLanguageList. Это, опять же, следует из справки.
(https://docs.microsoft.com/powershell/module/international/Set-WinUserLanguageList)
Когда вы выполняете операции с коллекцией (add или remove), вы используете соответствующие методы .NET, присущие объекту коллекции (типа «List»).
https://docs.microsoft.com/dotnet/api/system.collections.generic.list-1.add
https://docs.microsoft.com/dotnet/api/system.collections.generic.list-1.remove
Как следует из документации по этим методам, в качестве аргумента передаётся объект того же типа, которому принадлежат все объекты коллекции. Т.е., в нашем случае, «Microsoft.InternationalSettings.Commands.WinUserLanguage».
Как же так работает, когда вы указываете строку (типа «ja-JP»)? А вот так. PowerShell умеет подспудно превращать одни типы в другие, при соблюдении ряда условий. (Т.е. если он понимает, какой тип от него ожидают, и такое превращение в принципе возможно.)
Как это проверить?
Ну, например.
Первая строка создаёт объект. Поскольку мы не указываем тип явно, PowerShell угадывает сам. Тут угадать не сложно — текст по умолчанию считается объектом типа «String». Что мы и проверяем второй строкой, которая выводит полное имя типа. Соответственно, пример выше выводит результат: «System.String». Но это произошло бы в общем случае, если бы мы с этой строкой ничего дальше не делали (и PowerShell бы не испытывал необходимости приводить объект к другому типу).
А что же происходит в нашем случае, когда PowerShell заранее знает, что метод «Add» ожидает получить объект типа «Microsoft.InternationalSettings.Commands.WinUserLanguage»? Он пытается превратить строку, котрую вы указали, в объект нужного типа. Примерно вот так.
Первая строка нужна для того, чтобы PowerShell подгрузил библиотеки, отвечающие за нужный тип. Если её не выполнять (и не запускать предварительно какие-нибудь коммандлеты из этого модуля), то произойдёт ошибка из-за того, что тип не будет найден. (В случае, когда ранее выполнялся коммандлет «Get-WinUserLanguageList» такой необходимости нет, потому что модуль уже загружен).
В третьей строке мы создаём новый объект, явно указывая его тип. На самом деле это несколько избыточно. В примерах Вадима нескольких объектов разных типов не создаётся, вся конвертация происходит «на лету». Но я старался показать в несколько шагов для наглядности. Ну и в результате четвёртая строка проверяет тип нового объекта, и он предсказуемо возвращает значение «Microsoft.InternationalSettings.Commands.WinUserLanguage».
Именно это и происходит «за кадром», когда вы выполняете метод Add, указывая объект типа строка.
В теории, точно так же оно бы работало и для метода «Remove». Но происходит заковыка, связанная с тем, что новый объект не идентичен тому, что уже есть в коллекции. И если пытаться удалить новый объект из коллекции, то объект, который указан как удаляемый, в коллекции не находится. В результате попытка удаления завершается с ошибкой.
Поэтому приходится не создавать новый объект и удалять его, а выбирать его непосредственно из коллекции по фильтру — как и делает Вадим. Считайте это нюансами реализации конкретных коммандлетов. (В общем случае я бы ожидал, что создаваемый объект будет идентичен тому, что в коллекции. Свойства-то у них совпадают).
Но в любом случае, в вызовах обоих методов (Add и Remove) используется именно объект типа «Microsoft.InternationalSettings.Commands.WinUserLanguage», а не строка.
artem
Почему в первом случае строка в кавычках, я объявнил выше. (Без кавычек не получится, потому что парсер не поймёт, чего вы от него хотите. Метод .Add ожидает объекта, а текст без кавычек — это ещё не объект. И однозначно превратить текст в объект без кавычек в этом случае не получается).
А во втором случае Вадим сделал то, чего я делать настоятельно не рекомендую именно из дидактических соображений. Он пропустил то, что технически можно пропустить. Хотя это добавляет неоднозначности.
На самом деле во втором случае там тоже строка. Просто когда вы указываете строку как значение для параметра, PowerShell понимает, что надо превратить этот текст в строку. По-хорошему всегда надо указывать кавычки, но работает и без кавычек.
Вот так. В случае метода без кавычек не работает, а в случае значения параметра работает. (Ну, если не встречаются пробелы или спецсимволы). Поэтому, конечно, всегда стоит использовать кавычки, чтобы не запутывать неопытных пользователей.
А ещё надо указывать имена параметров. Вот так было бы совсем хорошо.
artem
Опишите, пожалуйста, задачу. Потому что я пока не понимаю, что именно вам не нравится.
Если вы хотите добавить, и не знаете точно, как называется то, что вы хотите добавить — воспользуйтесь ссылкой Вадима. (Я не дам руку на отсечение, что коды всегда совпадают. Потому что не знаю, как именно работает внутри превращение строки к объекту типа «Microsoft.InternationalSettings.Commands.WinUserLanguage». Но в общем, думаю, что предположение Вадима недалеко от истины.)
Если вы хотите удалить — ну, вы, наверное знаете, что именно хотите удалить?
gryzun
Тут в прошлой записи был задан интереснейший вопрос.
Расскажу.
Вот поэтому и не использую. Использование «учётной записи» может привести к неоднозначным результатам.
В моей шараге мне вложили в голову золотую мысль, можно сказать правило:
«Если выполнение программы приводит к неоднозначному результату, который трудно или невозможно предсказать, то эта программа плоха, а программист, её написавший — плохой программист.»
Использование учётной записи M$ есть жирный пример такой программы, пользование которой всегда вызывает сомнения в результатах работы. То есть неоднозначный и/или труднопредсказуемый результат.
Произошла ли синхронизация? Какие данные точно синхронизируются, а какие нет? Какие приложения настроили использование облака для синхронизации, а какие нет? Синхронизируются ли параметры? А синхронизируются ли «старые» настройки и параметры? Синхронизируются? А какие из них не синхронизируются? А настройки реестра? А приложения? А почему пропал флажок «автоматический вход»? Что это за новый «пин-код»? Какие данные передаются на сервера? С какой периодичностью? С какой целью? Какие файлы отправляет в M$ защитник и как они соспоставляются с учётными записями? Сколько ресурсов (почему так много???) используют службы телеметрии и обновлений? Когда в следующий раз я увижу рекламу рекомендации в пуск? И вообще, могут ли предложить мне эти рекомендации что нибудь внятное? Не произойдёт ли через все эти «фичи» и учётные записи утечка слишком чувствительной информации?
Я уж не говорю про политику сбора и использования «персонифицированной информации» (и ключей шифрования, хех), в этом деле вообще никто никогда не сознается, слишком большие деньги (и не только деньги. В основном не деньги.) на кону. Тут правды не ищите, её здесь нет. Однозначность соответствующая.
Существование таких учёных записей есть результат притока в сеть малообразованного (самое интересное, даже не всегда платёжеспособного. Угадайте, чем такие платят.) населения земли из-за экстенсивной политики расширения сетей и «сервисов». Вот за них в M$ и решают, что надо синхронизировать, какую кнопку надо убрать, а где без учётной записи никуда не пустят. Ну это так, лирика.
Чтобы по хорошему использовать виндовые навороты (облачные, дизайновые, системные), вводимые с 2015-го года, необходимо прочесть не один талмуд (половина из них 404, спасибо M$), и не только по «how to..» и юзабилити: крайне рекомендуется глубоко ознакомиться с текущими и запланированными корпоративным процессами, терминологией и прочим мелкомягким энтерпрайзом… И это надо как-то совместить со всеми теми знаниями(опыт и юзабилити всех прошлых версий, НЕМАЛЫЙ И НЕМАЛОВАЖНЫЙ), что были накоплены за прошлые годы, и что вот-вот могут быть ВНЕЗАПНО признаны устаревшими. А ведь кому-то в этом мире приходится быть не только » самолично опытным пользователем ПК», но и техническим специалистом. И в той области, такие вот «бесплатные» «учётные записи» с кучей свистоперделок не канают от слова совсем, там котируются немного другие материи — надёжность, отказоустойчивость, контролируемость процессов и т.д. Здравые идеи, в общем-то, очевидно, что они распространены среди тех, кто просто шарит (и среди тех, кто «шарит». сборщикам и прочим «бесам» привет).
Vadim Sterkin
Отвечу только по теме синхронизации языковых настроек. Она в целом корректно работает по моим наблюдениям, в т.ч. я не вижу жалоб в форуме на нее.
Я подспудно ожидал, что не преминут поддеть. Но здесь же я обозначил стандартные грабли. Очевидно, что если вам нужен японский язык периодически и только на одном ПК, то слать это в другие не надо.
Менее очевидно, что многократные изменения за короткий период могут давать неожиданный результат. Но это не практический, а экспериментальный сценарий.