A Compileable MOF File
While examining the syntax and semantics of the MOF language by reading examples is an important part of the learning process, it is far more beneficial to gain practical experience through typing and compiling your own examples. Type the following MOF file, which is based upon the previous examples, and follow the instructions to compile it. After you are confident with this process, then experiment and alter sections of the file to see the results.
In the example, we shall create our own namespace, to avoid cluttering any existing system namespaces. Microsoft recommends using the root/default namespace in developing schemas, although we shall create our own in this example.
To write a MOF file, you will need a simple ASCII text editor, such as Microsoft's WordPad or Notepad.
If you have Microsoft Developer Studio, you can configure the settings under Tools/Customize/Tools so the development environment will compile a MOF file for you. For more information, see Microsoft's Learn WMI tutorial at http://msdn.microsoft. com/downloads/sample.asp?url=/msdn-files/027/001/574/msdncompositedoc.xml.
First, open your ASCII text editor or Developer Studio. Within the window, type the MOF text in Figure 4.11.
Figure 4.11 A compilable MOF (part 1 of 2)
The initial #pragma classflags("forceupdate") directive tells the compiler to update any existing class definitions in the CIM repository that match those with the class definitions supplied in this MOF file and to resolve conflicts where possible. The update process applies to properties, methods, and qualifiers contained within a class. If the changes within a class are extensive, then it is always better first to delete the existing class from the repository and then to compile the new one. Be aware, however, that doing this deletes all child class definitions!
The CIM repository employs inheritance, which leads to some very real consequences when adding new classes to the repository. For example, replacing an existing class in the hierarchy or changing one of the qualifiers in an existing base class can have direct consequences to the later classes.
Consider a parent class, Storage, and a child class, CDROM. Imagine that the child class is defined with the class qualifier Write set to true. If we try to add base class, Storage, with the class qualifier, Read, set to true, a conflict exists between the child class's qualifier and the base class. In this instance, with the forceupdate flag specified, WMI would remove the qualifier from the child class to make way for the base class. The only situation in which this would not occur is if the child class has instances. If the specified flag were safeupdate, then the update would fail at that point because of the conflict with the child class.
In addition to the forceupdate flag, a number of additional settings exist to resolve conflicts when adding classes. You can combine these options, although you should avoid combining two options that effectively cancel each other out, such as updateonly and createonly. The available options follow.
forceupdate. Upon conflict with existing classes, override this option with new settings. It fails if child classes have instances.
safeupdate. This option allows a safe update of the classes. Do not override existing settings with new settings.
updateonly. This option updates existing classes only. It fails if the classes do not already exist in the target namespace.
createonly. This option adds new classes only. It fails if classes already exist in the repository.
The second #pragma namespace( ) (see Figure 4.12) tells the compiler to place any classes or instances following the statement into the root namespace on the host machine. The instance declaration of type class __namespace tells the compiler to create a new namespace instance. This tells WMI to create a new namespace in the CIM repository with the value assigned to the name property. The __namespace class in the root namespace is a WMI system class that WMI uses to store all the namespaces held in the CIM repository. We have assigned the key property name a value of Example1. The CIM repository now has an additional namespace into which we shall place our example classes.
Figure 4.12 The CIM repository with the new namespace, Example1
In Figure 4.13, this section of the MOF file starts by instructing the compiler to place all of the new classes and instances into the newly created Example1 namespace. It does this by specifying #pragma namespace ("\\\\.\\Root\\Example1"). In experimenting with new classes and associations within the CIM repository, it is good practice to keep all example classes away from the important systems management classes (such as those stored in the CIMV2 namespace) where they could accidentally cause problems. We do this by placing them in a separate namespace. When you have tested them and are satisfied that they are correct, you can merge them back into your target namespace (for example, the CIMV2 namespace).
Figure 4.13 A compileable MOF (part 2 of 3)
The next statement declares an abstract base class called MySchema_Storage. This class has a single property called DeviceId, which is declared as both a read-only property and the key property. The read-only qualifier signifies that the value of the property cannot be changed after the instance has been created. From the perspective of a client application, this means that the value of this property cannot be altered. This property also is flagged as a key value because it will uniquely identify instances of the class.
Now type the code in Figure 4.14.
Figure 4.14 A compileable MOF (Part 3 of 3)
Congratulations! You have created your first namespace, added classes to it, and created an instance of a class within the CIM repository.
At this point, you could have used the MOF generator wizard that is part of the WMI Developer Studio to compile your sample MOF file into the CIM repository. We shall look at using the wizards in more detail in Chapter 5.