Windows Regionseinstellungen per Script ändern
Jeder, der bereits mehrere Windows VMs deployed hat, dürfte bereits in den Genuss gekommen sein, nachträglich die Regions-Einstellungen abzuändern. Über das Userinterface funktioniert das noch relativ einfach, was ist aber, wenn man solche Einstellungen bei dutzenden VMs setzen möchte? In dem Fall wäre eine Automatisierung über ein Script die bessere Option. Allerdings macht es uns Windows nicht gerade einfach, denn eine leichte native Lösung gibt es nicht. Trotzdem möchte ich euch in diesem HowTo einen Weg zeigen, wie es trotzdem relativ gut zu bewerkstelligen ist. Da dieser Artikel relativ umfangreich ist, würde ich etwas Zeit einplanen oder direkt zum Kapitel „Die Lösung: intl.cpl und XML“ springen.
Um meine Ausgangssituation zu verdeutlichen, hier eine kurze Beschreibung: Wir deployen massenhaft Windows Maschinen über Templates, welche alle einheitlich mit dem „en-US“ Einstellungen gesyspreped wurden. Das bedeutet, die VM bekommt bei der Provisionierung ein englisches Tastaturlayout, Zeitangabe und United States als Location. Je nachdem in welchem Land die VM erstellt wird, müssen die Angaben natürlich an die jeweiligen Gegebenheiten angepasst werden. Dafür injecten wir nach dem Deploy ein PowerShell Script, welches alle weiteren Aufgaben abarbeitet. (Stichwort: Packer und Cloudbase-Init)
Über die GUI
Bevor wir allerdings in die Welt von Powershell und XML einsteigen, möchte ich vorab klären, wie solche Settings über die Benutzeroberfläche gesetzt werden. Dazu öffnet man die Systemsteuerung -> Region und wählt dort die passenden Parameter aus. Standardmäßig werden die Einstellungen nur für den angemeldeten Benutzer getroffen. Damit man sie systemweit ausrollen kann, müssen sie noch auf den „Welcome Screen“ und den „New User accounts“ repliziert werden.
Somit werden alle neuen Benutzer mit den neuen Parametern versorgt. Hätte man diesen Schritt ausgelassen, wäre nur der angemeldete Benutzer umgestellt worden.
Über die Powershell
Nun kommen wir bereits zu dem etwas interessanteren Part. Natürlich möchte man solche Einstellungen auch mit einem CMDLET setzen können. Zum Glück bringt Windows dafür auch ein eigenes Module mit – das sogenannte „International“ Modul. Mithilfe dessen werden uns einige Befehle zur Verfügung gestellt, welche sich in Gänze hier abrufen lassen: Microsoft Technet – International
Um die selben Einstellungen zu treffen, wie wir es bereits mithilfe der GUI erledigt haben, sind folgende Befehle erforderlich:
- Setzen der Zeitzone auf die Mitteleuropäische Standard Zeit:
Set-TimeZone -Id "W. Europe Standard Time"
- Setzen der Systemweiten System Location:
Set-WinSystemLocale -SystemLocale de-AT
- Setzen der Tastaturlayout Sprache:
Set-WinUserLanguageList -LanguageList de-AT -Force
- Setzen der unter anderem Kalender- und Datumsanzeige:
Set-Culture -CultureInfo de-AT
- Setzen der Home Location des Benutzers (die Ländercodes lassen sich hier abrufen):
Set-WinHomeLocation -GeoId 0xe
Die Einstellungen erfordern einen Neustart. Danach hat man das gleiche Ergebnis, als hätte man es mit der GUI erledigt – aber leider nur fast. Denn diese Befehle setzen die Parameter nur für jenes Benutzerprofil, welches sie ausgeführt hat. Das bedeutet, dass neue Benutzer diese Settings nicht übernehmen (außer die WinSystemLocale). Somit ist diese Vorgehensweise nicht wirklich brauchbar. Einen Befehle, um das auch auf alle neuen Profile zu übernehmen, wie wir es über die GUI machen, gibt es leider nicht.
Was passiert in der Theorie?
Um vielleicht noch einen kleinen Einblick zu gewähren, was bei diesen Befehlen eigentlich passiert, möchte ich noch kurz auf die Theorie eingehen. Wie so oft werden einfach Registry Keys in die NTUSER.DAT geschrieben. Auch in diesem Fall ist es nicht anders. Setzt man mit der Powershell wie oben beschrieben die Einträge, braucht man nur einen Blick in folgende Keys zu werfen:
- Computer\HKEY_CURRENT_USER\Keyboard Layout
- Computer\HKEY_CURRENT_USER\Control Panel\International
So könnte man die Regionseinstellungen auch über eine GPO innerhalb einer Domäne steuern. Dieser Anwendungsfall ist allerdings für meine Zwecke nicht geeignet.
Die Lösung: intl.cpl und XML
Nun kommen wir aber endlich zur Lösung des Problems. Bei dem „intl.cpl“ handelt es sich im eigentlichen Sinne um den bereits bekannten Regionsrreiter in der Systemsteuerung. Diese kann man glücklicherweise auch mithilfe einer XML über ein Powershell Script füttern. Auf einer frisch provisionierten Virtuellen Maschine hätte man nun zwei Möglichkeiten: entweder man lädt die XML über ein PowerShell Script von einem Fileserver herunter oder man übergibt es einfach innerhalb des Scripts. Da ich nicht davon ausgehe, dass meine VMs von Beginn an eine funktionierende Internetverbindungen haben, ist es für mich die sicherere Variante, es innerhalb des Scripts zu übergeben.
$regionalsettings = "<gs:GlobalizationServices xmlns:gs='urn:longhornGlobalizationUnattend'> <!--User List--> <gs:UserList> <gs:User UserID='Current' CopySettingsToDefaultUserAcct='true' CopySettingsToSystemAcct='true'/> </gs:UserList> <!-- user locale --> <gs:UserLocale> <gs:Locale Name='de-AT' SetAsCurrent='true' ResetAllSettings='true'/> </gs:UserLocale> <!-- system locale --> <gs:SystemLocale Name='de-AT'/> <!-- GeoID --> <gs:LocationPreferences> <gs:GeoID Value='14'/> </gs:LocationPreferences> <gs:MUILanguagePreferences> <gs:MUILanguage Value='de-AT'/> </gs:MUILanguagePreferences> <!-- input preferences --> <gs:InputPreferences> <!--en-AU--> <gs:InputLanguageID Action='add' ID='0c07:00000407' Default='true'/> </gs:InputPreferences> </gs:GlobalizationServices>" $regionalsettings | Out-File C:\Windows\Temp\Region_de-AT.xml $regionalsettingsXML = "C:\Windows\Temp\Region_de-AT.xml" & $env:SystemRoot\System32\control.exe "intl.cpl,,/f:`"$regionalsettingsXML`"" Start-Sleep -Seconds 5 Restart-Computer -Force
Innerhalb der Variable $regionalsettings befindet sich der Code für mein XML-File. Anschließend wird im TEMP-Ordner das besagte XML aus der Variable erstellt. Wie bereits erwähnt könnte man es auch direkt von einem Fileserver herunterladen. Nun rufen wir noch das intl.cpl auf und befüttern es mit dem Pfad zu der zuvor erstellten Datei und starten das System neu. Et voilà, sowohl der bestehende Nutzer, als auch alle neuen Benutzer bekommen die richtigen Regionseinstellungen ausgeliefert.
Eine Schwachstelle gibt es allerdings, wofür ich noch keine passende Lösung gefunden habe: Bereits existierende User (mit Ausnahme jenen, der das Script ausführt) werden nicht umgestellt. Hier müsste ich dementsprechend manuell Hand anlegen und das ist mir persönlich ein Dorn im Auge. Wenn ich einen Weg finde, wird dieser Post aktualisiert – versprochen 🙂
UPDATE: Wir bereits in den Kommentaren kurz angemerkt, habe ich eine Lösung für das angesprochene Problem gefunden: Windows Regionseinstellungen per Script ändern – Teil 2
Super Artikel. Habe eine änliches Procedere für meine Task Sequence. Hast du schon eine Lösung für die Schwachstelle schon gefunden? Habe das gleiche Problem auch.
Danke für das Feedback, freut mich zu hören, dass es jemanden weiterhilft! Ich sag einmal jein: Ich habe eine Lösung für das Problem gefunden, es ist aber eine für mich nicht perfekte Lösung. Folgende Vorgehensweise: Nachdem ich die intl.cpl über das Script ausgeführt habe, wurden die Einstellungen korrekt gesetzt außer für bestehende Benutzer. Bei meinem Deployment gibt es genau zwei Benutzer: cloudbase-init: Mit dem User werden alle nachgelagerten Powershell Scripts ausgeführt Administrator: Hier werden die Regionseinstellungen nicht gesetzt. Jetzt gehe ich einfach her, und lade mir den Administrator HKEY_USERS Hive (dafür benötigst du die SID des Users) und erstelle unter… Weiterlesen »
https://schweigerstechblog.de/windows-regionseinstellungen-per-script-aendern/#comment-76