Say you have a need to add a registry key into the 64-bit registry hive but you’re stuck with doing it from a vbscript running in a 32-bit process. For example SCCM always runs vbscript in a 32-bit process, even on a 64-bit Windows machine! If you try this normally Windows 7 64-bit will redirect the key to the virtual 32-bit hive. So running in a 32-bit process if we want to add a key to
HKLM\Software\ you will find it will always end up in
HKLM\Software\Wow6432Node\ no matter what you do.
I couldn’t find a way to do it directly using vbscript in the short time I spent looking into it, but I did find a sneaky indirect way. My method is to execute a command to add a scheduled task into Windows that will do it for you!
I’ve written a bit of vbscript which will create a run-once self-deleting scheduled task that can be used to run a command such as
REG ADD which will be running as a 64-bit process, assuming you use it on Windows x64. The only thing you need to have is admin rights, the rest will happen automatically.
You could use it for all sorts of things, like getting access to an area of the OS that needs LOCAL SYSTEM rights for example. You must remember though it’s just for firing off a command that you don’t need a response from. You need to test whatever you fire-off because you can’t check what you’ve done from within the script!
To use the vbscript function you need to call the
CreateJob() function and pass it the command that you want to run. For example if we call the following…
CreateJob("REG ADD HKLM\Software\64BitKey /v 64BitValue /d 64BitData /f")
…then my function will create a scheduled task that runs the command between the quotes 1 minute after it is created. Once the task completes it will then delete itself automatically, whether it succeeds or fails. The command in my example will create a registry key
HKLM\Software\64BitKey with a new REG_SZ value
64BitValue which has the string data
I’ve commented the code as best I can. Basically the scheduled task that is created will have a unique name every time due the use of a guid string for the name. The task will work on XP, Vista and Windows 7, and on 32-bit or 64-bit, but it will always be in ‘XP mode’ so that it will delete itself after it is executed.
Here’s a slightly generic example of use:
Adding a registry key
KeyName that has a DWORD value of
CreateJob("REG ADD HKLM\Software\RegKey /v KeyName /t REG_DWORD /d 0xFF /f")
Notice here the use of
0xFF to specify the hex value, and the
/f switch to force the key to add. If we don’t use
/f and the value is already there then the command will perpetually wait for a response.
Here are some screenshots proving it works…
For more info about the
REG ADD command either go here, try typing
reg add /? in the command-line, or you could Google it.
The right way to do my precise example is use WMI as mentioned here but my way is more flexible because you can do other stuff like run apps in a 64-bit process as well…
Anyway, here’s my function. Have fun with it, and don’t forget, you’re running as the SYSTEM account when you use this, so please be careful!
Function CreateJob(strCommand) Const SHELL_WAIT = True Const SHELL_HIDE = 0 CreateJob = False ' Get date & time 1 minute in advance ' And it must be at least 1 minute ' Source: w3schools, & mikeblas on hardforum.com Dim strDateTime : strDateTime = DateAdd("n", 1, Now()) Dim strDate : strDate = LEFT(strDateTime, InStr(strDateTime, " ")-1) Dim strTime : strTime = MID(strDateTime, InStr(strDateTime, " ")+1) ' define the command we will run to create the once-only scheduled task ' uses a new guid for the name each time so it will be a unique task Dim strJobCmd : strJobCmd = "schtasks.exe /Create /TN " & _ getGuid & " /RU SYSTEM /ST " & _ strTime & " /SD " & _ strDate & " /SC ONCE /TR """ & _ strCommand & """" ' on Vista/Win7 must create task as XP-readable type using /V1 ' this is so it will delete itself propely (bug in schtasks) using /Z If onVistaWin7 Then strJobCmd = strJobCmd & " /Z /V1" WScript.echo strJobCmd Dim oJobShell : Set oJobShell = CreateObject("WScript.Shell") Dim jobRet : jobRet = oJobShell.Run(strJobCmd, SHELL_HIDE, SHELL_WAIT) If jobRet = 0 Then CreateJob = True ' here we tried to make the task and get the result to a variable ' if the return is non-zero then the creation of the task errored Set oJobShell = Nothing End Function Function getGuid ' this functions gets a unique guid and returns it as a string Dim TypeLib : Set TypeLib = CreateObject("Scriptlet.TypeLib") getGuid = Left(CStr(TypeLib.Guid),38) ' above line also removes some strageness at the end Set TypeLib = Nothing End Function Function onVistaWin7 ' this function returns true on Vista or above (incl. Srv2008) Dim colOSver, objOSver onVistaWin7 = False Set colOSver = GetObject("WinMgmts:root\cimv2").ExecQuery _ ("Select Version from Win32_OperatingSystem") For Each objOSver In colOSver If Left(objOSver.Version,1) >= 6 Then onVistaWin7 = True Next Set colOSver = Nothing End Function