Hey, Scripting Guy! I know that when I run a script I can use code to determine whether the script is running under WScript or CScript. What I can’t figure out is this: how can I determine the default script host on a computer before I run a script?
— AT
Hey, AT. You know, it’s not very often that people completely stump the Scripting Guys; however, we have to admit this question posed a bit of a challenge. (OK, OK: so maybe it’s not that hard to stump the Scripting Guys; to be honest, it’s actually pretty easy. But you guys don’t need to know that.) We had no idea how to answer this question, and we knew it was going to take a lot of hard work and dedication in order to help you out with this.
But, in the face of adversity, did the Scripting Guys give up? Well, as a matter of fact we did. However, in the process of doing something totally unrelated, we accidentally stumbled upon the answer. Here, using a somewhat-roundabout methodology, is a script that will tell you the default script host on a computer:
Const HKEY_CLASSES_ROOT = &H80000000strComputer = “.”
Set objRegistry = GetObject(“winmgmts:\\” & strComputer & “\root\default:StdRegProv”)
strKeyPath = “VBSFile\Shell\Open\Command” objRegistry.GetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue
strValue = LCase(strValue)
If InStr(strValue, “wscript.exe”) then Wscript.Echo “WScript” Else Wscript.Echo “CScript” End If
As it turns out, information about the default script host is stored in the registry, although not in a particularly obvious location. What you need to do is open HKEY_CLASSES_ROOT, find the registry key VBSFile\Shell\Open\Command and then look at the default value. (The default value is an otherwise-unnamed registry value, one that shows up as (Default) in Regedit.) The value of (Default) will be the path to the script host executable (e.g., %SystemRoot%\System32\WScript.exe). In turn, the executable file tells you whether the default script host is CScript or WScript.
So how do we actually get to that value? Well, we begin by defining a constant named HKEY_CLASSES_ROOT and setting the value to &H80000000; that tells the script which registry hive we want to work with. We then connect to the WMI service on the local computer (although we could just as easily run this script against a remote machine), taking care to bind to the root\default namespace. (Most WMI scripts use the root\cimv2 namespace, but, for some reason, the System Registry Provider lives in root\default instead. Probably cheaper housing or better schools.)
After making the connection we create a variable named strKeyPath, assigning it the value VBSFile\Shell\Open\Command. At that point we’re ready to read the value from the registry.
What’s that? Didn’t we forget something? No, we didn’t forget anything. (Although now that you mention it we’re beginning to wonder if anyone turned off the stove when we left the house this morning.) You’re right that, in most WMI registry scripts, we would need to assign values to two variables, one to represent the registry key, the other to represent the desired value within that registry key. In this case, however, we don’t need to create a variable in which to store the name of the registry value. Why not? Because, technically, (Default) values don’t actually have a name; they’re just, well, the default values. What we’ll end up doing is telling the script to read a Null value from this particular registry key. That doesn’t sound like a very good plan but, fortunately, the Registry Provider will know that this means to read the (Default) value.
In fact, as long as we’re on the subject, here’s the line of code that retrieves the value for us:
objRegistry.GetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue
Because (Default) happens to have the REG_EXPAND_SZ data type we call the GetExpandedStringValue method, passing four parameters:
• |
HKEY_CLASSES_ROOT, the constant that tells the script which registry hive to work with. |
• |
strKeyPath, the variable that tells the script which registry key to work with. |
• |
vbNullString, a VBScript constant representing a Null value. This is where we would usually insert a variable representing the value name but, as we noted, this time around our value doesn’t have a name. |
• |
strValue, an “out” parameter. GetExpandedStringValue needs a place to store the value it reads from the registry; an out parameter is simply a placeholder variable where that value can be stashed. |
As soon as GetExpandedStringValue does its thing we use this line of code to change all the characters in strValue to lowercase; we do that to make it easier to determine whether the value contains a particular string or not:
strValue = LCase(strValue)
Finally, we call the InStr function, looking to see if the string value wscript.exe can be found anywhere within strValue. If it can, then we echo back the fact that the default script host is WScript; if it can’t, then that must mean the default script host is CScript:
If InStr(strValue, “wscript.exe”) then Wscript.Echo “WScript” Else Wscript.Echo “CScript” End If
So there you go, AT: now you can determine the default script host on a computer without running a script. (Yes, we know, you have to run the script that determines the default script host…but you get the point.) We hope you find this useful, and we hope everyone has learned an important lesson today: try as you might, you can’t stump the Scripting Guys.
Well, not unless you ask us a question we can’t answer. But you’ll never stump us by asking a question that we can answer.
OK: almost never.
0 comments