• No results found

In this lab, you are going to delete the folders created in Lab 14. 1. Open Notepad.exe.

2. Open your solution to Lab 14, or open Lab14Solution.vbs from the companion CD.

3. Copy all the Header information section from Lab 14. The code will look like the following:

Option Explicit Dim numFolders Dim folderPath Dim folderPrefix Dim objFSO Dim objFolder Dim i

4. Copy the Reference section of the script from Lab 14. The code will look like the following:

numFolders = 10 folderPath = “C:\" folderPrefix = “Student”

5. Implement a For...Next loop, using the variable i that goes to the variable num-

Folders. You can copy the following line from Lab 14 as well:

For i = 1 To numFolders

6. Create an instance of FileSystemObject. Use the CreateObject method, and assign it to the variable objFSO. This line is also in Lab 14 and looks like the following: Set objFSO = CreateObject(“Scripting.FileSystemObject”)

7. Use an If...Then loop that incorporates the folderExists method to determine whether the folder is present prior to deleting it. If the folder does exist, echo out the path. This code is present in Lab 14 and looks like the following:

If objFSO.FolderExists(folderPath & folderPrefix & i) Then WScript.Echo(folderPath & folderPrefix & i & “ exists.”)

8. Use the DeleteFolder method of FileSystemObject to delete the folder if it is present on the system. You will need to build the name of the folder by using the folder- Path variable, folderPrefix, and the counter i. The code to do this looks like the following:

objFSO.DeleteFolder(folderPath & folderPrefix & i)

9. Use WScript.Echo to echo out that the folder was deleted, as illustrated here:

WScript.Echo(folderPath & folderPrefix & i & “ was deleted”)

10. The Else clause implements a simple WScript.Echo command that indicates the folder does not exist on the system. The code for this looks like the following: Else

WScript.Echo(folderPath & folderPrefix & i & “ does not exist”)

11. End your If...Then loop by using End If. 12. End the For...Next loop by using Next.

Option Explicit Dim numFolders Dim folderPath Dim folderPrefix Dim objFSO Dim objFolder Dim i numFolders = 10 folderPath = “C:\" folderPrefix = “Student" For i = 1 To numFolders

Set objFSO = CreateObject(“Scripting.FileSystemObject”) If objFSO.FolderExists(folderPath & folderPrefix & i) Then

WScript.Echo(folderPath & folderPrefix & i & “ exists.”) objFSO.DeleteFolder(folderPath & folderPrefix & i)

WScript.Echo(folderPath & folderPrefix & i & “ was deleted”) Else

WScript.Echo(folderPath & folderPrefix & i & “ does not exist”) End If

143

8

Why Windows Management

Instrumentation?

The discussion in the first few chapters of our book focused on what you can do with

Microsoft Visual Basic Script (VBScript). From a network management perspective,

many useful tasks can be accomplished using just VBScript, but to truly begin to

unleash the power of scripting, you need to bring in additional tools. This is where

Windows Management Instrumentation (WMI) comes into play. WMI was designed to

provide access to many powerful ways of managing Microsoft Windows systems. In

Windows Server 2003, WMI was expanded to include management of many aspects of

server operations, including both configuration and reporting capabilities of nearly

every facet of the server. Some of the tasks you can perform with WMI follow:

■ Report on drive configuration

■ Report on available memory, both physical and virtual

■ Back up the event log

■ Modify the registry

■ Schedule tasks

■ Share folders

■ Switch from a static to a dynamic IP address

Before You Begin

The material presented in this chapter assumes you are familiar with the following concepts from earlier chapters:

■ Implementing a dictionary

■ Implementing the For…Next construction

■ Implementing Select Case constructions

After completing this chapter you will be familiar with the following: ■ Connecting to the WMI provider

■ Navigating the WMI namespace

■ Running queries to retrieve information from WMI

What Is WMI?

WMI is sometimes referred to as a hierarchical namespace, in which the layers build upon one another like an LDAP directory used in Active Directory, or the file system structure on your hard disk drive. Although it is true that WMI is a hierarchical namespace, the term doesn’t really convey the richness of WMI. The WMI model has three sections that you need to be aware of:

WMI resources Resources include anything that can be accessed by using WMI—the file system, networked components, event logs, files, folders, disks, Active Directory, and so on.

WMI infrastructure The infrastructure comprises three parts: the WMI service, the WMI repository, and the WMI providers. Of these parts, WMI providers are most important because they provide the means for WMI to gather needed information.

