The Scripting Guys' First Blog

  • Windows XP Service Pack 2 Application Compatibility Scripts

    One of the developer resources useful to IT folks that you might overlook in the vastness of microsoft.com is -- deep breath -- the Application Compatibility Testing and Mitigation Guide for Windows XP Service Pack 2

    This download contains documentation and scripts for handling issues of application compatibility that also deal with problems that most sysadmins will face in deploying SP2.

    On the Scripting Solutions Center of TechNet Script Center we've posted a set of supplemental scripts with their own readme that show how to perform most of the tasks in the Application Compatibility Guide, using WMI or the new Windows Firewall COM object model.  The Guide's scripts use mostly WSH and batch files.  The two sets of scripts complement each other -- there's something for everyone's needs and scripting preferences.

    Windows XP Service Pack 2 Application Compatibility - Supplemental Scripts

    Let us know how you're handling the deployment and management of SP2 and what issues you're encountering at:
    scripter@microsoft.com

  • New Scripting Guys webcast on scripting Windows XP Service Pack 2 available on-demand

    The latest Scripting Guys' Webcast took place Friday, October 8th, and is now available from the TechNet Webcast archives in on-demand video form.

    It's called Scripting with Microsoft Windows XP Service Pack 2: SOS! and you can find it at:
    http://msevents.microsoft.com/cui/eventdetail.aspx?EventID=1032259299&Culture=en-US

    By the way, you now need to register for the event to view the on-demand video afterwards as well as the event itself, so you have to click the "Register for event" link in the left-hand pane.

    Here's what Greg said about it:

    This Webcast -- to be presented by the scripting songbird himself, Mr. Peter Costantini -- ... will introduce you to some of the new scripting objects found in XP Service Pack 2. Perhaps more important, it will also tell you how you can get your scripts to work with Service Pack 2 in the first place; by default, the new Windows Firewall prevents you from using scripts to remotely manage a computer running Service Pack 2. But don't despair: Peter will show you how to work around that issue, as well as show you how to do such things as manage the new Pop-Up blocker in Internet Explorer.

    The webcast goes into some depth on:

    • Deploying and blocking deployment of SP 2 with scripting
    • Re-enabling remote administration on SP 2 hosts
    • Windows Firewall scripting
    • Scripting networking configuration
    • Scripting local security configuration
    • Scripting Internet applications
    • Other scriptable areas of SP 2

    And it shows code examples for each area.

    Here's a bit of dialogue from the section of the webcast on scripting registry changes:


    Dr. Scripto:

    The registry is Windows' heart of darkness.  Mister Kurtz designed it.

    Peter:

    Think back to that English lit class you used to fall asleep in.  Remember Joseph Conrad's novel?  What was that they said about Mister Kurtz? "Mistah Kurtz, he dead"  And not only is Mister Kurtz dead, but he didn't tell anybody where he put the blueprints for the registry.

    So the registry has grown organically, with its own logic  It's really less a database than an ecosystem, a sort of mysterious and chaotic digital rain forest.  It's a place of teeming life ... and violent death.

    Listen!  Can you hear that flock of DWORDS high in the treetops of HKEY_LOCAL_MACHINE?  And look!  There goes a sinuous REG_SZ slithering through the undergrowth of HKEY_CLASSES_ROOT!

    We can never tame the registry, but with patience we can learn to appreciate the ebb and flow of its seasons.  And very cautiously, we can make small changes in it.  Now as you may be aware, that's a controversial topic.

    Mark Minasi, the columnist for Windows IT Pro magazine, has suggested that the standard registry warning in our documentation should be changed to read: "Manually changing the registry can cause sudden involuntary sex change."

    Now Mark is a very smart and funny guy, but there is absolutely no truth to his allegation.

    I do admit that we have heard completely unsubstantiated rumors that scripting the registry can cause hair to grow on the palms of your hands and, in extreme cases, temporary blindness and insanity.

    But we want to reassure you that we have not been able to verify one single case of this and that there is almost no chance that this will happen to you.


    BabyScript

  • Hey, Scripting Guy! How Can I Stop a Script Partway Through?

  • Hey, Scripting Guy! How Can I Create a Folder on a Remote Computer?

  • Hey, Scripting Guy! How Can I Prompt a User for Input?

  • Hey, Scripting Guy! How Can I Enumerate All the Objects in an Active Directory OU?

  • Hey, Scripting Guy! Daily Column

  • Extreme file and folder scripting: Listing a directory tree recursively - Day 3 – Bonus script: Using WMI with LIKE

     

    When I showed these scripts to Dean, he thought there had to be an easier way to recurse through a directory tree with WMI, and he found it.  The only caveat is that you must run it on Windows XP or Windows Server 2003.  This is because WMI Query Language, the SQL dialect that you use with the ExecQuery method of SwbemServices, first added the LIKE keyword in Windows XP (see http://msdn.microsoft.com/library/en-us/wmisdk/wmi/like_operator.asp).

     

    In this case, LIKE enables you to query for all directories that contain a specific string, surrounded by percent signs, for example: "%c:\\ff%" (remember that WQL queries require two backslashes rather than one to delimit file paths).  This would include all subdirectories of c:\ff and their subdirectories.  In other words, LIKE enables you to use WQL's equivalent of wildcards.  You can also use the percent sign at just one side of the string.  In this script we use "c:\\ff%", which returns any path on c: drive that begins with "ff".  Keep in mind that this will also return not just the subdirectories of c:\ff, but also any other top level folders that begin with ff, such as c:\ffx.

     

    The query including LIKE in this script seems to run very slowly, at least on my computer.  That may be because my computer is old and cantankerous, like me.  Or it may be because WMI has to search the whole file system to make sure there are no other matches that are LIKE the string.

     

    Here's Dean's script, which I suppose we could call Files-list-recurse-like-wmi.vbs, except that the name is getting too long.  Call it what you will.

     

    strComputer = "."

    strFolderRoot = "c:\\ff"

    Set objWMIService = GetObject("winmgmts:" _

     & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

    Set colFolders = objWMIService.ExecQuery _

     ("Select * from Win32_Directory where Name Like '" & strFolderRoot & "%'")

    For Each objFolder in colFolders

      Wscript.Echo "Folder: " & objFolder.Name

      strTMP = Replace(Mid(objFolder.Name,4,Len(objFolder.Name)),"\","\\")       

      strQuery = "SELECT * FROM CIM_DataFile WHERE Drive = 'c:' " & _

       "AND Path = '\\" & strTMP & "\\'"

      Set colFiles = objWMIService.ExecQuery(strQuery)

      On Error Resume Next

      For Each objFile in colFiles

        WScript.Echo "File: " & objFile.Name

      Next

    Next

     

  • Extreme file and folder scripting: Listing a directory tree recursively - Day 2 – Using WMI

    BabyScript

     

    Now that we've glanced at recursion out of the corner of our eye (on Day 1) and lived, it's time to stare straight-on into the unspeakable horror of the Medusa Code.  If you have sunglasses, please put them on now.  If you try to speak its name, Files-list-recurse-wmi.vbs, we won't be responsible for what might happen to your tongue.

     

    strComputer = "."

    strDrive = "c:"

    strPath = "ff" 'Use double backslashes in path if necessary

    strPathAlt = Replace(strPath, "\\", "\")

    strName = strDrive & "\" & strPathAlt

    Set objWMIService = GetObject("winmgmts:\\" & strComputer)

    WScript.Echo strName

    Set colFiles = objWMIService.ExecQuery _

     ("SELECT * FROM CIM_DataFile WHERE Drive = '" & strDrive & _

     "' AND Path = '\\" & strPath & "\\'")

    For Each objFile in colFiles

      WScript.Echo objFile.Name

    Next

    Set colFolders = objWMIService.ExecQuery _

     ("ASSOCIATORS OF {Win32_Directory.Name='" & strName & "'} " _

     & "WHERE AssocClass = Win32_Subdirectory " _

     & "ResultRole = PartComponent")

    For Each objFolder in colFolders

      WScript.Echo objFolder.Name

      strFolderPath = Replace(objFolder.Path, "\", "\\")

      strFilePath = strFolderPath & objFolder.FileName & "\\"

      Set colFiles = objWMIService.ExecQuery _

       ("SELECT * FROM CIM_DataFile WHERE Drive = '" & strDrive & _

       "' AND Path = '" & strFilePath & "'")

      For Each objFile in colFiles

        WScript.Echo objFile.Name

      Next

      ShowSubFolders objFolder.Name

    Next

     

    Sub ShowSubFolders(strSubFolder)

    Set colSubFolders = objWMIService.ExecQuery _

     ("ASSOCIATORS OF {Win32_Directory.Name='" & strSubFolder & "'} " _

     & "WHERE AssocClass = Win32_Subdirectory " _

     & "ResultRole = PartComponent")

    For Each objSubFolder in colSubFolders

      Wscript.Echo objSubFolder.Name

      strSubFolderPath = Replace(objSubFolder.Path, "\", "\\")

      strSubFilePath = strSubFolderPath & objSubFolder.FileName & "\\"

      Set colSubFiles = objWMIService.ExecQuery _

       ("SELECT * FROM CIM_DataFile WHERE Drive = '" & strDrive & _

       "' AND Path = '" & strSubFilePath & "'")

      For Each objSubFile in colSubFiles

        WScript.Echo objSubFile.Name

      Next

      ShowSubFolders objSubFolder.Name

    Next

    End Sub

     

    Here's the output from the same test folder:

     

    C:\scripts>files-list-recurse-wmi.vbs

    c:\ff

    c:\ff\disklog.txt

    c:\ff\otherfile.txt

    c:\ff\scriptlog.txt

    c:\ff\servicelog.txt

    c:\ff\servicestatus.txt

    c:\ff\testfile.txt

    c:\ff\ff1

    c:\ff\ff1\disklog.txt

    c:\ff\ff1\scriptlog.txt

    c:\ff\ff1\ff3

    c:\ff\ff1\ff3\disklog.txt

    c:\ff\ff1\ff3\scriptlog.txt

    c:\ff\ff2

    c:\ff\ff2\disk.log

    c:\ff\ff2\otherfile.txt

    c:\ff\ff2\service.log

    c:\ff\ff2\ff4

    c:\ff\ff2\ff4\disk.log

    c:\ff\ff2\ff4\otherfile.txt

    c:\ff\ff2\ff4\service.log

     

    Hmm, looks kind of familiar, doesn't it?  You mean, it takes all that code in WMI to produce the same output?  Yep.

     

    Actually, this script goes beyond the bonus script in the webcast.  That one only listed folders and subfolders.  This one displays the full Monty, folders, sub-folders and all their files.  But it takes quite a few more lines of code than the FSO version.

     

    We start out by assigning the drive and top folder names separately, so we can take them apart later.  WMI lets us (or makes us) define the elements of a file path separately.  Then we'll query the CIM_DataFile class for file instances, filtering with the separate drive and path variables.  Note the lovable quirk of WQL that we have to put double backslashes on both sides of the path.  This gives rise to some of the contortions in this script, as other methods of the class require a path separated by single backslashes rather than double ones.  VBScript is there to help with the Replace function, that lets us pass it a string, a substring to replace and second substring with which to replace the first.  So we use it to replace double backslashes with single backslashes and vice versa.

     

    At this point, we've only listed the files in the top folder.  What to do next?  Well, at this point we need a way to get at the subfolders in the current folder, but Win32_Directory doesn't give us anything as handy as the FSO SubFolders property.  What we do have, though, is something called an association class.

     

    Now both Greg and Dr. Scripto told me not to talk about association classes, and even Dean had reservations.  That way lies madness, they said.  Association classes are so Byzantine, so baroque, so rococo, that people will run screaming away from scripting and never return.  OK, I said, I’m sure they’ll take it on faith that they just work.

     

    Then I tossed and turned that night because I knew I couldn’t do this to our readers.  So here’s what an association class is: a class that associates two other classes or managed resources.  So far, so good.  In this case, the association class is Win32_Subdirectory, which associates two different sets of instances of Win32_Directory.  One of the two Win32_Directory instances is called GroupComponent, and it represents the parent directory of the two related instances.  The other is called PartComponent, and it represents the subordinate directory or directories in the relationship.

     

    So when this ASSOCIATORS OF query:

    "ASSOCIATORS OF {Win32_Directory.Name='" & strName & "'} " _

     & "WHERE AssocClass = Win32_Subdirectory " _

     & "ResultRole = PartComponent"

    filters for "ResultRole = PartComponent", it's asking for the directories that are subdirectories of the directory specified by strName.  The query returns a collection of these associated subdirectories, which we assign to an object reference, colSubFolders.

     

    If you want to pursue this, the WMI SDK documentation for Win32_Subdirectory is at:

    http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_subdirectory.asp

     

    Besides using the keywords “ASSOCIATORS OF” in a WQL query, as this script does, you can also call the AssociatorsOf method of the SwbemServices object, which is the kind of object referenced by objWMIService in this line:

    Set objWMIService = GetObject("winmgmts:\\" & strComputer)

    Then when you call objWMIService.AssociatorsOf(parameters), the only required parameter (there are also several optional ones including association class) is the object path of a managed resource or resources, such as:

    "Win32_Service.Name='Alerter'"

     

    Other association classes work in slightly different ways, but all enable you to associate related instances of classes.  For a fuller explanation of association classes, see:

     

    Have you run screaming yet?  If not, you've become one of the few, the proud, the ASSOCIATORS.  We're working on a secret handshake, but you can tell members of the confraternity by the glazed look in their eyes.

     

    But we're not quite done yet.  Once we've used the association class to get the subfolders, we still have to loop through the collection and then, as with FSO, the subroutine has to call itself recursively to loop through any subfolders of the subfolders.

     

    I hope it goes without saying that if you wanted to perform this astounding feat on a remote machine, you could just change line 1 to:

                strComputer = "computer1"

    where computer1 is an accessible host on your network on which you have administrative privileges.

     

    So we've done it.  We've actually walked a directory tree using both FileSystemObject and WMI.  Let the high-fiving and end-zone dances (or, for those of the soccer persuasion, "Gooooooooool" celebration) begin.

     

    I know you're thinking to yourselves, but you're too polite to ask: Um, couldn't you do all this in one line with dir /s?  Well, actually, um, I guess so (Dr. Scripto, help me out here!).  But then we wouldn't have had all this fun.  Nor would we appreciate what dir has to do under the hood.  If you ever wanted to customize this or add some functionality that does something to or within the resulting directory tree, you wouldn't know how.  And, most important, we would not have achieved such a deep understanding of extreme file and folder scripting with both FSO and WMI.

  • Extreme file and folder scripting: Listing a directory tree recursively. Day 1 – Using FilesSystemObject

    BabyScript

     

    If you attended Day 3 of the Scripting Week webcasts, "Scripting Files and Folders Makes Me Happy" http://go.microsoft.com/fwlink/?LinkId=30795, you may recall an odd and vaguely menacing script in the second section on WMI.  It bristled with strange code and was labeled "Bonus: listing a folder tree," but we didn't discuss it.  As Dr. Scripto said, merely looking at it could turn you to stone.

     

    OK, so Dr. Scripto exaggerates a little.  But we're going to call that script the Medusa Code because it sounds cool, kind of like the name of an action movie.  We'll come back to the Medusa Code later, so stay on the edge of your seats.  But for starters we're going to talk about what the Medusa Code was trying to accomplish in the first place: listing a directory tree recursively.

     

    Ah, "recursively": there's a word that rolls off the tongue!  Dr. Scripto loves to say it, although I had always suspected he wasn't too sure what it meant.  I wasn't either, so I got out my dictionary and checked.  There was no listing for "recursively," but it had a definition for "recursive": "1: of, relating to, or involving mathematical recursion."

     

    Doh!  Of course!  Elementary, my dear Scripto.

     

    Not being of a mathematical bent (I mean, being kind of bent, but not mathematically so), I forged ahead to the second definition: "2: of, relating to, or constituting a procedure that can repeat itself indefinitely or until a specified condition is met."

     

    Hmmm, repeating itself indefinitely – sounds like Greg on a bad day.  At that point, I threw the dictionary on my main pile (my office is organized by piles) and opened Notepad.  When something doesn't make sense, it usually helps to open Notepad and start writing code.

     

    At that point, Dr. Scripto whispered in my ear: "Don't worry about 'recursive.'  Just write a script that walks a directory tree and lists all the files and folders in each branch."  Aha, my muse had spoken.  "But that's not repeating itself indefinitely," I whined.  "No," replied Dr. Scripto, "just repeating itself until a specified condition is met.  And that condition?  That no more sub-folders can be found to recurse through."

     

    If you'll recall from the webcast, with WMI you can easily display the names of all the files or folders on a computer or on a particular disk drive.  But you probably don’t need to do that too often, and when you do, it can take a long time.  When you get down to listing all the files or folders in a specific directory, you run into a shortcoming of some methods of the WMI file and folder classes: they only list the first level of files or folders even if there are sub-folders and files in them.  In other words, they don't walk down all the branches of the directory tree.  Ipso est, they're not recursive.

     

    To show how to list a directory tree recursively, we're going to take a little detour back to the FileSystemObject.  You'll recall that the webcast began with FSO and worked up to the WMI file and folder classes.  So we'll follow the same path: before we get to WMI and the Medusa Code, it's a little bit easier to see how recursion works with FSO because the rest of the code is simpler.

     

    Here’s a script that uses FSO to list all files in a folder and its sub-folders recursively (we'll call it Files-list-recurse-fso.vbs):

     

    Const FOR_READING = 1

    strFolder = "c:\ff"

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    Set objFolder = objFSO.GetFolder(strFolder)

    WScript.Echo objFolder.Path

    Set colFiles = objFolder.Files

    For Each objFile In colFiles

      WScript.Echo objFile.Path

    Next

    ShowSubFolders(objFolder)

     

    Sub ShowSubFolders(objFolder)

      Set colFolders = objFolder.SubFolders

      For Each objSubFolder In colFolders

        WScript.Echo objSubFolder.Path

        Set colFiles = objSubFolder.Files

        For Each objFile In colFiles

          WScript.Echo objFile.Path

        Next

        ShowSubFolders(objSubFolder)

      Next

    End Sub

     

    Here's the output I got by running the script on a test folder:

     

    C:\scripts>files-list-recurse-fso.vbs

    C:\ff

    C:\ff\disklog.txt

    C:\ff\otherfile.txt

    C:\ff\scriptlog.txt

    C:\ff\servicelog.txt

    C:\ff\servicestatus.txt

    C:\ff\testfile.txt

    C:\ff\ff1

    C:\ff\ff1\disklog.txt

    C:\ff\ff1\scriptlog.txt

    C:\ff\ff1\ff3

    C:\ff\ff1\ff3\disklog.txt

    C:\ff\ff1\ff3\scriptlog.txt

    C:\ff\ff2

    C:\ff\ff2\disk.log

    C:\ff\ff2\otherfile.txt

    C:\ff\ff2\service.log

    C:\ff\ff2\ff4

    C:\ff\ff2\ff4\disk.log

    C:\ff\ff2\ff4\otherfile.txt

    C:\ff\ff2\ff4\service.log

     

    The script is pretty straightforward for the most part.  It gets the folder specified by the variable strFolder (in this case, c:\ff), then gets a collection of the files in that folder and loops through it with a For Each loop, displaying the full path of each one.  A nice feature of the FileSystemObject is that Folder objects include a Files property that's a collection of all the files in the folder.  How logical!  How'd they ever come up with that?

     

    But take a closer look at that Sub.  What's it doing there?  By jingo, Dr. Scripto, it's calling itself!  Is that legal?  Actually, as Dr. Scripto reassures me, that's what a recursive subroutine does, kind of like a dog chasing its own tail.

     

    Besides the Files collection, FSO Folder objects have a SubFolders collection that includes — you'll never guess — all the folders contained within the folder.  Very handy.  We can use SubFolders to loop through each subfolder in the top-level folder, then get the collection the files in each and loop through that, displaying each one.  Then, within the top For Each loop for subfolders, the sub-routine calls itself, passing itself the name of each subfolder in the collection successively.  This is the key to how it can drill down through the levels of a directory tree.  There are only three levels in the output example, but the script will keep drilling down — recursing — until it hits oil or the bottom level of the tree.

     

    Is that crystal clear now?  If you want to see this in action (and think you can handle this much fun), you could run the script in the Microsoft Script Debugger and watch the variables change through all those loops.  If you start to get dizzy, just look away.  For more information, Greg talked about how to run scripts in the debugger during our August 4 webcast "What Do You Want To Script Today?" http://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US&EventID=1032255873&EventCategory=5

     

    Incidentally, if you want to read a directory tree on a remote machine, FSO allows you to use a UNC path, such as "\\computer\share".  So you could change line 2 to:

    strFolder = "\\server1\c$\ff"

    and display that tree recursively, provided of course that administrative shares are enabled on server1 and that you have administrative credentials on the machine.

     

    More soon about doing this with WMI.

  • Hey, I've been busy, OK? (Well, not really, but ....)

    Ok, ok, it has been a long time since I posted anything here, hasn’t it? Do I have an excuse for that? Shoot, not only do I have an excuse, I have three of them:

     

    1. I’m lazy.
    2. It’s baseball season. (As I noted awhile back, coaching baseball limits the amount of free time I have outside of work, and that’s pretty much the only time when I can put together blog entries. On the bright side, we’re 3-0 versus our cross-town rivals, and my son made a regional all-star team that will play in Japan in August. So don’t expect many blog postings in August, either.)
    3. I spend surprisingly little time doing scripting-related stuff.

    I know, I know, that last one sounds pretty lame: we call ourselves the Microsoft Scripting Guys, and yet we don’t spend all our time doing scripting stuff? Sad, but true (although that might be changing in the very near future.) Although we do some scripting stuff, we haven’t always been given an opportunity to play around with new/undocumented scripting stuff, exactly the kind of information I’d like to premiere in the blog. Sure, we could we talk about mapping network drives in this space, but, I mean, come on: mapping network drives, in a blog? Not that mapping network drives isn’t important, it’s just that it isn’t exactly cutting-edge material, either. And so by sticking to the notion that the blog ought to focus on things we haven’t talked about elsewhere, well, that means most days I really don’t have much to say. And that’s because most days I don’t spend much time (if any) looking any new/different scripting technologies.

     

    Over the past few days, however, I’ve started fooling around with Windows XP Service Pack 2. And it’s a good thing I did: there are some new scriptable items in Service Pack 2 (like Windows Firewall and Software Update Services), so – for once – that gives me an opportunity to talk about something new and different in the blog. (Most likely what I’ll do is just mention some stuff here, and then sooner or later we’ll post more detailed information in the Script Center.) It’s also a good thing I looked at Service Pack 2 because we had queried the WMI and ADSI teams to ask them if either of their technologies were being changed for SP 2. They said no, and – technically – that’s true; WMI and ADSI are largely unchanged. But guess what happened when first I tried to run a WMI script against a remote machine that had Service Pack 2 installed? If you guessed, “It worked like a charm!”, well, sorry. Instead, I got this error message:

     

    The remote server machine does not exist or is unavailable.

     

    When I tried running an ADSI script, I got an even cooler result: nothing. The script ran, and then just kind of disappeared, without even giving me an error message of any kind. (If any of you happen to open a closet door or something and you see a lost ADSI script in there, it’s probably mine.)

     

    So what’s the deal here; does this mean WMI and ADSI have been changed (for the worse) with Service Pack 2? No; in fact, if you run the scripts locally they work just fine. As it turns out, the culprit is the new Windows Firewall. By default, the Windows Firewall is enabled when you install Service Pack 2, and, by default, the Firewall blocks all incoming RPC traffic. If you try to run a script against a remote computer running Service Pack 2, the firewall will block the script, regardless of any admin privileges you might hold. (The firewall simply blocks all incoming signals; it doesn’t really care who might have sent them.)

     

    So are you hosed, are all those WMI scripts you have so painstakingly crafted over the past year or two now totally useless once you install Service Pack 2? Fortunately, the answer is no. In fact, your scripts will still work just fine, without you having to change a single line of code; instead, you simply have to open the appropriate ports on the Windows Firewall.

     

    A hassle? Well, maybe (though the argument, of course, is that it’s a small price to pay for added security and protection). But at least it’s easy to open the appropriate ports; in fact, here’s a script that will take care of that for you:

     

    Set objFirewall = CreateObject("HNetCfg.FwMgr")

    Set objPolicy = objFirewall.LocalPolicy.CurrentProfile

     

    Set objAdminSettings = objPolicy.RemoteAdminSettings

    objAdminSettings.Enabled = TRUE

     

    Pretty easy, huh? Run that script locally on each machine that has Service Pack 2 installed, and your WMI and ADSI (and other scripts) will work just like they always have.

     

    (Oh, did I say that you had to run the script locally on each machine? Well, there’s a bit of a Cacth-22 situation going on here: you need to run the script to open the firewall, but because the firewall isn’t open, any script you run remotely can’t get through. Consequently, you’ll have to run the script locally after you install Service Pack 2. Are there better ways to do this? Possibly; you can use an unattend file to install Service Pack 2, and within that file you can indicate that you want remote administration enabled. We’re still investigating the best/easiest ways to do all this. Stay tuned.)

     

    By the way, the Windows Firewall has its own object model, and is fully scriptable. We intend to document this as fully as we can by the time Service Pack 2 is officially released. In the meantime, here are a couple scripts you can play around with. Over the next week or so, I’ll pop a few additional scripts into the blog, just to give you a better idea of what (and how) you’ll be able to manage the firewall after you upgrade all your XP machines to Service Pack 2.

     

    Disable the Windows Firewall

     

    As I noted before, the Windows Firewall is enabled by default when you install Service Pack 2. For most people that’s a good thing; if you already have a firewall running on your machine, however, you might not want to have Windows Firewall running as well. So how can you disable Windows Firewall? Why, by running this script, of course:

     

    Set objFirewall = CreateObject("HNetCfg.FwMgr")

    Set objPolicy = objFirewall.LocalPolicy.CurrentProfile

     

    objPolicy.FirewallEnabled = FALSE

     

    Later on, if you decide to re-enable the firewall, just set the FirewallEnabled property to True, like so:

     

    Set objFirewall = CreateObject("HNetCfg.FwMgr")

    Set objPolicy = objFirewall.LocalPolicy.CurrentProfile

     

    objPolicy.FirewallEnabled = TRUE

     

    Basic Firewall Properties

     

    Here’s a script that will provide some basic information about Windows Firewall. Without going into a lot of detail, it will tell you:

     

    • Whether or not the firewall is currently enabled.
    • Whether or not exceptions are allowed to the default firewall settings. If ExceptionsNotAllowed is set to True, then all incoming traffic is blocked, no exceptions allowed (hmmm, wonder if that’s where the property name came from). What that means is that only network traffic that you initiate can pass through the firewall. If this property is set to False, then you can do things like allow traffic originating from and intended for certain applications to get through the firewall. That’s something we’ll talk about next week.
    • Whether or not notifications are disabled. If notifications are not disabled, then anytime a script or application tries to wriggle its way through the firewall a message box will pop up alerting the user to this.
    • Whether or not Unicast responses to multicast broadcasts are disabled. To tell you the truth, I don’t fully understand the reason why you might want to enable or disable this. But, hey, I’m just a scripting guy; I can’t be expected to actually understand computing!

     

    Set objFirewall = CreateObject("HNetCfg.FwMgr")

    Set objPolicy = objFirewall.LocalPolicy.CurrentProfile

    Wscript.Echo "Current profile type: " & objFirewall.CurrentProfileType

     

    Wscript.Echo "Firewall enabled: " & objPolicy.FirewallEnabled

    Wscript.Echo "Exceptions not allowed: " & objPolicy.ExceptionsNotAllowed

    Wscript.Echo "Notifications disabled: " & objPolicy.NotificationsDisabled

    Wscript.Echo "Unicast responses to multicast broadcast disabled: " & _

        objPolicy.UnicastResponsestoMulticastBroadcastDisabled

     

    Resetting the Firewall

     

    This is kind of a handy little script, especially after you start messing around with the firewall. Next week we’ll show you some scripts that can do things like open ports, add applications to the exceptions list, and otherwise change the default settings. That’s good, but when you’re all done fooling around you might think to yourself, “Ok, I’m not totally sure what I did here, and whether or not I might have inadvertently screwed things up.” Hey, don’t worry about it; just run this script, and it will automatically restore the default settings:

     

    Set objFirewall = CreateObject("HNetCfg.FwMgr")

    objFirewall.RestoreDefaults()

     

    Cool, huh? Next week, we’ll go into the Windows Firewall object model in a little more detail – promise. (Well, of course, we have a game on Monday and another on Wednesday, practice on Tuesday and Thursday, a doubleheader Saturday ….)

     

    P.S. If you don’t trust me to actually continue the exciting saga of Windows Firewall next week, well, I can’t say as if I blame you. Therefore, if you want to hedge your bets a little, you might take a look at the Windows Firewall SDK, located here: http://msdn.microsoft.com/library/en-us/ics/ics/windows_firewall_start_page.asp

  • Help Design the "Next Generation" Script Center

    Hey, guys. I apologize for being absent for so long from this space, but this time of year it’s hard for me to find the time to do things like blogs. Now, that might sound a bit odd; after all, as a Microsoft Scripting Guy, isn’t it my job to do things like scripting blogs? Well, to tell you the truth, it’s not. People always say to me, “Man, what a great job you have, just sitting around writing about scripting all day.” And you know what: that is a great job; it’s just not my job. In reality, I don’t spend much time during the workday writing about scripting; I do other more … important … things. If I want to write a blog or do a Webcast, I pretty much have to put that stuff together at home. Now, I don’t mind doing that (well, not too much anyway) but because I coach baseball my evenings are pretty much booked between March and August. So expect the postings to be sporadic for the next few months. I’ll try to get something posted on a regular basis, but not only am I coaching, but I also volunteered to take care of standings and stats for our league as well.

     

    (Well, actually, I didn’t volunteer, I just mentioned when I signed my son up that it would be nice if we kept the standings on the league Web site this year. Next thing I knew, I was conducting scorekeeping clinics and compiling stats and doing all sorts of stuff like that. I’m still not sure how that happened.)

     

    I have a confession to make, though: even though I am posting something today, I’m also cheating a bit. That’s because I’m just posing a question rather than providing some any kind of scripting information. (You can always tell when bloggers are getting lazy, because they start saying things like, “I’d like to turn this blog over to you, the readers, for awhile.”) As I think I mentioned awhile back, while we are generally pleased with the TechNet Script Center we’ve also been somewhat disappointed in the fact that the Script Center has not evolved along with the interest in scripting. In fact, the Script Center hasn’t evolved at all; it’s basically in the exact same shape it was 100 years ago (albeit with about twice the number of scripts we started with). And that’s a problem. For example, we have over 1,200 new scripts we’d like to add (as a point of reference, we have a little over 900 scripts there right now). These scripts run the gamut: IIS scripts, Virtual Server scripts, a few Exchange scripts, Services for Unix scripts, etc. So why don’t we add them? Well, up until now, the categories for the Script Center have been writ in stone; we have not been allowed to create new categories, and have been required to file new scripts under those existing categories. Based on that, most of our 1,200 new scripts would have to be unceremoniously dumped into the Computer Management node. That sounded like a usability/discoverability nightmare, and so we have been reluctant to do anything with the new scripts.

     

    But now, after over a year of negotiating, we have been given the right to do the Script Center ourselves. That means we can change existing categories, create new categories, delete old categories that don’t make much sense. It also means we can create a dynamic home page, we can “advertise” things like Webcasts, we can post content quickly and easily, we might (and I emphasize the word might) even be allowed to post scripts submitted by – gasp! – non-Microsoft people. It’s gonna take us awhile to learn the ropes of self-publishing on Microsoft.com, but we think it will eventually be cool. Way cool.

     

    So here’s the question I wanted to pose: what do you think we should do to the Script Center? We have some ideas, but we’d like to hear what people who actually use the Script Center have to say. What would you like to see? What wouldn’t you like to see? Give us your wish list. Obviously there’s no guarantee that we can, will, or will be allowed to do the things on your list, but, hey, who knows; after all, about a year ago we were told that there was zero chance we’d ever be allowed to actually manage the Script Center ourselves. Who’da thunk it?

     

    Anyway, if you have ideas for the Script Center and if you have ideas for helping us create a true scripting community, either post them here, or email scripter@microsoft.com. Thanks, guys!

     

    And now if you’ll excuse me, I’ve got to start thinking about the lineup for Saturday.

     

  • Book Review: Administrator's Top 10 Introductory Scripts

    One of the reasons I thought we should do a scripting blog is because there are a lot of things (like book reviews) that we can’t do on TechNet. Being somewhat naïve, I thought the other Scripting Guys (who actually read computer books) would jump at the chance to share their opinions with you. So far, though, they’ve kind of wienered out on me. I’ll keep pushing them, however, because I know they have a lot of interesting things to share with the scripting world.

     

    (I’d encourage you to send angry emails to scripter@microsoft.com and shame them into contributing to the blog. But – sigh – at the moment I’m the only one who reads and replies to those emails, so ….)

     

    So why can’t I just do book reviews myself? Well, I have a confession to make: I don’t ever read computer books. (I’m not saying that’s good or bad, that’s just the way it is.) One time, when I worked at the University of Washington School of Dentistry doing computer support stuff, I had to swing by the Dean’s Office on my way home to show someone how to do a mail merge in Word. (Back then my days seemed to consist solely of showing people how to do a mail merge in Word.) I set my book (The Collected Stories of P.G. Wodehouse) down and helped the receptionist with her mail merge problem. As I was doing so, our administrative assistant popped by and picked up the book. “Oh, I love P.G. Wodehouse,” she said. “Whose book is this?”

     

    “Mine.”

     

    “No, really; whose book is this?”

     

    “It’s mine.”

     

    “No, really, I just want to know whose – fine, don’t tell me.”

     

    No one would believe that I didn’t spend my free time reading about computers. But it’s true.

     

    Here’s another shocker: Up until I couple weeks ago, and before I finally succumbed to family pressure, we had no Internet connection at home. (I know, it’s hard to believe that people could even live in such primitive conditions.) And I won’t even mention the fact that we don’t have digital cable and that I don’t have a cell phone; I don’t want anthropology students hanging around trying to determine whether or not I’m the missing link. (Although the truth is, even the Neanderthals tend to roll their eyes whenever my name gets mentioned.)

     

    The interesting thing, of course, is that people always ask me if I can recommend a good scripting book; heck I can’t even recommend a bad scripting book. In my defense, though, I will say that prior to joining the Scripting Guide team, I had no reason to read a scripting book (not when there are books like Sometimes a Great Notion and Catch-22 out there). And after joining the Scripting Guide team, I specifically chose not to read any scripting books. That might seem like a dumb idea when you consider the fact that I didn’t know much about scripting, but I decided that I didn’t want to be unduly influenced by what other people had or had not done. Besides, if I was writing about scripting during the day, I didn’t want to go home and read about scripting at night.

     

    In fact, up until last week the closest I had ever come to reading a scripting book occurred when I read selected parts of two books on WMI written by Alain Lissoir. These books, by the way, are great; you can’t believe how much information Alain has packed into two little volumes. Be aware, however, that neither book is aimed at beginners; if you don’t know anything about WMI, I’d strongly suggest that you start with the WMI Primer in the Windows 2000 Scripting Guide and then move on to Alain’s stuff. However, if you’re fairly comfortable with WMI scripting and at least somewhat familiar with WMI terminology, then I definitely recommend Alain’s books. (The only problem I have with them is that he’s pretty much explained everything there is to know about WMI; he didn’t leave anything for the rest of us.)

     

    By special request, however, I was asked if I would read a new book – Administrator’s Top 10 Introductory Scripts – by Jeff Fellinge. And so I did. Like I said before, I’m not overly familiar with the genre, but as near as I can tell Jeff has taken a different tack here. What he’s done is written 10 full-scale production scripts (a logon script; a script that lists Active Directory accounts due to expire; a worm vulnerability detector; etc.). He’s then used those scripts as the basis for individual chapters in the book, methodically working his way through each script, explaining how the different sections of each script work. (Incidentally, I'm not convinced that these are the top 10 scripts, but they're useful and interesting nonetheless.)

     

    I really like the fact that Jeff has chosen to write full-featured scripts, scripts that can do things like handle command-line arguments. Why? Well, a lot of people get their scripting information from the TechNet Script Center. Nothing wrong with that, except in the Script Center (as I’ve noted before) we specifically shy away from full-scale production scripts (that is, scripts that use error handling and accept command-line arguments and carry out multiple functions and ….). We always tell people that they can take our little code snippets and knit them into a full-scale production script, but we’ve never shown them any examples of this. Fortunately, Jeff has done that for us. That alone makes it a worthwhile addition to the scripting oeuvre. (See, if all I ever read was computer books, I wouldn’t know how to toss in high-falutin’ words like oeuvre.) We Scripting Guys tend to emphasize the “quick and dirty“ approach to scripting, and that has its benefits. At the same time, however, there are also benefits to using scripting as a way to create more sophisticated utilities. That's the direction taken in this book.

     

    In addition, Jeff has also written these scripts in Jscript. I know there are lots of Web page scripting books that use Jscript, but there are few – if any – system administration scripting books that use Jscript. Yet another first, and a welcome one at that. Although I do everything in VBScript, I like seeing books that use other scripting languages to carry out system administration tasks. That helps drive home the point that it doesn’t really matter, that you should use the language you’re most comfortable with. I know that, because of the Web, a lot of people are familiar with Jscript; I think it’s great that there’s now a book that shows them how to apply their Jscript skills to system administration scripting. I’d hate to think that people might spend years honing their Jscript knowledge, only to feel they had to learn an entirely new language in order to do system administration scripting. You don't, guys. As long as your scripting language can work with COM objects (like WMI and ADSI), well, the language you choose to use is as much a matter of personal preference as it is anything else.

     

    In fact, the one criticism I have of the book is that it doesn’t use Jscript exclusively. The introductory chapters, for example, tend to jump back and forth between VBScript and Jscript, showing concept A in VBScript, concept B in Jscript, etc. To be honest, I’m not sure there’s much to be gained by that. Later on, the big production scripts are written in either Jscript or VBA . Why VBA? Well, in several scripts Jeff use Microsoft Excel as the UI for his scripts, typically returning information from a number of sources and then writing that information to a spreadsheet. I would have liked it better had there been an exclusive focus on Jscript. The truth is, if you’ve decided to use Jscript, well, then who cares how the same operation is carried out in some other language? As the saying goes, ya gotta dance with whut brung ya.

     

    And using nothing but Jscript wouldn't keep you from stashing data in Excel; instead of starting Excel and then running a VBA script, you could start a Jscript script and then launchand manipulate Excel from within that script. Because VBScript, Jscript, and VBA are not alike, I’m afraid people might get a bit confused by some of these scripts; all the more reason to stick with one language all the way through. Interestingly enough, Jeff uses an HTA to serve as the UI for another script. Why not use HTAs throughout the book rather than Excel? To me, it seems like overkill to use Excel simply as a way to store tabular data.

     

    But those are minor quibbles. There is still a lot of interesting code in here, and the next time you’re in your neighborhood bookstore, it might be worth your while to check it out. It’s nice, too, because the book deals with Windows XP and Windows Server 2003. I feel that we Scripting Guys helped jumpstart system administration scripting in Windows, but then we kind of dropped the ball by not following up our Windows 2000 book with an XP/2003 book. I think it’s great that people like Jeff are picking up the slack for us.

     

    By the way, seeing as how the other Scripting Wieners – um, Scripting Guys have chosen to remain silent, I’d be interested in hearing about books that the rest of you have found interesting. If you have a favorite or two, by all means, let us know.

     

  • Useful Scripts? Please: Don't Ask

    As I’ve noted before, Microsoft really isn’t anything at all like its reputation. For example, we’re supposed to be the ruthless corporate bulldozer that simply crushes any human being that dares get in our way; in truth, though, we are probably the most politically-correct and overly-sensitive company in the history of the universe. Take our documentation (please!). In the Windows 2000 Scripting Guide, for example, I had a sentence that read something like this:

     

    Learning to write scripts is no different than learning to play baseball: if you want to be good at it, you have to be willing to practice.

     

    Not the exact sentence, but you get the idea.

     

    So what’s wrong with that? Well, supposedly, soccer is the most popular sport in the world; therefore, I couldn’t use the word baseball. Why? Because soccer fans would somehow be offended. I was told it was OK to use the word soccer, but that didn’t make a lot of sense to me: after all, wouldn’t baseball fans then be offended? In the end, we just yanked the sentence altogether. (I mean, not that it was a great sentence or anything. It was just the principle of the thing.)

     

    In another place in the book I said something along these lines:

     

    In many respects, choosing a scripting language is similar to choosing a car: the model you pick depends on what you need to do. If all you need to do is get from Point A to Point B, then it probably doesn’t matter ….

     

    I just realized that this could make for an interesting game show: For $500, tell me what is inappropriate about the preceding paragraph? If you said, “Nothing,” well, sorry, but we do have some lovely parting gifts for you. As was pointed out to me, not everyone in the world owns a car; therefore, we couldn’t use a car as an analogy. When I protested that even people who don’t own cars have likely heard of cars, the reply was, “Maybe. But you don’t know that for sure, do you?” Therefore, to avoid offending the one system administrator in the world who can still manage his or her Windows 2000 network despite having never heard of a car, we were supposed to remove this paragraph. (Did we actually remove it? To tell you the truth, I don’t even remember.)

     

    As you might expect, it’s difficult to write a blog under these circumstances. Blogs, by definition, are supposed to be at least somewhat opinionated, but I don’t think the folks around here would be too thrilled if I started ranting and raving about the burning issues of the day. Therefore, I won’t bring up the fact that the Washington men’s basketball team whipped top-ranked and previously-unbeaten Stanford 75-62 on Saturday. And I won’t mention that the Huskies, who also beat Arizona twice this year, finished second in the Pac-10 with a 12-6 record. Nor will I mention that sports commentators seem to universally believe that the UW does not deserve a bid to the NCAA basketball tournament. Why? Well, for heaven’s sake, if we let the second-place team from the Pac-10 in, then we might not have room for the eighth-place team from the ACC! Good grief; what kind of a tournament would it be if we didn’t allow in a team that managed to finish 8th in a 9-team conference? That’s right: a travesty.

     

    But although I have strong feelings about all this, you won’t hear a peep out of me. No, sir.

     

    In the spirit of uncertainty surrounding the Huskies’ chances of going to the NCAA tournament (hopefully they’ll just win the Pac-10 tournament, and then the NCAA will have to let the Huskies in), I present a couple of scripts I’ve had lying around for years (I think they were originally written by my great-great-great-great-grandfather, and have been passed down through the family for generations). A long time ago, I somehow or another stumbled upon the Shell.LocalMachine COM class, and discovered you could write a script to get some interesting information about the local computer:

     

    Set objComputer = CreateObject("Shell.LocalMachine")

    Wscript.Echo "Computer name: " & objComputer.MachineName

    Wscript.Echo "Shutdown allowed: " & objComputer.IsShutdownAllowed

    Wscript.Echo "Friendly UI enabled: " & objComputer.IsFriendlyUIEnabled

    Wscript.Echo "Guest access mode: " & objComputer.IsGuestAccessMode

    Wscript.Echo "Guest account enabled: " & _

        objComputer.IsGuestEnabled(0)

    Wscript.Echo "Multiple users enabled: " & _

        objComputer.IsMultipleUsersEnabled

    Wscript.Echo "Offline files enabled: " & _

        objComputer.IsOfflineFilesEnabled

    Wscript.Echo "Remote connections enabled: " & _

        objComputer.IsRemoteConnectionsEnabled

    Wscript.Echo "Undock enabled: " & objComputer.IsUndockEnabled

     

    How useful is this? I don’t know, but some of it looks like it might be applicable to system administrators. (For example, off the top of my head, I’m not sure how else to determine whether or not offline files or remote connections are enabled on a machine.) This class also has a couple of methods that make it really easy to enable and disable the Guest account. For example, here’s a script that enables the Guest account:

     

    set objComputer = CreateObject("Shell.LocalMachine")

    objComputer.EnableGuest(1)

     

    And here’s one that disables the Guest account:

     

    set objComputer = CreateObject("Shell.LocalMachine")

    objComputer.DisableGuest(0)

     

    Are these the coolest bits of scripting code you’ll ever see? Hey, I don’t want to offend anyone, so I have no opinion whatsoever. They are what they are.

     

    Here’s one I’m even less sure about. It tells you the name of the Passport account currently in use, as well as the member services URL for that Passport account:

     

    Set objUser = CreateObject("UserAccounts.PassportManager")

    Wscript.Echo "Current passport: " & objUser.CurrentPassport

    Wscript.Echo "Member services URL: " & objUser.MemberServicesURL

     

    What would you use something like this for? Well, that’s entirely up to you; my job is just to pass along crazy little tidbits of information like this.

     

    And one final script, just for the heck of it. This one returns the name and Product ID (PID) for all the Microsoft applications installed on a computer. Useful or not useful? Hey, we report, you decide:

     

    Set objMSInfo = CreateObject("MsPIDinfo.MsPID")

    colMSApps = objMSInfo.GetPIDInfo()

     

    For Each strApp in colMSApps

        Wscript.Echo strApp

    Next

     

    By the way, I think these are Windows XP-only scripts. I hope those of you who don’t have Windows XP aren’t too upset by this. If you are, feel free to complain; just get in line behind the soccer fans and the system administrators who have never heard of cars before.

     

     

  • The ... Joys ... of Scripting

    Yesterday was an interesting day. I went into the little editor they have for this blog site, and – like I always do – copied the day’s entry out of Word and pasted it into the editor. Everything looked hunky-dory, so I clicked the Submit button, logged out, and went back to work.

     

    A little while later, I got a couple of emails telling me that the bottom half of the article was unreadable. That’s nothing new; heck, most of the things I write are unreadable. When I went and looked at the blog, though, it turns out that it really was unreadable: words and sentences were cut in half, margins were out of whack, there was a weird grey box in the middle of the post, etc. All in all, pretty dang weird. I assumed the problem was with some HTML code that I had included in the post, so I tried taking that out and re-posting the article. That didn’t help: even with the HTML removed, I got the same screwy results. I put the HTML back in; same thing. Took the HTML out – well, you guessed it.

     

    At that point I decided to try andedit the HTML of the article itself. Holy smokes; what a bad idea that was! Turns out that this blog uses Microsoft Word-like (in other words, crazy) HTML. For example, I would have thought the HTML for the first paragraph of this post would look something like this:

     

    {P}Yesterday was an interesting day. I went into the little editor they have for this blog site, and – like I always do – copied the day’s entry out of Word and pasted it into the editor. Everything looked hunky-dory, so I clicked the Submit button, logged out, and went back to work.{/P}

     

    Note. To try to avoid problems, I’m using curly braces like these {} rather than traditional HTML tags, at least until I figure out how this all works.

     

    Instead, it looks like this:

     

    {P class=MsoNormal style="MARGIN: 0in 0in 0pt"}{SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"}Yesterday was an interesting day. I went into the little editor they have for this blog site, and – like I always do – copied the day’s entry out of Word and pasted it into the editor. Everything looked hunky-dory, so I clicked the Submit button, logged out, and went back to work.{/SPAN}{/P}
    {P class=MsoNormal style="MARGIN: 0in 0in 0pt"}{SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"}{?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /}{o:p}{/o:p}{/SPAN> {/P}

     

    Every individual line in the sample HTML code I posted was surrounded by paragraph tags and span tags and style and font parameters and, well, it was all very … interesting …. And so I tried dutifully to edit each line. I’d make the changes, click the Submit button … and all the weird formatting and weird tags would get added back in, and I’d be left with an unreadable page once more. Eventually I copied the thing out of the blog editor, pasted it into Word, saved the document as a Word file, reset all the formatting, replaced the HTML tags with curly braces, copied the revised article, and pasted it back into the blog editor. That did the trick, but I still don’t know what went wrong, nor do I know why I wasn’t able to fix it. Yet another thing to put on my to-do list, I guess.

     

    Of course, I should be used to spending my time figuring out why you can’t do something that seems so simple. Last Friday, for example, I got an email from someone in Microsoft, a guy who actually does our logon scripts (and does some pretty slick things, by the way). He had what sounded like a simple request: he needed to find a way to list:

     

    • Internet Explorer add-ins (the things found in C:\Windows\Downloaded Program Files).
    • Microsoft Outlook add-ins.
    • Windows Explorer add-ins.

    He couldn’t figure out how to get at any of these things, and wondered if there was something he was missing. (Actually, what he was missing the first rule of scripting, which is: You can always script anything except what you need to script this very moment.)

     

    As it turned out, he was missing a couple things, though I can’t really blame him for not knowing about them. For example, this script will return the items found in C:\Windows\Downloaded Program Files:

     

    strComputer = "."

    Set objWMIService = GetObject("winmgmts:\\" & strComputer _

        & "\root\cimv2\Applications\MicrosoftIE")

    Set colIESettings = objWMIService.ExecQuery _

        ("Select * from MicrosoftIE_Object")

    For Each strIESetting in colIESettings

        Wscript.Echo "Code base: " & strIESetting.CodeBase

        Wscript.Echo "Program file: " & strIESetting.ProgramFile

        Wscript.Echo "Status: " & strIESetting.Status

        Wscript.Echo

    Next

     

    How come he wasn’t aware of this? Well, look at the WMI class being used: root\cimv2\Applications\MicrosoftIE.MicrosoftIE_Object. No one has ever heard of this class before; as near as I can tell it’s never been documented anywhere. In fact, there are a number of classes in the root\cimv2\Applications\MicrosoftIE namespace that might be useful to people. But, again, no one even knows about them. (We do have some sample scripts in the Script Center that use these classes, but they’re buried in some nebulous category like Computer Management, and it’s no wonder no one ever sees them. But that’s an issue we’ll take up some other time.)

     

    So how did I know about them? Well, a few months ago, when I was bored, I opened up Wbemtest and just started clicking around, seeing what was in there. Root\cimv2\Applications\MicrosoftIE happened to be one interesting namespace I found. (Note: You might not have this namespace and these classes on your machine. I think they are automatically installed along with IE 5.5, but I could easily be wrong about that.) Another interesting namespace is root\WMI. There are a bunch of classes in this namespace, many of which don’t return any data, but others which do return data. For example, there are a lot of classes that start with MSNdis_80211 which return information about wireless networking. I haven’t had a chance to really dig into these and see how useful they are, but they sure look useful. But, again, undocumented. And not because they’re top-secret and confidential, just because, well, they’ve never been documented.

     

    And because I’m running Office 2003, I have a namespace called root\MSApps11. Sure enough, there’s a class in there that lets me get at the Outlook add-ins. (One caveat: this thing won’t return any data unless Outlook is running.) Thus:

     

    strComputer = "."

    Set objWMIService = GetObject("winmgmts:\\" & strComputer _

        & "\root\MSApps11")

    Set colSettings = objWMIService.ExecQuery _

        ("Select * from Win32_OutlookCOMAddin")

    For Each strSetting in colSettings

        Wscript.Echo "GUID: " & strSetting.GUID

        Wscript.Echo "Path: " & strSetting.Path

        Wscript.Echo "Name: " & strSetting.Name

        Wscript.Echo "Installed: " & strSetting.Installed

        Wscript.Echo

    Next

     

    Once more, undocumented, even though there are classes in there for all the Office apps. (Again, one problem with these is that the apps typically have to be running before you can get at the data.) Useful stuff? I can't say for sure. But some of it looks very useful. (Like, say, being able to know what Outlook add-ins people have installed on their computers.)

     

    I never did find a way to get at Windows Explorer add-ins, but that doesn’t mean there isn’t one, it just means I haven’t stumbled across it.

     

    Obviously this is a problem: there are millions of unwritten scripts lying around simply because people don’t know they can even write those scripts. We get emails all the time from people asking, “How can I know what things I can script on my computer?” or “Can you point me to the one spot where I can find information about all the object models and all the things I can script?” The truth is, we don’t have an answer for them. (Well, unless you consider, “You can’t” or “No” as answers.) This is something we’d love to address in some way, but we haven’t yet come up with anything that seemed reasonable. In the meantime, don’t be afraid to open up Wbemtest and poke around. Likewise, there’s an object browser for scripting called TLViewer that can be useful (though it does have a few quirks). And, of course, the Object Browser in Visual Studio is pretty handy, though buying Visual Studio just to look at a few COM classes might be overkill. I’d be interested in hearing how other people hunt down scriptable items, and any suggestions you might have for ways we can make these items more discoverable to people.

     

    As for me, I’ve got HTML fish to fry.

     

More Posts Next page »

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker