Let’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:
- Check for
\Windows\SysWOW64
- If the directory exists, you are running on x64 Windows, so call the command with the full
\Windows\sysnative
path - 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!
Thanks for the excellent example and explanation on the Windows\sysnative virtual folder
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.
D’OH! You are absolutely correct. I’ll update the article. Thanks!!
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.
I explained how I made the executable here:
http://scottiestech.info/2009/02/14/how-to-determine-the-master-browser-in-a-windows-workgroup/
And check your e-mail for the source!
Excellent information!! I found this solution full day. Thank you. Important point is 32bit or 64bit OS system.
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
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?
Hmm, I dunno. I’ve never used IIS.
:: 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
:: —————————-