WMI consumers A consumer “consumes” the data from WMI. A consumer can be a VBScript, an enterprise management software package, or some other tool or utility that executes WMI queries.

An Object in Any Other Namespace…

Let’s go back to the idea of a namespace introduced earlier in this chapter. You can think of a namespace as a way to organize or collect data related to similar items. Visualize an old-fashioned filing cabinet. Each drawer can represent a particular namespace. Inside this drawer are hanging folders that collect information related to a subset of what the drawer actually holds. For example, at home in my filing cabinet, I have a drawer reserved for information related to my woodworking tools. Inside this particular drawer are hanging folders for my table saw, my planer, my joiner, my dust collector, and so on. In the folder for the table saw is information about the motor, the blades, and the various accessories I purchased for the saw (such as an over-arm blade guard).

The WMI namespace is organized in a similar fashion. (However, you will not neces€ sarily find a table saw folder.) Rather, namespaces contain objects, and these objects contain properties you can manipulate (and as Will Rogers once said, “manipulation is good”). Let’s use a WMI script, ListWmiNameSpaces.vbs, to illustrate just how the WMI namespace is organized.

strComputer = “."

Set objSWbemServices = GetObject(“winmgmts:\\” & strComputer & “\root”) Set colNameSpaces = objSwbemServices.InstancesOf(“__NAMESPACE”)

For Each objNameSpace In colNameSpaces WScript.Echo objNameSpace.Name Next

On a Windows 2003 Server, the results would look like the following: SECURITY perfmon RSOP Cli MSCluster WMI CIMV2 MicrosoftActiveDirectory Policy MicrosoftDNS MicrosoftNLB Microsoft DEFAULT directory subscription

So what does all this mean, you ask? It means that on a Windows 2003 server, there are more than a dozen different namespaces from which you could pull information about our server. Understanding that the different namespaces exist is the first step to being able to navigate in WMI to find the information you need. Often, students and people new to VBScript work on a WMI script to make the script perform a certain action, which is a great way to learn scripting. However, what they often do not know is which namespace they need to connect to so that they can accomplish their task. When I tell them which namespace to work with, they sometimes reply, “It is fine for you, but how do I know that the such and such namespace even exists?” By using the ListWMInamespaces.vbs script, you can easily generate a list of namespaces installed on a particular machine, and armed with that information, search on MSDN to see what information it is able to provide.

Let’s discuss the preceding script, ListWmiNameSpace.vbs, because it’s similar to many other WMI scripts. The first line sets the variable strComputer equal to ".". This con€ struction (period in quotation marks) means that the script will operate against this computer only. The period therefore is a wildcard character that allows the script to run locally on many computers without you needing to define or change the name included in the script.

The next line of the script is used to define the variable objsWebmServices and set it equal to the handle that is returned by using the getObject method to connect to Win-

Mgmts and access the root namespace on the local computer. (The connection string in

WMI is sometimes referred to as a moniker. The word moniker comes from Gaelic and simply means nickname, or familiar name.) We will discuss the WMI moniker in much more detail in Chapter 9, “WMI Continued.” These first two lines of the script can be reused time and again in many WMI scripts. In the third line of the script, you use the

Set command to assign colNameSpaces to be equal to a collection represented by the instances of the command that query for the presence of the word “_NameSpace”. The

Worker information section of the script simply uses a For Each...Next loop to iterate through the collection of namespaces returned by the query and to echo them out to the screen.

Tip Although in the ListWMInamespaces.vbs script, I used all lowercase in code for the win3

mgmts name. There really is no requirement for name case with this particular moniker, and in

the Microsoft Platform SDK you will find nearly every possible combination: winmgmts, WinM3

mgmts, WINMGMTS, and I bet even winMgmts.

Keep in mind, however, that name case does matter with some monikers such as “WinNT:”.

More Than Just a Name

Knowing the default namespaces gives some information, and though helpful, to better map out the WMI namespace, you’ll want information about the subnamespaces as well. You’ll need to implement a recursive query so that you can gain access to the subnamespace data. The next script, RecursiveListWmiNameSpace.vbs, is similar to ListWmiNameSpace.vbs except that it utilizes a subroutine to enable it to perform a re- entrant query. On some computers, this script might seem to perform a little slowly during the first running, so I included a WScript.Echo (Now) command at the beginning and at the end of the script. This allows the network administrator to determine how long the script takes to run.

As with the previous script, RecursiveListWmiNameSpace.vbs uses strNameSpace with a "." to indicate the script is run against the local computer. It then calls the subroutine named EnumNameSpaces and starts with the “root” namespace. Subroutines are dis€ cussed in detail in Chapter 15, “Subs and Other Round Things,” but I wanted to use one in this script, because it adds a lot of power and flexibility.

