Hey, Scripting Guy! Question

Hey, Scripting Guy! I just found out that Internet Explorer 7 and even Internet Explorer 8 Beta 2 allows you to have multiple home pages. This is like soooo cool. I would like to be able to write a script that uses Windows PowerShell to change the start page to the Script Center. It would be nice if I could do this remotely, but that is not a huge requirement. Can you show me how to go about doing this?

- AJ

SpacerHey, Scripting Guy! Answer

Hi AJ,

Like, I totally agree with you. Internet Explorer 8 Beta 2 is, like, totally cool, and like you, I did not realize until recently that you can have multiple home pages—and could have done so since Internet Explorer 7.

Standard disclaimer: The script today talks about editing the registry. Microsoft does not support editing the registry. If this script causes your computer to run slower or you to break out with pimples, we warned you. If your cat begins to behave erratically or your dog begins chasing the garbage truck, well these things can happen if you are not careful. Please back up your registry before proceeding to run the script. Back up everything you don't want to lose, including your stamp collection, butterfly collection, and coin collection. Put them in a box and mail that box to the Scripting Guys c/o The United States, and we will hold them for you just in case of disaster.

Disclaimer about the standard disclaimer: Don’t mail us anything. We can’t even find the sweet prescription glasses we just got in less than an hour from Lens Crafters.

The first thing you should do before working with the registry is ensure you are either working on a virtual machine that allows you to roll back changes if you wish, or ensure you have a good backup of the registry. Jerry Honeycutt has written a number of good books about the registry for Microsoft Press, as well as a number of excellent articles about the registry such as this one.

For a good overview of the registry, you can refer to this article. To explore the registry, you can use the Tweakomatic, which produces scripts in VBScript. Here is a good Sesame Script article that gives an overview of the registry. And here is the Script Center registry archive.

We decided to write a script that reads or modifies a couple of values from the registry to configure the Internet Explorer start pages. As it turns out, there are actually two registry keys that govern this behavior. The one that is documented in the Tweakomatic accepts a single string for the start page, which makes sense because traditionally you could only have a single start page. For Internet Explorer 7, it seems we added an additional registry key that will accept multiple strings (an array of strings), which in turn gives us the ability to have multiple start pages. We will be using the WMI stdRegProv class to both read and edit the registry keys. The main advantage of this technique is it gives us the ability to edit the registry remotely. In Windows PowerShell 2.0 you will be able to do this without resorting to WMI, but Windows PowerShell 2.0 is in community technology preview right now and will not be released formally for some time. Here is today’s script:

Param([switch]$get,[switch]$set,$computer="localhost")
Function Get-ieStartPage()
{
 $hkcu = 2147483649
 $key = "Software\Microsoft\Internet Explorer\Main"
 $property = "Start Page"
 $property2 = "Secondary Start Pages"
 $wmi = [wmiclass]"\\$computer\root\default:stdRegProv"
 ($wmi.GetStringValue($hkcu,$key,$property)).sValue
 ($wmi.GetMultiStringValue($hkcu,$key, $property2)).sValue
} #end Get-ieStartPage

Function Set-ieStartPage()
{
  $hkcu = 2147483649
  $key = "Software\Microsoft\Internet Explorer\Main"
  $property = "Start Page"
  $property2 = "Secondary Start Pages"
  $value = "http://www.microsoft.com/technet/scriptcenter/default.mspx"
  $aryValues = "http://social.technet.microsoft.com/Forums/en/ITCG/threads/",
  "http://www.microsoft.com/technet/scriptcenter/resources/qanda/all.mspx"
  $wmi = [wmiclass]"\\$computer\root\default:stdRegProv"
  $rtn = $wmi.SetStringValue($hkcu,$key,$property,$value)
  $rtn2 = $wmi.SetMultiStringValue($hkcu,$key,$property2,$aryValues)
  "Setting $property returned $($rtn.returnvalue)"
  "Setting $property2 returned $($rtn2.returnvalue)"
} #end Set-ieStartPage

# *** entry point to script 
if($get) {Get-ieStartpage}
if($set){Set-ieStartPage}

The registry keys we will be working with are seen here:

Image of the registry keys worked with in this article

 

The first thing we need to do is create a few command-line parameters. Two of these are switched parameters, which will allow us to control the way the script operates: get the information from the registry, or set information in the registry. The last parameter is a regular parameter that controls the target computer. We are assigning a default value for the $computer variable of localhost, which means the script will read the local registry by default. This is shown here:

