244 lines
11 KiB
Plaintext
244 lines
11 KiB
Plaintext
==================================================================
|
|
WMI Client Sample
|
|
==================================================================
|
|
This sample demonstrates various ways to do use WMI features.
|
|
Where multiple ways exist to do the same things, an effort was
|
|
made to show each way. Use the following table of contexts to
|
|
find the technique you want. The implementation of each 'button'
|
|
is in a separate .cpp file to make it easier to deal with. Common
|
|
helper routines are in the SampDlg.cpp file itself. Class-wise,
|
|
all WMI code is in the main dialog.
|
|
|
|
This app is a dialog-based app created by AppWizard and
|
|
using MFC for simplicity. The code is designed to be easy to
|
|
follow and doesn't necessarily show a good practice for building
|
|
'real' WMI client apps. Concentrate on the steps and architect
|
|
your app in a way that makes sense for you.
|
|
|
|
==================================================================
|
|
Build Notes
|
|
==================================================================
|
|
Things to remember when you're building your own WMI client app.
|
|
|
|
1. If you want your client to run on NT and non-DCOM versions of Win95,
|
|
manually load the ole32.dll and see if CoInitializeSecurity() exists.
|
|
This routine wont exist on win95 OS's that dont have DCOM installed
|
|
separately. If this routine doesn't exist, the async routines in
|
|
this sample wont work because of mismatched security level problems.
|
|
The synchronous techniques will still work.
|
|
|
|
2. If you dont care about non-DCOM versions of win95, you can define
|
|
_WIN32_DCOM so that CoInitializeSecurity() is available for implicit
|
|
linking. Don't use _WIN32_WINNT to get this prototype since it
|
|
won't compile under Windows 9x OSs.
|
|
|
|
3. Either way, this call (in InitInstance()) is required to work around a
|
|
security problem when WMI trying to call a Sink object but
|
|
won't identify itself. The CoInitializeSecurity() call turns
|
|
off the authentication requirement.
|
|
|
|
4. WMI interfaces are defined in wbemcli.h and wbemprov.h found in
|
|
the wmi\include directory. You may #include both these files by
|
|
including just wbemidl.h located in the same directory.
|
|
|
|
5. WMI interface CLSIDs are defined in wbemuuid.lib. If you get
|
|
unresolved externals in interfaces and CLSIDs, this is
|
|
what's missing.
|
|
|
|
6. You'll need to link with oleaut32.lib and ole32.lib to get the
|
|
COM stuff.
|
|
|
|
7. In the Link|Output settings, specify 'wWinMainCRTStartup' as the
|
|
entry point. This is per the Unicode programming instructions.
|
|
|
|
8. If you're using the makefiles, don't forget to set the VC vars. In
|
|
VC++ 5.0, its VCVARS32.BAT.
|
|
|
|
==================================================================
|
|
UI Summary
|
|
==================================================================
|
|
Button File Action
|
|
------ ---- ------
|
|
Connect OnConnect.cpp Connects to specified
|
|
namespace.
|
|
|
|
Exit WBEMSampDlg.cpp Exits the app.
|
|
|
|
Enum Disks OnEnumDisks.cpp lists the logical disks.
|
|
|
|
Get C: Disk Details OnDiskDetails.cpp lists C: disk properties.
|
|
|
|
Enum Services OnEnumSvcs.cpp lists the services.
|
|
|
|
Enum Services Async OnAsync.cpp lists the services.
|
|
|
|
Add Equipment OnAddEquipment.cpp adds to a list of office
|
|
equipment.
|
|
|
|
Register Perm OnPerm.cpp registers/unregisters the
|
|
local-server event consumer
|
|
WbemPermConsumer.exe.
|
|
|
|
Register Temp OnTemp.cpp registers/unregisters the
|
|
in-proc event consumer;
|
|
CEventSink in OnTemp.*.
|
|
|
|
About Disk Properties OnDiskPropsDescriptions.cpp lists the description of the
|
|
logical disk class, as well as
|
|
descriptions of all its properties.
|
|
Note that this information is
|
|
localizable and will be displayed in
|
|
the language that corresponds to the
|
|
current user locale on the client
|
|
machine, as long as the server has
|
|
corresponding localized resources.
|
|
|
|
You can connect to remote machines by changing the namespace before
|
|
connecting.
|
|
|
|
The results of actions show up in the upper listbox. Event related
|
|
messages go in the lower listbox. The Permanent Event Consumer is
|
|
a separate app that will start as needed.
|
|
|
|
On Windows 95, no services will list because win95 doesn't have
|
|
services. This is normal.
|
|
|
|
==================================================================
|
|
Task: Connecting to a namespace
|
|
==================================================================
|
|
Implementations:
|
|
OnConnect.cpp shows how to connect to a namespace. This will enable the
|
|
rest of the buttons because they all require the client to be connected.
|
|
\root\cimv2 is the most commonly used namespace since the win32
|
|
schema classes are in it. \root\security is also built-in but it
|
|
only contains security related classes. In this example, the '.'
|
|
(dot) can be replaced with a remote machine's name to connect
|
|
remotely. Dot is used for the local machine.
|
|
|
|
OnAddEquipment.cpp uses OpenNamespace() to connect to root\cimv2\office
|
|
because its UNDER root\cimv2 and relative navigation is possible.
|
|
|
|
==================================================================
|
|
Task: Enumerating classes
|
|
==================================================================
|
|
Implementation:
|
|
OnEnumDisks.cpp creates an enumerator for all instances of disks then
|
|
walks the result list using the 'classic' OLE enumerator scheme.
|
|
Properties are extracted for display.
|
|
|
|
==================================================================
|
|
Task: Enumerating properties
|
|
==================================================================
|
|
Implementation:
|
|
OnDiskDetails.cpp enumerates the properties for your C: drive. It uses
|
|
GetNames() to get a SAFEARRAY of property names which is then using to
|
|
Get() property values directly.
|
|
|
|
==================================================================
|
|
Task: Retrieving (amended) qualifiers
|
|
==================================================================
|
|
Implementation:
|
|
OnDiskPropsDescriptions.cpp lists class description and property descriptions
|
|
for Win32_LogicalDisk class. Note that description qualifiers can be quite lengthy
|
|
and are normally not retrieved, unless WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
|
|
is specified in IWbemServices::GetObject().
|
|
|
|
Object qualifiers are retieved by IWbemClassObject::GetQualifierSet().
|
|
Property qualifiers are retrieved by IWbemClassObject::GetPropertyQualifierSet()
|
|
- you need to supply property name as a parameter.
|
|
|
|
Get() method on the IWbemQualifierSet retrives specific qualifier values -
|
|
in this case, descriptions.
|
|
|
|
Amended qualifiers (such as descriptions) are localizable and
|
|
will be displayed in the language that corresponds to the current user
|
|
locale on the client machine, as long as the server is able to provide
|
|
appropriate localized resources.
|
|
|
|
==================================================================
|
|
Task: Using WQL for queries
|
|
==================================================================
|
|
Implementation:
|
|
OnEnumSvcs.cpp uses ExecQuery() to issue a WQL query to find all
|
|
services running on the machine. It then uses the BeginEnumeration()/
|
|
Next()/EndEnumeration() scheme to walk through the properties for
|
|
each service-- looking for the properties of interest. This is a
|
|
contrived example for demo purposes only. This scheme is normally
|
|
used for displaying ALL properties rather than looking for particular
|
|
ones.
|
|
|
|
==================================================================
|
|
Task: Using WQL for asynchronous queries
|
|
==================================================================
|
|
Implementation:
|
|
OnAsync.cpp does exactly the same thing as OnEnumSvcs.cpp except it
|
|
does it asychronously. ExecQueryAsync() is passed a CAsyncQuerySink
|
|
COM object which implements an IWbemObjectSink. This object has it's
|
|
Indicate() and SetStatus() called for the reesult of the query instead
|
|
of creating an enumerator.
|
|
|
|
==================================================================
|
|
Task: Creating user-defined classes
|
|
==================================================================
|
|
Implementation:
|
|
OnAddEquipment.cpp shows how to create classes and instances. After
|
|
prompting for items in your office, the OfficeEquipment class is
|
|
created if it already doesn't exist then a new instance of the class
|
|
is created for the item you typed into the dialog box. Once the first
|
|
equipment is added, the special namespace will exist and the "Register"
|
|
buttons will enable since they get events from this namespace. The
|
|
namespace must exist before you can register for its events.
|
|
|
|
==================================================================
|
|
Task: Creating instances
|
|
==================================================================
|
|
Implementations:
|
|
OnAddEquipment.cpp creates instances of the user-defined classes.
|
|
|
|
==================================================================
|
|
Task: Creating new namespaces
|
|
==================================================================
|
|
Implementation:
|
|
OnAddEquipment.cpp creates a namespace of root\cimv2\office to
|
|
store the OfficeEquipment class and instances.
|
|
|
|
==================================================================
|
|
Task: Temporary Event Consumers
|
|
==================================================================
|
|
Implementation:
|
|
OnTemp.cpp registers and unregisters temporary events. CEventSink is
|
|
the interface that is called to handle those events. It hooks instances
|
|
of "OfficeEquipment" being created. This is the class defined/used by
|
|
OnAddEquipment.cpp. Temporary events are displayed in the lower listbox.
|
|
|
|
==================================================================
|
|
Task: Permanent Event Consumers
|
|
==================================================================
|
|
Implementation:
|
|
OnPerm.cpp registers and unregisters Permanent events. It hooks the
|
|
same events as OnTemp.cpp so that you can compare and contrast. The
|
|
events are handled by WBEMPermEvents.exe; a separate project under
|
|
wmi\samples\EventConsumer. Events are displayed in this separate
|
|
app. The registry entries required to allow CIMOM to spawn a local
|
|
server which displays to the user's desktop is documented in the
|
|
RegisterServer() routine of that app. You must run 'mofcomp SampleViewer.mof'
|
|
to register the Event Consumer before the Register Perm function
|
|
will work.
|
|
|
|
==================================================================
|
|
Task: Dealing With Security
|
|
==================================================================
|
|
When using temporary events, the CIMOM service calls back to the
|
|
client app. The default security authentication setting doesn't
|
|
allow this call to get through. The client app must lower its
|
|
authentication setting for these callbacks to work. This is
|
|
complicated by the fact that Windows 95 doesn't come with DCOM
|
|
which contains the CoInitializeSecurity() routine (OLE32.dll is
|
|
updated when you install DCOM). The logic for dealing with this
|
|
security issue is in CWbemSampleApp::InitSecurity() in WBEMSamp.cpp.
|
|
|
|
You also must call IClientSecurity::SetBlanket() for any IWbemServices
|
|
or IEnumWbemClassObject. See CWBEMSampleDlg::SetBlanket() in OnConnect.cpp
|
|
for this technique.
|
|
|
|
END readme.txt |