Subroutines

Basically, a subroutine is a section of a script that you can get to from anywhere inside the script. All we need to do is call the subroutine by name to jump to a particular part of the script. You use a subroutine in this script rather than code that is sequential (as all our other scripts have used so far) because you need to execute the commands that make up the subroutine as a group. When you are finished, you exit out. You can easily identify a subroutine because it begins with the word Sub followed by the name of the subroutine, and it ends with the end sub command. When you exit a subroutine (via the end sub command), you go back to the line after the one that caused you to enter the subroutine.

Once you enter the subroutine, you echo strNameSpace, which on the first pass is sim€ ply the root. Next you use GetObject to make a connection to the WMI namespace that is identified by the subroutine strNameSpace argument. In the first pass, you are con€ nected to the root. The subroutine then retrieves all namespaces that are immediately below the one it is currently connected to. You then use a For Each…Next construction to loop through all the namespaces below the currently connected one. In doing so, you also concatenate the names to provide a fully qualified name to the namespace. You take the newly constructed name, pass it to EnumNameSpaces, and work through the namespace one more time.

WScript.Echo(Now) strComputer = “." Call EnumNameSpaces(“root”) Sub EnumNameSpaces(strNameSpace) WScript.Echo strNameSpace Set objSWbemServices = _

GetObject(“winmgmts:\\” & strComputer & “\” & strNameSpace) Set colNameSpaces = objSWbemServices.InstancesOf(“__NAMESPACE”) For Each objNameSpace In colNameSpaces

Call EnumNameSpaces(strNameSpace & “\” & objNameSpace.Name) Next

End Sub

WScript.Echo(“all done “ & Now)

Providers

Understanding the namespace assists the network administrator with judiciously apply€ ing WMI scripting to his or her network duties. However, as mentioned earlier, to access information via WMI, you must have access to a WMI provider. Once the pro€ vider is implemented, you can gain access to the information that is made available. The following script, ListWmiProviders.vbs, enumerates all the WMI providers instru€ mented on the machine. This information can lead the network administrator to MSDN or some other place to find details about the methods supported by the provider. strComputer = “."

Set objSWbemServices = _

GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)

Set colWin32Providers = objSWbemServices.InstancesOf(“__Win32Provider”)

For Each objWin32Provider In colWin32Providers WScript.Echo objWin32Provider.Name

When you run the script on Windows 2003 Server, you get the following output: Win32_WIN32_TSLOGONSETTING_Prov MS_NT_EVENTLOG_PROVIDER Win32_WIN32_TSENVIRONMENTSETTING_Prov SCM Event Provider ProviderSubSystem VolumeChangeEvents NamedJobObjectLimitSettingProv HiPerfCooker_v1 WMIPingProvider Win32_WIN32_TSNETWORKADAPTERSETTING_Prov SystemConfigurationChangeEvents Win32_WIN32_TERMINALSERVICE_Prov MSVDS__PROVIDER Win32_WIN32_TSREMOTECONTROLSETTING_Prov Win32_WIN32_TSNETWORKADAPTERLISTSETTING_Prov Win32_WIN32_COMPUTERSYSTEMWINDOWSPRODUCTACTIVATIONSETTING_Prov Win32_WIN32_TSSESSIONDIRECTORY_Prov CmdTriggerConsumer

Standard Non-COM Event Provider

SessionProvider WBEMCORE RouteEventProvider WhqlProvider Win32_WIN32_TSSESSIONSETTING_Prov Win32_WIN32_TERMINALTERMINALSETTING_Prov Win32_WIN32_TSCLIENTSETTING_Prov Win32_WIN32_TERMINALSERVICESETTING_Prov

WMI Kernel Trace Event Provider

Win32_WIN32_PROXY_Prov NamedJobObjectProv MS_Shutdown_Event_Provider SECRCW32 Win32ClockProvider MSVSS__PROVIDER MS_Power_Management_Event_Provider Win32_WIN32_WINDOWSPRODUCTACTIVATION_Prov RouteProvider Cimwin32A Msft_ProviderSubSystem Win32_WIN32_TERMINALSERVICETOSETTING_Prov NamedJobObjectSecLimitSettingProv Win32_WIN32_TSSESSIONDIRECTORYSETTING_Prov Win32_WIN32_TSPERMISSIONSSETTING_Prov Win32_WIN32_TSACCOUNT_Prov Win32_WIN32_TERMINAL_Prov DskQuotaProvider Win32_WIN32_TSGENERALSETTING_Prov CIMWin32 NamedJobObjectActgInfoProv NT5_GenericPerfProvider_V1