Param([switch]$get,[switch]$set,$computer="localhost")

We now need to create the Get-ieStartPage function. The Get-ieStartPage function will be used to retrieve the current start page settings. To create a function we use the Function key word, and give it a name. This is seen here:

Function Get-ieStartPage()

After we use the function key word to create our function, we need to add some code to the script block. We first need to create some variables. These are the same kinds of variables you would have used when using WMI to read from the registry in VBScript. You must specify the registry hive from which you plan to query by using one of enumeration values from Table 1.

Table 1 WMI registry tree values

Name Value

HKEY_CLASSES_ROOT

2147483648

HKEY_CURRENT_USER

2147483649

HKEY_LOCAL_MACHINE

2147483650

HKEY_USERS

2147483651

HKEY_CURRENT_CONFIG

2147483653

HKEY_DYN_DATA

2147483654

In VBScript, we would often create a constant to hold this information (although a regular variable would be just fine if you did not change it). If you feel you must have a constant, use this syntax:

New-Variable -Name hkcu -Value 2147483649 -Option constant

The $key variable is used to hold the path to the registry key on which we will be working. The two variables, $property and $property2, are used to hold the actual properties that we will be working with to control the start pages. This section of the script is seen here:

{
 $hkcu = 2147483649
 $key = "Software\Microsoft\Internet Explorer\Main"
 $property = "Start Page"
 $property2 = "Secondary Start Pages"

Now we need to use the [wmiclass] type accelerator to create an instance of the stdRegProv WMI class. We hold the management object that is returned in the $wmi variable. The thing that may be a bit interesting is the path to the WMI class. It includes the computer name, the WMI namespace followed by a colon, and the name of the WMI class. This syntax corresponds exactly to the __path property that is present on all WMI classes because it is inherited from the __ System abstract class. (If you are interested in this level of detail about WMI, you should check out the Microsoft Press book, Windows Scripting with WMI: Self-Paced Learning Guide. All of the examples are written in VBScript, but the book applies nearly 100 percent to Windows PowerShell.) This is seen in here:

Image of the path to the WMI class

 

Here is the line of code that creates an instance of the stdRegProv WMI class on the target computer:

$wmi = [wmiclass]"\\$computer\root\default:stdRegProv"

Next we need to use the GetStringValue method, because we want to get the value of a string (it really is that simple). This is part that is a bit confusing when using the stdRegProv WMI class: the large number of methods. For each data type, you use a different method for both writing and reading from the registry. This also means you must know what data type is contained in the registry key property value you wish to work with. The methods are documented in Table 2.

Table 2 StdRegProv methods

Name Definition

CheckAccess

System.Management.ManagementBaseObject CheckAccess(System.UInt32 hDefKey, System.String sSubKeyName, System.UInt32 uRequired)

CreateKey

System.Management.ManagementBaseObject CreateKey(System.UInt32 hDefKey, System.String sSubKeyName)

DeleteKey

System.Management.ManagementBaseObject DeleteKey(System.UInt32 hDefKey, System.String sSubKeyName)

DeleteValue

System.Management.ManagementBaseObject DeleteValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName)

EnumKey

System.Management.ManagementBaseObject EnumKey(System.UInt32 hDefKey, System.String sSubKeyName)

EnumValues

System.Management.ManagementBaseObject EnumValues(System.UInt32 hDefKey, System.String sSubKeyName)

GetBinaryValue

System.Management.ManagementBaseObject GetBinaryValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName)

GetDWORDValue

System.Management.ManagementBaseObject GetDWORDValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName)

GetExpandedStringValue

System.Management.ManagementBaseObject GetExpandedStringValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName)

GetMultiStringValue

System.Management.ManagementBaseObject GetMultiStringValue(System.UInt32 hDefKey, System.StringsSubKeyName, System.String sValueName)

GetStringValue

System.Management.ManagementBaseObject GetStringValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName)

SetBinaryValue

System.Management.ManagementBaseObject SetBinaryValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName, System.Byte[] uValue)

SetDWORDValue

System.Management.ManagementBaseObject SetDWORDValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName, System.UInt32 uValue)

SetExpandedStringValue

System.Management.ManagementBaseObject SetExpandedStringValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName, System.String sValue)

