Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I add an Edit command to the context menu for an HTA? That way, any time I right-click an HTA file I can click Edit and then open the file in Notepad.

-- TC

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TC. You know, one of the Scripting Guys once had a friend who got a summer job baking pies in a local bakery. Admittedly, that sounds like the absolute perfect job and it was, except for one thing: this friend never actually got to eat the pies; because the pies were sold whole he didn’t get to cut himself a slice every now and then. As it turned out this was the worst possible job: perpetually surrounded by the aroma of freshly-baked pies, yet unable to eat a single bite.

We Scripting Guys can empathize with this poor pie-baking friend. After all, every day we write new scripts, yet we rarely get to use any of these scripts ourselves. We’ve written scripts for managing Active Directory, yet, for some strange reason, they won’t let us manage the Microsoft Active Directory. (Go figure.) We’ve written scripts for managing DNS servers, but we’re not allowed to put up our own DNS servers. We’re written scripts for creating charts in Excel, but they won’t let us create charts in Excel.

Well, OK, they’ll let us do that; we just don’t have anything worth charting.

But this task is different. We use HTAs all the time, and we invariably right-click an HTA and then click Edit; in turn, that opens the HTA up in Microsoft Word (or Microsoft FrontPage, depending on what we have installed on that particular machine), which is not our preferred editor for HTAs. Like you, we’d just as soon use Notepad, which means that the Scripting Guys could also benefit from a script that would add an Edit command to HTA files. You know, a script similar to this:

Const HKEY_CLASSES_ROOT = &H80000000

strComputer = "."
 
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")

strKeyPath = "htafile\Shell\Edit\Command"
objRegistry.CreateKey HKEY_CLASSES_ROOT,strKeyPath

strValue = "%SystemRoot%\system32\NOTEPAD.EXE %1"
objRegistry.SetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue

If you want to add a command to the context menu for an HTA file (and obviously you do) you first need to add a new key to the registry; in particular, you need to go to HKEY_CLASSES_ROOT and add the key htafile\Shell\Edit\Command. That’s what we do in the first half of the script. We define a constant named HKEY_CLASSES_ROOT and set the value to &H80000000; that tells the script which registry hive to work with. We then connect to the WMI service on the local computer (although this script can also be run against remote computers), binding to the StdRegProv class in the root\default namespace.

Pretty easy so far, right? We then use this line of code to assign the path (within HKEY_CLASSES_ROOT) to the new registry key to a variable named strKeyPath:

strKeyPath = "htafile\Shell\Edit\Command"

Once we’ve done that we can then use the CreateKey method to create our new key. To do this we simply call CreateKey and pass it two variables: the constant HKEY_CLASSES_ROOT and the variable strKeyPath. Or, to be more precise:

objRegistry.CreateKey HKEY_CLASSES_ROOT,strKeyPath

What’s that? What if you already have a registry key named htafile\Shell\Edit\Command? Hey, no problem. If the key already exists nothing bad will happen; the script will simply skip the CreateKey method and move to the next line of code. No error occurs if the registry key already exists.

And, yes, that is kind of nice, isn’t it?

What we have to do now is assign the actual command to be carried out (that is, “Open this file in Notepad”) to the default value of the Command key. That’s not especially hard but it is a tiny bit tricky. So maybe we should explain to you how it works.

As you know, we want HTA files to have a context menu similar to VBScript files: we want to be able to right-click an HTA file, click Edit, and then have the HTA open up in Notepad. To be honest, we weren’t 100% sure how to do that, so we simply took a peek at the default value for the VBSFile\Shell\Edit\Command key. That looks like this:

%SystemRoot%\system32\NOTEPAD.EXE %1

Will that work for HTA files as well? Hey, you’ll never know until you try, right? With that in mind, we assigned that same string to a variable named strValue:

strValue = "%SystemRoot%\system32\NOTEPAD.EXE %1"

Now we just need to assign the value of this variable to the default value for htafile\Shell\Edit\Command. Before we do that we need to keep two things in mind. First, you might have noticed that the environment variable %SystemRoot% is embedded in our command. That’s good: it means that we can enter the path to Notepad without having to know whether the Windows directory is C:\Windows or D:\Winnt or something else altogether. However, this also means that we have to configure the default value with a REG_EXPAND_SZ data type. A registry value with this data type will automatically “expand” an environment variable with the actual physical path; in other words, it will change %SystemRoot%\system32\NOTEPAD.EXE into something like C:\Windows\system32\NOTEPAD.EXE.

Is it going to be hard to give the default value a REG_EXPAND_SZ data type? Come on: if it was going to be hard do you really think the Scripting Guys would try it? All we have to do is make sure that, when we assign the value, we use the SetExpandedStringValue method.

Good point. Several of you have wondered why we keep using the generic phrase “default value” rather than using the name of the registry value we need to modify. There’s actually a good reason for that: the default value for a registry key doesn’t have a name. (It shows up as (Default) in RegEdit, but that’s just a placeholder value and is not its name.) So how can we access a registry value that doesn’t have a name? Fortunately, that turns out to be fairly easy, too: we simply don’t specify a name when we call the SetExpandedStringValue method. Take a look at the line of code where we call SetExpandedStringValue:

objRegistry.SetExpandedStringValue HKEY_CLASSES_ROOT,strKeyPath,vbNullString,strValue

Notice the four parameters: the constant HKEY_CLASSES_ROOT; the variable strKeyPath; the VBScript constant vbNullString; and the variable strValue. The secret to working with the default value for a registry key lies in using vbNullString (which simply represents a Null value) instead of a value name. When you specify vbNullString in place of the value name then you will automatically be connected to the default value.

Isn’t WMI wonderful?

Actually WMI is wonderful, but we don’t really have time to chat today. For some reason, we have a hankering for a big piece of blackberry pie.

Make that two big pieces of blackberry pie. With maybe a slice of chocolate cream pie for dessert.