2025-04-27 07:49:33 -04:00

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