SetMultiStringValue

System.Management.ManagementBaseObject SetMultiStringValue(System.UInt32 hDefKey, System.StringsSubKeyName, System.String sValueName, System.String[] sValue)

SetStringValue

System.Management.ManagementBaseObject SetStringValue(System.UInt32 hDefKey, System.String sSubKeyName, System.String sValueName, System.String sValue)

The code that obtains the value of the default home page is seen here:

($wmi.GetStringValue($hkcu,$key,$property)).sValue

After we have obtained the value of the string that holds the default home page, we need to obtain the value of a multistring that is used for the additional home pages. To do this, we use the GetMultiStringValue method. The convenient thing is that the values of the array that is returned are automatically expanded and we can avoid the For…Next gyrations of VBScript:

($wmi.GetMultiStringValue($hkcu,$key, $property2)).sValue

You can add comments to the closing curly brackets. I like to do this as a best practice to enable me to quickly know where the function begins and ends. Remind me to tell you a story about a train ride I once took in Germany from Regensburg to Hamburg (nearly a five hour trip) in which I spent the entire trip troubleshooting a problem with a script I was writing for the Vista Resource Kit. Here is the closing curly bracket and associated comment:

} #end Get-ieStartPage

Now we need to create a function to assign new values to the Internet Explorer start pages. Let's call the function Set-ieStartPage just for fun. This is seen here:

Function Set-ieStartPage()
{

We still need to assign some values to a bunch of variables. The first four variables are the same ones we used in the previous function (we could have make them script-level variables and saved four lines of code in the overall script, but then the functions would not have been stand alone pieces of code.) The $value variable is used to hold the default home page, and the $aryvalues variable holds a couple of secondary home pages:

Super-important note: Because you can have multiple home pages beginning with Internet Explorer 7, the Scripting Guys naturally recommend that you make the TechNet Script Center one of your home pages. In this way you can keep up with all the exciting news in the world of scripting. This plug brought to you by the Scripting Guys. As you were.

$hkcu = 2147483649
  $key = "Software\Microsoft\Internet Explorer\Main"
  $property = "Start Page"
  $property2 = "Secondary Start Pages"
  $value = "http://www.microsoft.com/technet/scriptcenter/default.mspx"
  $aryValues = "http://social.technet.microsoft.com/Forums/en/ITCG/threads/",
  "http://www.microsoft.com/technet/scriptcenter/resources/qanda/all.mspx"

After we are done assigning values to variables, we use the [wmiclass] type accelerator to create an instance of the stdRegProv WMI class. This is the same line of code we used in the Get-ieStartPage function, and it is seen here:

$wmi = [wmiclass]"\\$computer\root\default:stdRegProv"

We then use the SetStringValue method to set the value of the string. The SetStringValue method takes four values. The first is the numeric value representing the registry hive to connect to. The next is the string for the registry key. The third value is the property to modify, and the last is a string representing the new value to assign. This is shown here:

$rtn = $wmi.SetStringValue($hkcu,$key,$property,$value)

We now need to use a different method, such as the SetMultiStringValue method to set the value of a multistring registry key. It takes an array in the fourth position. The SetMultiStringValue method has as similar signature as the SetStringValue. The only difference is the fourth position needs an array of strings and not a single value. This is seen here:

$rtn2 = $wmi.SetMultiStringValue($hkcu,$key,$property2,$aryValues)

Now we print out the value of the returnvalue property. The returnvalue property contains the error code from the method call. A zero means it worked (no runs, no errors) and anything else means there was a problem. This is shown here:

"Setting $property returned $($rtn.returnvalue)"
  "Setting $property2 returned $($rtn2.returnvalue)"
} #end Set-ieStartPage

We are now at the entry point to the script. We decide to first get the starting values, and then we set them to the new values we wish to configure. If you wanted to requery the registry to ensure the values took, you could simply call the Get-ieStartPage function again. This is seen here:

if($get) {Get-ieStartpage}
if($set){Set-ieStartPage}

Well, AJ, great question. I sincerely hope you enjoy the new and improved Internet Explorer, and use the multiple home pages to your advantage. For me, it has become a mission critical feature allowing me to more quickly work through the e-mail that is sent to the scripter e-mail address. Tomorrow, we will finish up registry week. Until then, have an awesome day.

Ed Wilson and Craig Liebendorfer, Scripting Guys