WMI Self-Instrumentation Event Provider

DFSProvider

Adding a Touch of Class

In addition to working with namespaces, the inquisitive network administrator will also want to explore the concept of classes. In WMI parlance, you have core classes and you have common classes. Core classes represent managed objects that apply to all areas of management. These classes provide a basic vocabulary for analyzing and describing managed systems. Two examples of core classes are parameters and the sys3

temSecurity class. Common classes are extensions to the core classes and represent

managed objects that apply to specific management areas. However, common classes are independent from a particular implementation or technology. The CIM_Unitary-

ComputerSystem is an example of a common class. Core and common classes are not

used as much by network administrators because they serve as templates from which other classes are derived. Therefore, most of the classes stored in root\cimv2 are abstract classes and are used as templates. However, a few classes in root\cimv2 are dynamic classes used to hold actual information. The important aspect to remember about dynamic classes is that instances of a dynamic class are generated by a provider and are therefore more likely to retrieve “live” data from the system.

A property in WMI is a value that is used to indicate a characteristic (something describ€

able) about a class. A property has a name and a domain that is used to indicate the class that actually owns the property. Properties can be viewed in terms of a pair of functions: one to set the property value and another to retrieve the property value. In addition to properties are methods. As you’ve learned in earlier chapters, a method

answers the question “what does this thing do.” In many cases, the answer is “well, it does nothing.” However, the cool thing about WMI is that it’s constantly evolving—and in Windows Server 2003, more methods have been added than ever before. Like a property, a method also has a name and a domain. And just like a property, the method’s domain refers back to the owning class. One slightly confusing feature of a WMI method is that it can have an overriding relationship with a method from another class. Remember when I said that the domain points to the ownership of a method? Well, ownership can be overridden when the domain from the overridden method is a

SuperClass. It gets even worse.

Note Just because a class has a method does not guarantee that the method is imple- mented. You must verify that the implemented qualifier is attached to the method to ensure the method actually works. (You can do this by looking the method up in the Platform SDK. It will simply say “implemented.”) This is the only way you can ensure that the implementation is actually available for the class. I will admit that I have actually wasted several hours trying to make a particular method work, only to find out it was not even implemented.

The following script, ListWmiClasses.vbs, returns a list of classes found in the

root\cimv2 namespace.

strComputer = “." nSpace = “\root\cimv2" Set objSWbemServices = _

GetObject(“winmgmts:\\” & strComputer & nSpace) Set colClasses = objSWbemServices.SubclassesOf()

For Each objClass In colClasses WScript.Echo objClass.Path_.Path Next

Querying WMI

In most situations, when you use WMI, you are performing some sort of query. Even when you’re going to set a particular property, you still need to execute a query to return a dataset that enables you to perform the configuration. (A dataset is the data that comes back to you as the result of a query, that is, it is a set of data.) In this sec€ tion, you’ll look at the methods used to query WMI.

Just the Steps

� To query WMI

1. Specify the computer name. 2. Define the namespace.

3. Connect to the provider using GetObject. 4. Issue the query.

5. Use For Each...Next to iterate through collection data.

One of the problems with Windows Server 2003 for the small to medium enterprise is Windows Server 2003 product activation. Although the larger customers have the advantage of “select” keys that automatically activate the product, smaller companies often are not aware of the advantages of volume licensing and as a result do not have access to these keys. In addition, I’ve seen larger customers that use the wrong key— you can easily forget to activate the copy of Windows Server 2003. Many customers like to monitor the newly built machine prior to actual activation because of the problems resulting from multiple activation requests. As is often the case with many IT depart€ ments, emergencies arise, and it is easy to forget to make the trek back to the server rooms to activate the machines. This is where the power of WMI scripting can come to the rescue. The following script uses the new Win32_WindowsProductActivation WMI class to determine the status of product activation:

Option Explicit On Error Resume Next dim strComputer dim wmiNS dim wmiQuery dim objWMIService dim colItems Dim objItem strComputer = “." wmiNS = “\root\cimv2"

wmiQuery = “Select * from Win32_WindowsProductActivation"

Set objWMIService = GetObject(“winmgmts:\\” & strComputer & wmiNS) Set colItems = objWMIService.ExecQuery(wmiQuery)

For Each objItem In colItems

WScript.Echo “ActivationRequired: “ & objItem.ActivationRequired