Enable Clock on Task Bar for Windows XP and 2003

by Jeremy Saunders on May 10, 2009

Microsoft made it a real challenge to automate the enabling of the Clock on the taskbar. Some clever people worked out how this can be achieved several years ago by manipulating certain bits of the Settings binary value under the “Stuckrects2” registry key. However, it would only take effect on the 2nd logon, because the Stuckrects2 key is only created on the first logoff for a new user profile. I’ve simply extended an earlier script, written by Jeff Durbin, to create the Stuckrects2 key structure and set the Settings value to a default value during the first logon. This then allows us to manipulate the value as intended so that we can ensure the task bar Clock is displayed for all new user logons.

Enjoy!


‘================================================================================

‘ Release 1.2
‘ Modified by Jeremy@jhouseconsulting.com 23rd April 2009.

‘ Original Script written by jeffdurbin at gmail dot com on 24th January 2003.’

‘ COMMENT: In a Terminal/Citrix Server environment, the administrator usually
‘ tightly controls the user environment using System or Group Policies.
‘ Policy settings make changes to registry values that are reflected in
‘ the user’s environment. Unfortunately, some of the common settings,
‘ such as those that affect the Taskbar, are not controllable via policy.
‘ Examining the registry value that determines the Taskbar’s configuration
‘ reveals the problem: The settings are lumped into a binary key. In the
‘ case of the Taskbar, 4 bits of byte 9 (for Win2K and above) determine
‘ which of the Taskbar’s options are enabled. This is a problem, as System
‘ and Group Policies do not give us a mechanism for changing a single bit
‘ within a byte. Take the clock, for example. I routinely have customers
‘ that ask me to either turn the clock ON for all users, or turn the clock
‘ OFF for all users. This is not a problem for users that have never
‘ logged on and don’t have a Terminal Server profile. I modify the
‘ Default User profile on the Citrix servers using REGEDT32 and set
‘ the options the way I want them. I’m out of luck for users with roaming
‘ profiles that already exist, however; because their profiles already
‘ exist, they never receive the settings I’ve made in the Default User
‘ profile. So the question becomes: how do you change the settings for
‘ users with existing profiles?
‘ One way would be to use REGEDT32 to load the NTUSER.DAT registry
‘ hive for each user and make the change. That’s fine if you have 10
‘ users, but if you’ve got 500, that’s not practical. Obviously, you
‘ want to make a change as the user logs in. The first question to
‘ resolve is, what bits need to be changed? The bits and their functions
‘ are as follows:

‘ Bit 1 (from right): on = auto hide
‘ Bit 2 (from right): on = always on top
‘ Bit 3 (from right): on = show small icons in start menu
‘ Bit 4 (from right): on = hide clock

‘ Auto Always Show Small Hide
‘ Binary Dec Hex Hide On Top Icons Clock
‘ —————————————————-
‘ | 00000000 00 00 | | | | |
‘ | 00000001 01 01 | x | | | |
‘ | 00000010 02 02 | | x | | |
‘ | 00000011 03 03 | x | x | | |
‘ | 00000100 04 04 | | | x | |
‘ | 00000101 05 05 | x | | x | |
‘ | 00000110 06 06 | | x | x | |
‘ | 00000111 07 07 | x | x | x | |
‘ | 00001000 08 08 | | | | x |
‘ | 00001001 09 09 | x | | | x |
‘ | 00001010 10 0A | | x | | x |
‘ | 00001011 11 0B | x | x | | x |
‘ | 00001100 12 0C | | | x | x |
‘ | 00001101 13 0D | x | | x | x |
‘ | 00001110 14 0E | | x | x | x |
‘ | 00001111 15 0F | x | x | x | x |
‘ | ————————————————–

‘ SINGLE OPTIONS:
‘ 08 = No Settings Enabled
‘ 09 = Auto Hide
‘ 00 = Show Clock
‘ 0A = Always on Top
‘ 0C = Show small icons in Start Menu

‘ MULTIPLE OPTIONS:
‘ 01 = Auto Hide and Show Clock
‘ 02 = Always on Top and Show Clock
‘ 03 = Always on Top and Auto Hide and Show Clock
‘ 04 = Show small icons in Start Menu and Show Clock
‘ 0E = Always on Top and Show small icons in Start Menu
‘ 0F = Always on Top and Auto Hide and Show small icons in Start Menu
‘ 06 = Always on Top and Show small icons in Start Menu and Show Clock
‘ 07 = All Options Enabled
‘ 0B = Always on Top and Auto Hide
‘ 0D = Auto Hide and Show small icons in Start Menu

‘ Writing a script to change those bits is simple. Unfortunately,
‘ if you run the script during logon, the changes aren’t reflected
‘ on the Taskbar because Explorer has already loaded. You might think
‘ that the changes would show up at the next login, but that’s not
‘ the case; it seems that that the settings revert to those stored
‘ in the profile. You could kill Explorer and restart it, but that
‘ wouldn’t be a very nice login for the users.
‘ The answer is to run the script -before- Explorer starts. To do
‘ this, follow these instructions*:

‘ 1. Save this script to your Winnt\system32 folder
‘ 2. Open winnt\system32\usrlogon.cmd
‘ 3. Add the following line after the @Echo off line:

‘ %systemroot%\system32\SetTaskBarOptions.vbs

‘ That’s it. Now, when a user logs in, the script will run and set
‘ the options before Explorer runs, so the settings will show up
‘ immediately.

‘ * These instructions are for Terminal Servers. A similar technique
‘ can be used on non-TS machines (which don’t use USRLOGON.CMD).
‘ At HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon,
‘ there is a value called ‘UserInit’ which references an executable
‘ called USERINIT.EXE. You can replace the reference to USERINIT.EXE
‘ with a reference to a batch file (say, USERINIT.CMD). The batch
‘ file contents could be:

‘ @echo off
‘ cls
‘ SetTaskBarOptions.vbs
‘ userinit

‘ USAGE: This script relies on WMI, which is included with Win2K and above.

‘ To configure the options, modify the variables below the line that
‘ reads: ‘*************** OPTIONS ARE SET HERE ***************
‘ For example, I prefer the following configuration: show clock, always
‘ on top, do not hide taskbar, show small icons. To achieve this result,
‘ I need to set 1 bit (always on top), and clear 3 bits (auto hide
‘ taskbar, hide clock, show small icons). You simply add the 4 constants
‘ to the appropriate variable: intBitsToSet or intBitsToClear.
‘ The registry key is called StuckRects2 in Windows 2000 and above.

‘ IMPORTANT: Usually the Stuckrects2 key is only created when the user logs off for
‘ the first time with a new profile. Therefore these settings would only
‘ take place after the second login. However, as you will see, this
‘ script will create a default key and value, and populate it with a
‘ typical default value to start with.

‘ This is typically what the default value is after the first logoff…
‘ Settings = hex:28,00,00,00,ff,ff,ff,ff,0a,00,00,00,03,00,00,00,3c,00,00,00,1e,00,00,00,fe,ff,ff,ff,e4,03,00,00,02,05,00,00,02,04,00,00

‘ This is what we change it to. Notice the 9th hex value.
‘ Settings = hex:28,00,00,00,ff,ff,ff,ff,02,00,00,00,03,00,00,00,3c,00,00,00,1e,00,00,00,fe,ff,ff,ff,e4,03,00,00,02,05,00,00,02,04,00,00

‘ This “simple” change enables the clock on the task bar.

‘================================================================================

Option Explicit

Dim objReg, intBitsToClear, intBitsToSet, strComputer, strKeyPath, strKeyRoot
Dim strValue, strValueData, arrTemp, item, arrValueData, Return, i, blnDebug
Dim intDecimalValue, StdOut

Const HKEY_CURRENT_USER = &H80000001
Const cAutoHideTaskbar = 1
Const cAlwaysOnTop = 2
Const cShowSmallIcons = 4
Const cHideClock = 8

‘*************** OPTIONS ARE SET HERE ***************

intBitsToSet = cAlwaysOnTop
intBitsToClear = cAutoHideTaskbar & cHideClock & cShowSmallIcons
‘ These options will set the 9th value to 02 (00000010), which is
‘ Always on Top and Show Clock

‘****************************************************

Set StdOut = WScript.StdOut
strComputer = “.”
strKeyRoot = “HKCU\”
strKeyPath =”SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Stuckrects2″
strValue = “Settings”
strValueData = “28,00,00,00,ff,ff,ff,ff,0a,00,00,00,03,00,00,00,3c,00,00,00,1e,00,00,00,fe,ff,ff,ff,e4,03,00,00,02,05,00,00,02,04,00,00”
blnDebug = False

Set objReg=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\” & _
strComputer & “\root\default:StdRegProv”)

‘ New profiles will not contain the key and value, so we need to create them, using
‘ typical default data to start with.
If NOT RegKeyExists(strKeyRoot & strKeyPath) Then
Return = objReg.CreateKey (HKEY_CURRENT_USER,strKeyPath)
If blnDebug Then
If (Return = 0) And (Err.Number = 0) Then
Wscript.Echo “Create the ” & strKeyPath & ” key.”
Else
Wscript.Echo “Could not create the ” & strKeyPath & ” key.”
End If
End If
End If
If NOT RegValueExists(strKeyRoot & strKeyPath & “\” & strValue) Then
‘ This is tricky to add because we need to present the data to the SetBinaryValue method
‘ as an array of strings, each representing an integer between 0 and 255. So we first
‘ need to convert the string of hex values into an array of integers.
arrTemp = Split(strValueData,”,”)
For i = 0 to ubound(arrTemp)
intDecimalValue = HexToDec(arrTemp(i))
If blnDebug Then
wscript.echo “Array Element ” & i & “: ” & intDecimalValue
End If
If IsArray (arrValueData) Then
ReDim Preserve arrValueData(uBound(arrValueData) + 1)
Else
ReDim arrValueData(i)
End If
arrValueData(i) = intDecimalValue
Next
If blnDebug Then
For i = 0 to uBound(arrValueData) – 1
StdOut.WriteLine “Array Element ” & i & “: ” & arrValueData(i)
Next
End If
Return = objReg.SetBinaryValue (HKEY_CURRENT_USER, strKeyPath, strValue, arrValueData)
If blnDebug Then
If (Return = 0) And (Err.Number = 0) Then
Wscript.Echo “SetBinaryValue succeeded.”
Else
Wscript.Echo “SetBinaryValue failed. Error = ” & Err.Number
End If
End If
End If

