Home > Programming > Calling a 32-bit System Command from a Script in x64 Windows

Calling a 32-bit System Command from a Script in x64 Windows

June 20th, 2009

64-bit ScriptingLet’s say you’ve written a little 32-bit script that calls a Windows command such as nbtstat. When you try to run the script in x64 Windows, you get an annoying “File not found” error – even though you can see the command sitting in the \Windows\system32 folder.

What’s going on here?

x64 version of Windows have two system folders: \Windows\system32 and \Windows\SysWOW64.

The 32-bit commands are in the SysWOW64 folder, and the 64-bit commands are stored in the system32 directory. x64 Windows looks in system32 by default when you call a command line function, since it tries to call the 64-bit goodies (no, that’s not backwards!).

So, you might think that you can simply change your script to explicitly call, for example, \Windows\system32\nbtstat instead of just nbtstat, and you’ll be off and running, right? Wrong.

Fortunately, there is an easy way to solve this little problem…

The reason that calling your command line function with the full path doesn’t work is because Windows has a lovely little built-in “auto-redirect” to the SysWOW64 (32-bit stuff) folder. Since your script is 32-bit, the redirect kicks in.

If you’re writing an honest-to-god Windows application, there is a call you can make to disable this automatic redirection (Wow64DisableWow64FsRedirection). However, this won’t work for a simple Ruby script, such as my LAN Scanning Tool. In fact, this is exactly where I ran into this problem the other day. I hadn’t tested my little tool on an x64 version of Windows. After installing the x64 Windows 7 Release Candidate, I discovered the LANscan.exe app would throw the error I mentioned above.

Lucky for us, it is really easy to fix this little problem.

It turns out that x64 Windows includes a “virtual folder” called \Windows\sysnative. The sysnative folder cannot been seen in Explorer, or even from the command line. If you call a command in sysnative from within a normal application, it won’t work. But, if you call \Windows\sysnative\nbtstat from within a script – such as my Ruby-based LANscan app, Windows will automatically redirect the call to the \Windows\system32 directory instead of defaulting to the 32-bit stuff in \Windows\SysWOW64. Thus, your 32-bit app can access functions in the native 64-bit “system32” directory! Cool, eh?

Note that this redirection trick isn’t necessary for all system calls. For example, ping exists as both a 32-bit and 64-bit executable. In that case, redirection isn’t necessary. However, in my case, nbtstat is only available as a 64-bit function in \Windows\system32, and NOT as a 32-bit executable in \Windows\SysWOW64. That’s why I was getting the “not found” error: because Windows was automatically redirecting my call to the 32-bit SysWOW64 directory.

In order to make your script work on both 32-bit and 64-bit Windows, you might want to do something like the following in your scripts:

# Check for x64, call appropriate command
if File.directory? '\\Windows\\SysWOW64' then
  result = `\\Windows\\sysnative\\nbtstat.exe -A #{putername}`
else
  result = `nbtstat.exe -A #{putername}`
end

Of course, the above example is written in Ruby, so you’ll have to customize it for your chosen language. But the general idea remains the same:

  1. Check for \Windows\SysWOW64
  2. If the directory exists, you are running on x64 Windows, so call the command with the full \Windows\sysnative path
  3. If the directory does not exist, you’re running on 32-bit Windows, so call the command with no path and let Windows handle it

Pretty simple, eh?

I’ve released v1.3 of my LAN Scanning Tool, which you can download for free. It now fully supports XP, XP x64, Vista, Vista x64, Win7, and Win7 x64.

Have fun!

Programming , ,

Shortlink:

  1. kamleong
    June 15th, 2010 at 17:28 | #1

    Thanks for the excellent example and explanation on the Windows\sysnative virtual folder

  2. kamleong
    June 15th, 2010 at 17:45 | #2

    You mentioned that “The 32-bit commands are in the system32 folder, and the 64-bit commands are stored in the SysWOW64 directory. x64 Windows looks in SysWOW64 by default when you call a command line function.”. I read somewhere else that SysWOW64 directory actually stores the 32-bit (instead of 64-bit) binaries. That only exist on a x64 Windows. The system32 folder always stores the “native” binary of the OS.

    • June 15th, 2010 at 21:41 | #3

      D’OH! You are absolutely correct. I’ll update the article. Thanks!!

  3. Mike Farmwald
    December 12th, 2010 at 09:20 | #4

    Thanks for the note.

    I had to add “C:\\Windows” as I was running Ruby from another drive than C.

    How do you make the distributable .exe for a ruby program? Also, do you share the source code for the LAN Scanning Tool? I just wrote something similar and was curious.

    Thanks.

  4. CheHo Kim
    October 31st, 2014 at 11:23 | #6

    Excellent information!! I found this solution full day. Thank you. Important point is 32bit or 64bit OS system.

  5. Wayne Phipps
    May 5th, 2015 at 15:02 | #7

    I was having the issue discussed when trying to run qwinsta, never knew about the \windows\systemnative path and thanks to this crucial info, this article resolved the issue. Many thanks

  6. Nitin
    July 3rd, 2015 at 09:09 | #8

    Running executables in System32 folder does not work with IIS Server. It works with Visual Studio. Any ideas why? I am able to run executables in SysWOW64 folder using both IIS and Visual Studio? Any solution or alternative?

  7. Boris
    September 21st, 2015 at 11:06 | #10

    :: Thank you for the article!
    :: For some reason in a batch file it depends how the batch file is called.
    :: Here is what seems to be working for me:
    :: —————————-
    set Log=”%~dp0%~n0.log”
    set L=^>^>%LOG% 2^>^&1& :: Merge Standard Output and Standard Error

    set nbt_call=%comspec% /C &::
    if exist “%windir%\sysnative\nbtstat.exe” set nbt_call=%windir%\sysnative\&::

    %nbt_call%nbtstat.exe -a -n %L%

    exit
    :: —————————-

  1. No trackbacks yet.