2

What is the best way to invoke a 32-bit command with Shell.Run in VBScript such that it will succeed on both Windows 32-bit and 64-bit operating systems?

On 64-bit, the app terminates because it's not a 64-bit process. Whilst I could use c:\windows\syswow64\cscript.exe myscript.vbs, this isn't portable to Windows 32-bit.

  • 2
    It would help if you showed us the relevant line(s) of code. – John Gardeniers Apr 7 '11 at 23:52
1

I can't reproduce the problem you're describing on my system. If I write a VBScript to invoke the 32-bit version of Notepad in %windir%\syswow64 using Shell.Run, it works just fine despite the fact that the scripting host is 64-bit and Notepad is 32-bit.

Set oShell = WScript.CreateObject("WScript.Shell")
oShell.Run "%windir%\syswow64\notepad.exe"

What 32-bit command are you trying to invoke that is failing?

  • +1, Same here... works fine. – Chris S Apr 8 '11 at 1:43
  • Except syswow64 does not exist on Windows 32-bit... so that particular example does not work. – jessicah Apr 9 '11 at 4:42
  • You said your problem only exists on 64-bit Windows. Why would a sample demonstrating the problem need to run on 32-bit Windows? The question I asked in my answer still stands. Perhaps if you posted your own script, we can analyze what's wrong. – Ryan Bolger Apr 9 '11 at 4:51
0

I realize this question is old, but I am posting an answer to it anyway because I have some specific, relevant knowledge about this and it's useful for future Googlers out there (which is how I came across it).

Microsoft provides both 32-bit and 64-bit versions of the Windows Script Host (cscript.exe and wscript.exe) on a 64-bit system, with the default being the platform-native version when a script is run. This is good news because it means you can deal with platform differences yourself without having to worry about WSH's external behavior in a 32-bit emulated environment on a 64-bit machine. If you actually want to rely on that behavior, you can manually invoke cscript or wscript from the \SysWOW64 directory, but it's usually preferable to use the native version and deal with the platform differences in your own code.

I always preface every VBScript I write with the following:

Option Explicit    'I always use this to avoid spelling errors in var names; Just my personal preference

Dim objShell :Set objShell = CreateObject("WScript.Shell")
Dim objFS :Set objFS = CreateObject("Scripting.FileSystemObject")

'Determine OS platform
Dim strPlatform :strPlatform = objShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")
If strPlatform = "AMD64" Then strPlatform = "x64"

'Set 32-bit and 64-bit filesystem paths
Dim strProgramFilesX64    'Will always be "\Program Files", regardless of platform
Dim strProgramFilesX86    'Will be "\Program Files (x86)" on 64-bit, otherwise "\Program Files" on 32-bit
Dim strSystem32X64    'Will always be "\Windows\System32", regardless of platform
Dim strSystem32X86    'Will be "\Windows\SysWOW64" on 64-bit, otherwise "\Windows\System32" on 32-bit

strProgramFilesX64 = objShell.ExpandEnvironmentStrings("%ProgramFiles%")
strSystem32X64 = objShell.ExpandEnvironmentStrings("%SystemRoot%") & "\System32"
If strPlatform = "x64" Then
    strProgramFilesX86 = objShell.ExpandEnvironmentStrings("%ProgramFiles(x86)%")
    strSystem32X86 = objShell.ExpandEnvironmentStrings("%SystemRoot%") & "\SysWOW64"
Else
    strProgramFilesX86 = strProgramFilesX64
    strSystem32X86 = strSystem32X64
End If

Note that the above code uses shell environment variables to set the platform and 64-bit paths first. This is because those variables are common to every version of Windows, but the x86-specific ones are only defined on 64-bit systems (which is backwards in my opinion).

Using this code at the beginning of your scripts makes them totally portable between platforms. You can control your own code's behavior by using the strProgramFilesX86/64 and strSystem32X86/64 variables, and they will always map to the correct locations regardless of what platform your script is running on.

So for example, if you are using objShell.Run() to launch something that you know is 32-bit software, you can always use objShell.Run(strProgramFilesX86 & "\MyApp\App.exe"), and it will correctly run from Program Files (x86) on 64-bit systems, and \Program Files on 32-bit systems.

You can also use the strPlatform variable if you need something different to happen on one platform vs. the other. For example, when I am doing software installs, and I have both a 32-bit and a 64-bit version of the software. I rename the 32-bit version to have a -x86 at the end of its filename, and likewise -x64 with the 64-bit version. That way, I can call the installer with a single line of code without caring what platform it is, like so:

objShell.Run "setup-" & strPlatform & ".exe"

This will evaluate to setup-x64.exe on a 64-bit system and setup-x86.exe on a 32-bit system.

As long as you stick to these variables, you do not need to worry about maintaining two different versions of your scripts, or what platform the target computer is running.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.