|
|
-
-
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
|
-
-
-
-
-
-
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
|
-
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.
|
-
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.
|
-
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:
- I’m lazy.
- 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.)
- 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
| |
|