Need help creating a simple VBScript to change region settings in Vista
Hi,
I need to create a couple of simple VBScripts that modify the region and time zone settings in Vista.
I must be able to execute one script to change from US to UK and then another to change back to US again. The change must take effect imediatly without having to restart at any point.
This is due to a CRM program our US sales guy is using requiring UK region and time zone settings while it syncs to our database in the UK. I just want to save him having to trawl through dialogue boxes every time he needs to sync, which will be most days.
I found some example code which I've attached. This sounds like it could be made to do what I want but it's way more complicated than what I need and I don't have enough VBScript knowledge to re-write it.
I'd be really greatful if someone could show me the basic code I need to do this.
Thanks,
David.
'********************************************************************'* Goal'* This script changes the Regional Settings in the Registry of a Win2K3 Server'*'* The script checks some things: is the server reachable, is the OS Win2K3,'* are the Regional Settings correct (i.e. equal to the values in the script.)'*'********************************************************************'* Prerequisites'* Run the script with administrative privileges'*'********************************************************************'* Changes'* Version Name Date Comment'* v.1.0 Corné Bogaarts 291204 Basic functionality works'* v.1.1 Corné Bogaarts 210305 Made script less fragile by taking up'* the settings in the script, instead of as'* a separate textfile.'* v.1.2 Corné Bogaarts 010505 Translated to English'*'* TODO: Have the script make the same changes to Current_User'*'********************************************************************Option Explicit'On Error Resume NextDim strLanguage, strNextLine, strKeyPath, strComputer, strItemDim strCollectionName, strEntryName, strValue, strSettingDim objCorrectSettings, objFSO, objSettingsFile, objReg, objWMIServiceDim objOperatingSystem, objCurrentSettingsDim arrSetting, colOperatingSystems, arrEntryNames, arrValueTypes, arrValueDim byteValue, arrItem, blCompare'*** Some constants for registry-edittingConst HKEY_USERS = &H80000003Const HKEY_CURRENT_USER = &H80000001Const REG_SZ = 1Const REG_EXPAND_SZ = 2Const REG_BINARY = 3Const REG_DWORD = 4Const REG_MULTI_SZ = 7'*** A constant for reading a fileConst ForReading = 1'* Registry-path (in HK_Users) for Default-userstrKeyPath = ".DEFAULT\Control Panel\International"strComputer = "."'*** Make 2 dictionaries and set the 'compare-mode' (necessary'*** for the comparison that we're going to make). The compare-'*** mode must be set before any data is entered into the dic-'*** tionary.Set objCurrentSettings= CreateObject("Scripting.Dictionary")objCurrentSettings.CompareMode = vbBinaryCompareSet objCorrectSettings = CreateObject("Scripting.Dictionary")objCorrectSettings.CompareMode = vbBinaryCompareFillCorrectSettings'PrintCollectionContents objCorrectSettingsSet objFSO = CreateObject("Scripting.FileSystemObject")'*** Connect to WMI (de CIMV2 namespace), necessary for most WMI-actionsSet objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _strComputer & "\root\cimv2")'*** Connect to the WMI Registry-provider, necessary for working with the RegistrySet objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _strComputer & "\root\default:StdRegProv")'* Verify the OS-version. If not Win2K3, than stop the script.'*** Win2K = 5.0, WinXP = 5.1, Win2K3 = 5.2Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")For Each objOperatingSystem in colOperatingSystems' Wscript.Echo strComputer & vbTab & objOperatingSystem.Caption & vbTab & _' objOperatingSystem.VersionIf Left(objOperatingSystem.Version, 3) <> "6.0" ThenOsNotWin2K3End IfNext'* Verify if the Regional Settings are 'Nederlands''*** Check all settings, if 1 or more is not correct, then change all settingsReadSettings strKeyPath, arrEntryNames'*** To check the script, write the collection to the screen:'PrintCollectionContents objCurrentSettings'*** Compare the current with the correct settings:blCompare = CompareSettings (objCorrectSettings, objCurrentSettings)If blCompare = True Then'*** all items are the same, so nothing has to be changedWScript.Echo "All settings are already correct."Else'*** 1 or more items not the same, so make he changesSetCorrectSettingsWriteEndMessageEnd If'*************************************************'* Sub-routines'*************************************************Sub OsNotWin2K3'* If the OS is not Win2003, then write a message to the screen and stop the script.WScript.Echo "The Operating System on this server is not Windows Server 2003." & vbCrLf & _"The script-execution will be stopped."WScript.QuitEnd SubSub FillCorrectSettings'* Fill the Dictionary with the correct settings'*** You can copy these settings from the logfile that was'*** written by the 'ReadRegionalSettings'-script.objCorrectSettings.Add "iCountry", "31"objCorrectSettings.Add "iCurrDigits", "2"objCorrectSettings.Add "iCurrency", "2"objCorrectSettings.Add "iDate", "1"objCorrectSettings.Add "iDigits", "2"objCorrectSettings.Add "iLZero", "1"objCorrectSettings.Add "iMeasure", "0"objCorrectSettings.Add "iNegCurr", "11"objCorrectSettings.Add "iTime", "1"objCorrectSettings.Add "iTLZero", "0"objCorrectSettings.Add "Locale", "00000413"objCorrectSettings.Add "s1159", ""objCorrectSettings.Add "s2359", ""objCorrectSettings.Add "sCountry", "Netherlands"objCorrectSettings.Add "sCurrency", "?"objCorrectSettings.Add "sDate", "-"objCorrectSettings.Add "sDecimal", ","objCorrectSettings.Add "sLanguage", "NLD"objCorrectSettings.Add "sList", ";"objCorrectSettings.Add "sLongDate", "dddd d MMMM yyyy"objCorrectSettings.Add "sShortDate", "d-M-yyyy"objCorrectSettings.Add "sThousand", "."objCorrectSettings.Add "sTime", ":"objCorrectSettings.Add "DefaultBlindDialFlag", "0"objCorrectSettings.Add "sTimeFormat", "H:mm:ss"objCorrectSettings.Add "iTimePrefix", "0"objCorrectSettings.Add "sMonDecimalSep", ","objCorrectSettings.Add "sMonThousandSep", "."objCorrectSettings.Add "iNegNumber", "1"objCorrectSettings.Add "sNativeDigits", "0123456789"objCorrectSettings.Add "NumShape", "1"objCorrectSettings.Add "iCalendarType", "1"objCorrectSettings.Add "iFirstDayOfWeek", "0"objCorrectSettings.Add "iFirstWeekOfYear", "2"objCorrectSettings.Add "sGrouping", "3;0"objCorrectSettings.Add "sMonGrouping", "3;0"objCorrectSettings.Add "sPositiveSign", ""objCorrectSettings.Add "sNegativeSign", "-"objCorrectSettings.Add "Nation", "176"End SubSub ReadSettings (strKeyPath,arrEntryNames)'* Read RegionalSettings from Registry and put them in a DictionaryobjReg.EnumValues HKEY_CURRENT_USER,strKeyPath,arrEntryNames,arrValueTypesFor Each strEntryName In arrEntryNames'*** This is the only Binary valueIf strEntryName = "DefaultBlindDialFlag" ThenobjReg.GetBinaryValue HKEY_CURRENT_USER,strKeyPath,strEntryName,arrValueFor Each byteValue in arrValueobjCurrentSettings.Add strEntryName, byteValueNextElse'*** These are all RegSZ value'sobjReg.GetStringValue HKEY_CURRENT_USER,strKeyPath,strEntryName,strValueobjCurrentSettings.Add strEntryName, strValueEnd IfNext'*** This is the only value that's in a sub-keystrEntryName = "Nation"objReg.GetStringValue HKEY_CURRENT_USER,strKeyPath & "\Geo",strEntryName,strValueobjCurrentSettings.Add strEntryName, strValueEnd SubSub PrintCollectionContents (strCollectionName)'* Write the contents of a collection to the screen'* Usefull for checking the scriptWScript.Echo "Subroutine 'PrintCollectionContents'"For Each strItem In strCollectionName' WScript.Echo strItem & " = " & objDictionary.Item(strItem)If strItem = "DefaultBlindDialFlag" ThenarrValue = Array(strCollectionName.Item(strItem))For Each byteValue in arrValueWScript.Echo strItem & " = " & byteValueNextElseIf strItem = "Nation" ThenWScript.Echo strItem & " = " & strCollectionName.Item(strItem)ElseWScript.Echo strItem & " = " & strCollectionName.Item(strItem)End IfNextWScript.Echo "End of subroutine 'PrintCollectionContents'"End SubFunction CompareSettings (objCorrectSettings, objCurrentSettings)'* Compare the contents of both collections'* If at least one item is not the same, then return-value = False'* otherwise it's True.'*** Rem: The value of 'DefaultBlindDialFlag' is not compared: technically more dificult as'*** they're arrays, and the values don't seem important.'*** --> can be added later' WScript.Echo "Function CompareSettings"CompareSettings = True'*** Verify if all items of A are in BFor Each strSetting In objCorrectSettingsIf NOT objCurrentSettings.Exists(strSetting) Then' WScript.Echo vbTab & strSetting & " doesn't exist"CompareSettings = FalseElse 'if so, are the values the same?If strSetting <> "DefaultBlindDialFlag" ThenIf objCurrentSettings.Item(strSetting) <> objCorrectSettings.Item(strSetting) ThenWScript.Echo vbTab & strSetting & " not equal in both Dictionaries:" & _ objCorrectSettings.Item(strSetting) & " and " & objCurrentSettings.Item(strSetting)CompareSettings = FalseEnd IfEnd IfEnd IfNext'*** Verify if all items of B are in AFor Each strSetting In objCurrentSettingsIf NOT objCorrectSettings.Exists(strSetting) Then' WScript.Echo vbTab & strSetting & " doesn't exist"CompareSettings = FalseElse 'if so, are the values the same?If strSetting <> "DefaultBlindDialFlag" ThenIf objCorrectSettings.Item(strSetting) <> objCurrentSettings.Item(strSetting) ThenWScript.Echo vbTab & strSetting & " not equal in bothDictionaries:" & _objCorrectSettings.Item(strSetting) & " and " & objCurrentSettings.Item(strSetting)CompareSettings = FalseEnd IfEnd IfEnd IfNext' WScript.Echo "CompareSettings = " & CompareSettings & "."' WScript.Echo "End of Function CompareSettings"If CompareSettings = False Then WScript.Echo "The settings in the Registry are not correct & _ and will be adjusted."End FunctionSub SetCorrectSettings'* Wite the correct settings to the Registry' WScript.Echo "Subroutine SetCorrectSettings"For Each strItem In objCorrectSettings' WScript.Echo strItem & " = " & objDictionary.Item(strItem)If strItem = "DefaultBlindDialFlag" Then' WScript.Echo "Reg_Binary"arrItem = Array(objCorrectSettings.Item(strItem))RegEditBinary strKeyPath, strItem, arrItemElseIf strItem = "Nation" Then' WScript.Echo "\Geo - Nation"RegEditSZ strKeyPath & "\Geo", strItem,objCorrectSettings.Item(strItem)Else' WScript.Echo "Reg_SZ"RegEditSZ strKeyPath, strItem,objCorrectSettings.Item(strItem)End IfNextWScript.Echo "Regional Settings adjusted."' WScript.Echo "End of subroutine SetCorrectSettings"End SubSub RegEditSZ (strKeyPath, strEntryName, strValue)'* Changing String-valued (REG_SZ) EntriesobjReg.SetStringValue HKEY_CURRENT_USER, strKeyPath, strEntryName, strValueEnd SubSub RegEditBinary (strKeyPath, strEntryName, arrValue)'* Changing Binary-valued (REG_Binary) Entries'*** SetBinaryValue needs an Array as 'value', even if there's only 1 value in itobjReg.SetBinaryValue HKEY_CURRENT_USER, strKeyPath, strEntryName, arrValueEnd SubSub WriteEndMessage'* Message on screen when script is finished.WScript.Echo "Regional Settings adjusted." & vbCrLf & vbCrLf & "REMEMBER:" & vbCrLf & _"The server needs to be restarted, before the new settings are activated."End Sub
Hi, perhaps a bit of a shortcut (and seeing as you only need two different locales), you could make all your changes for one locale, then export the following key
HKEY_CURRENT_USER\Control Panel\International
to say, US_REGIONAL.reg, then change manually to all of the UK settings, and export the same key to say, UK_REGIONAL.reg
Then, to set the US stuff, just type
regedit /s C:\RegFiles\US_REGIONAL.reg
and see if that takes immediate effect, then, to change back, use
regedit /s C:\RegFiles\UK_REGIONAL.reg
Regards,
Rob.
David
ASKER
Good thinking Rob.
Your suggestion works perfectly for the region settings but I can't get it working for the time zone.
When I manually change the time zone, it takes immediate affect and it seems to affect two lots of registry keys:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
and
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation]
However, if I import these keys into the registry with different time zone settings to those already applied, it doesn't affect the current time zone settings or change the clock until I restart the PC.
I guess this is something to do with the fact the settings are stored in HKEY_LOCAL_MACHINE instead of HKEY_CURRENT_USER, like the region settings are.
Does anyone know of a way I can change the time zone settings without having to reboot?
Thanks,
David.
David
ASKER
I've found the attached script which updates the time zone without requireing a reboot but unfortunately it doesn't seem to work in Vista, it just says "Unable to set time zone."
Does anyone know how I could get this working in Vista?
Thanks,
David.
On Error Resume NextstrComputer = "."'Change value to reflect desired GMT offset in minutes.intGMTOffset = -480Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")Set colCompSys = objWMIService.ExecQuery _ ("Select * from Win32_ComputerSystem")For Each objCompSys in colCompSys objCompSys.CurrentTimeZone = intGMTOffset objCompSys.Put_ If Err = 0 Then Wscript.Echo "Time zone set to specified value." Else Wscript.Echo "Unable to set time zone." End If Err.ClearNext
HKEY_CURRENT_USER\Control Panel\International
to say, US_REGIONAL.reg, then change manually to all of the UK settings, and export the same key to say, UK_REGIONAL.reg
Then, to set the US stuff, just type
regedit /s C:\RegFiles\US_REGIONAL.re
and see if that takes immediate effect, then, to change back, use
regedit /s C:\RegFiles\UK_REGIONAL.re
Regards,
Rob.