A way to run a 64-bit process from a 32-bit script (like add a registry key)

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!

Click here to see my function on pastebin

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 64BitData.

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 HKLM\Software\RegKey with KeyName that has a DWORD value of 000000FF:
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…

1. running the script in an Admin CMD prompt running in 32-bit mode on a 64-bit machine

2. proving the script is running as a 32-bit process

3. showing the scheduled task about to run

4. and finally the registry key after it has been created, definitely in the 64-bit hive!

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
  • Dave

    This is exactly what I need but I can’t get the code to run. How exactly would you call the CreateJob function? I thought it would go something like this? cscript test.vbs CreateJob(“REG ADD HKLM\Software\RegKey /v KeyName /t REG_DWORD /d 0xFF /f”)

    Do we need to change this line – CreateJob = False to be True?

    Thanks for your effort creating this. It looks very good.

  • NiXC

    Hi Dave, thanks for your approval of my script. I’ve learned that there is actually a nicer way to do what I tried to do using WMI which is much easier than using a scheduled task, so when I get to grips with that I will post about it too.
    Anyway what you need to do is paste all my code in a text file, then in a bit of whitespace above my code write the line that calls the CreateJob function. Save that file as a .vbs and then run the way you’ve suggested but without the createjob bit, e.g.: cscript test.vbs

    test.vbs look a bit like this:
    ‘ beginning of test.vbs
    ‘ below line calls the createjob function to add a registry key using a scheduled task
    CreateJob(“REG ADD HKLM\Software\RegKey /v KeyName /t REG_DWORD /d 0xFF /f”)

    ‘ then the function that we’re calling
    Function CreateJob(…
    ‘ all the functional code goes here

    ‘end of test.vbs

  • Dave

    Thanks for your help. I’m getting much closer. I’m located in the United States and our date/time format appears to be causing me trouble. I was able to get the command to run but it never created the task.

    I pasted the text from the vbscript output as I thought it should work and wanted to see if any error messages were shown. This is how I found the date/time issue. I pasted it here for reference. I had to remove the AM on the time issue and change the date to the correct format. Which for the US is mm/dd/yyyy. I haven’t had much time to modify the script for US use but will post the changes when/if I can figure it out.

    Thanks again for posting this. I’m looking forward to be able to use this script to deploy my Windows 7 64 bit operating systems in SCCM,

    schtasks.exe /Create /TN {CBA45F98-668F-4F5B-AF6F-78A067
    6319AA} /RU SYSTEM /ST 11:45:15 AM /SD 9/30/2011 /SC ONCE /TR “reg add HKEY_LOCA
    L_MACHINE\Software\Test /t REG_SZ /d 1 /f” /Z /V1
    ERROR: Invalid argument/option – ‘AM’.
    Type “SCHTASKS /CREATE /?” for usage.

    schtasks.exe /Create /TN {CBA45F98-668F-4F5B-AF6F-78A067
    6319AA} /RU SYSTEM /ST 11:45:15 /SD 9/30/2011 /SC ONCE /TR “reg add HKEY_LOCAL_M
    ACHINE\Software\Test /t REG_SZ /d 1 /f” /Z /V1
    ERROR: Invalid Start Date (Date should be in “mm/dd/yyyy” format).

    schtasks.exe /Create /TN {CBA45F98-668F-4F5B-AF6F-78A067
    6319AA} /RU SYSTEM /ST 11:45:15 /SD 09/30/2011 /SC ONCE /TR “reg add HKEY_LOCAL_
    MACHINE\Software\Test /t REG_SZ /d 1 /f” /Z /V1
    INFO: The schedule task “{CBA45F98-668F-4F5B-AF6F-78A0676319AA}” will be created
    under user name (“NT AUTHORITY\SYSTEM”).
    SUCCESS: The scheduled task “{CBA45F98-668F-4F5B-AF6F-78A0676319AA}” has success
    fully been created.

  • Tomtom

    Obviously you’ve never heard of WMI. Read this:
    http://msdn.microsoft.com/en-us/library/aa393067%28VS.85%29.aspx

  • Thanks for that my anonymous friend, my googling wasn’t very productive when I went looking for a solution to my problem, but now you’ve helped me with that I’ve updated my post. Nice one.