‘ Read in the Binary value and set the required options.
Return = objReg.GetBinaryValue (HKEY_CURRENT_USER, strKeyPath, strValue, arrValueData)
If blnDebug Then
For i = 0 to uBound(arrValueData)
StdOut.WriteLine “Array Element ” & i & “: ” & arrValueData(i)
Next
End If

If (Return = 0) And (Err.Number = 0) Then

If ubound(arrValueData) > 0 Then
arrValueData(8) = arrValueData(8) OR intBitsToSet
arrValueData(8) = arrValueData(8) AND (NOT(intBitsToClear))

Return = objReg.SetBinaryValue (HKEY_CURRENT_USER, strKeyPath, strValue, arrValueData)
If blnDebug Then
If (Return = 0) And (Err.Number = 0) Then
Wscript.Echo “SetBinaryValue succeeded”
Else
Wscript.Echo “SetBinaryValue failed. Error = ” & Err.Number
End If
End If

‘ Set: Byte = Byte OR cShowSmallIcons
‘ Clear: Byte = Byte AND (NOT(cShowSmallIcons))
‘ Check: if ((Byte AND cShowSmallIcons) = cShowSmallIcons)

End If
End If

Set objReg = Nothing
Set StdOut = Nothing

WScript.Quit(0)

Function RegKeyExists(ByVal sRegKey)
‘ Returns True or False based on the existence of a registry key.
Dim sDescription, oShell
Set oShell = CreateObject(“WScript.Shell”)
RegKeyExists = True
sRegKey = Trim (sRegKey)
If Not Right(sRegKey, 1) = “\” Then
sRegKey = sRegKey & “\”
End If
On Error Resume Next
oShell.RegRead “HKEYNotAKey\”
sDescription = Replace(Err.Description, “HKEYNotAKey\”, “”)
Err.Clear
oShell.RegRead sRegKey
RegKeyExists = sDescription <> Replace(Err.Description, sRegKey, “”)
On Error Goto 0
Set oShell = Nothing
End Function

Function RegValueExists(sRegValue)
‘ Returns True or False based of the existence of a registry value.
Dim oShell, RegReadReturn
Set oShell = CreateObject(“WScript.Shell”)
RegValueExists = True ‘ init value
On Error Resume Next
RegReadReturn = oShell.RegRead(sRegValue)
If Err.Number <> 0 Then
RegValueExists = False
End if
On Error Goto 0
Set oShell = Nothing
End Function

Function HexToDec(strHex)
‘ This function converts a hexadecimal value represented by a string into a decimal value.
‘ http://www.sonofsofaman.com/hobbies/code/hextodec.asp
dim lngResult
dim intIndex
dim strDigit
dim intDigit
dim intDecimalValue
lngResult = 0
for intIndex = len(strHex) to 1 step -1
strDigit = mid(strHex, intIndex, 1)
intDigit = instr(“0123456789ABCDEF”, ucase(strDigit))-1
if intDigit >= 0 then
intDecimalValue = intDigit * (16 ^ (len(strHex)-intIndex))
lngResult = lngResult + intDecimalValue
else
lngResult = 0
intIndex = 0 ‘ stop the loop
end if
next
HexToDec = lngResult
End Function

Jeremy Saunders

Jeremy Saunders

Technical Architect | DevOps Evangelist | Software Developer | Microsoft, NVIDIA, Citrix and Desktop Virtualisation (VDI) Specialist/Expert | Rapper | Improvisor | Comedian | Property Investor | Kayaking enthusiast at J House Consulting
Jeremy Saunders is the Problem Terminator. He is a highly respected IT Professional with over 35 years’ experience in the industry. Using his exceptional design and problem solving skills with precise methodologies applied at both technical and business levels he is always focused on achieving the best business outcomes. He worked as an independent consultant until September 2017, when he took up a full time role at BHP, one of the largest and most innovative global mining companies. With a diverse skill set, high ethical standards, and attention to detail, coupled with a friendly nature and great sense of humour, Jeremy aligns to industry and vendor best practices, which puts him amongst the leaders of his field. He is intensely passionate about solving technology problems for his organisation, their customers and the tech community, to improve the user experience, reliability and operational support. Views and IP shared on this site belong to Jeremy.
Jeremy Saunders
Jeremy Saunders

Previous post:

Next post: