Download source files - 168 Kb
Overview
When developing
COM Objects, I often wished to have something similar to VB's Properties- or
Debug-window to retrieve or interactively change an object's current properties at runtime. There exists a small
number of little demo apps (like the AtlCon sample in MSDN) about property browsing, but in general those were not functional enough for me
- one cannot browse properties which take one or more extra parameters (not
just setting/returning one value), one cannot invoke methods, one can only
browse a COM object's default interface (although most objects do implement more
than one interface), and one can only do the browsing during design time.
To circumvent those restrictions, I implemented
three
ActiveX controls doing the job for me (see screenshots above):
One for browsing through an
object model hierarchy (example above: MS Word), one for browsing all implemented
interfaces (restriction: only registered interfaces described in a typelib
are listed) of a specified object (example above: a MS ProgressBar control
on a VB-Form), and one for browsing an objects current property
values and interactively change (i.e. invoke) the objects properties and methods
(example above: MS Word's "Normal Template" object).
Furthermore, the
source code for the controls shows how to retrieve Type Information via the Type
Description Interfaces ITypeInfo
, ITypeLib
, etc. and the Type
Information structures (see MSDN: PlatformSDK/Component
Services/COM/Automation).
Control
Description
1. Running Object
Table Browser Control
This control enables the browsing through an
object model hierarchy similar to
VB's Debug-window in a treeview. There are two 'categories' of objects
to be browsed: objects registered in the "Running Object Table" (see
MSDN) and objects added either programmatically or interactively through Drag 'n
Drop from
the "object browser control" or the "Invoke Dialog" (see "4.
Drag and Drop" below). Clicking the right mouse button inside the control
shows the following context menu:
The command Refresh ROT first clears the category
"Running Object Table", then enumerates all objects registered in the
Running Object Table and adds them to this category. The first available object
is automatically selected as the active item. The objects default interface is
scanned for properties returning further objects, thus building the object model
hierarchy (just like in VB with the "dot", e.g. App.Documents.Item(1) ...).
With the command
Refresh Object you can update this
hierarchy for the currently selected object. This is needed if one of the
properties building the hierarchy changed, i.e. returns an object other than the
already retrieved one, and for collection objects as well, when the collection
itself changed.
The command Remove Object finally removes the selected object from the control's list.
Naturally, this command is only available for 'root' objects.
The currently
selected object changes each time the user activates a treeview item with the
mouse.
2. Interface
Browser Control
This control lists all implemented interfaces of a
specified object which are registered in the registry AND described in a Type library.
Note: Almost all
'standard' interfaces defined by Microsoft (e.g. the IOleXXX
interfaces) aren't
described in a Typelib, therefore those interfaces won't be listed. Obviously,
Microsoft didn't want to give access to those interfaces via Automation.
Nevertheless, you can find quite a few Typelibs describing those
interfaces in the net (e.g. Eduardo A. Morcillo 's site).
When the user activates one of the listed interfaces
with the mouse, a special technique for wrapping the object for this interface
is exploited (see Chris Sell 's site "How do I expose multiple interfaces
to scripting clients - Use a separate object to perform QI"). The wrapped object
then exposes this interface for automation. Giving the Object Browser
Control the wrapped object, one can browse the methods/properties of this
interface instead of the objects default interface. Note that this feature
isn't available in VB (and I didn't find it in any other application etc. in the
net...).
3. Object Browser
Control
This control is a
somewhat extended combination of VB's Properties-and Debug-window. It
lists ALL methods and properties (hidden and restricted ones, regardless of the
number of parameters) of a given object. 'Normal', hidden and restricted
methods/properties can be distinguished by different types of icons displayed in
front of the method/property-name. Read write-properties can be interactively
edited within this control (see below), provided the property takes only one
parameter (just like VB's Property window). For read-only and
read/write-properties
taking only one parameter (i.e. the 'retval' for read-only properties), the
current properties value is displayed. (Note: VB's Property window displays only
read/write properties).
Clicking the right
mouse button within the control displays the following context menu:
The command Refresh updates all
properties of the browsed object.
With the commands
Show Hidden Members and Show Restricted
Members one can determine wether hidden and restricted
methods/properties should be browsed. The command Group Members
sorts all methods/properties, otherwise those are displayed in the order given
by the objects Type Information.
If the object can be
edited on a property page (i.e. the object needs to support ISpecifyPropertyPages
, see MSDN), the command View Property pages
shows a (modal) property sheet with all the property pages specified by the object. In case the currently activated (i.e. the highlighted
one) method/property in this control can be mapped to a special property page,
the command View Property page shows a (modal)
property sheet with only this special propert ypage. For this to work, the object needs to
implement the IPerPropertyBrowsing
interface as well (again, see MSDN).
The commands Execute Method,
Execute Get-Property and Execute Put-Property open the
following on-modal dialog:
With this dialog, one can invoke methods and properties
which take more than one parameter. In the listview Required Parameters
one needs to specify each of the parameters needed to call
the method/property (see editing below). Clicking the Button
Invoke finally calls the method/property. If the call succeeds
and returns a value, this value is displayed in the field Return
Value,
otherwise a message box describing the error is displayed. In case the return
value is a COM-Object, you can start a Drag 'n Drop operation through clicking
inside this field and 'dragging' the object e.g. into the Object Browser or
Running Object Table Browser control.
The editing of values in the above dialog and in the
control itself is done in a similar way: clicking inside
theValue column starts the editing, changing the
focus to somewhere else ends the editing.
The type of
editing depends on the type of the value to be edited and is is determined in
the following order:
If one wants to edit a property value inside the control
itself, and the property supports PerPropertyBrowsing
(see MSDN), a
combobox with the supported strings is displayed (Note: this doesn't apply
to the dialog). If the value is of a type defined in a typelib (e.g. an
enum), a combobox is displayed listing all available values. If the value is a
boolean type, a combobox with "True" and "False" is displayed. If the value is a
COM-Object itself, 'normal' editing isn't available, you need to set the value
with a Drag 'n Drop operation; a text "<Valid Object>" will be displayed.
All other editing is done through displaying an editbox
and text-editing.
When finishing editing a read/write-property in this control, the put-property is
automatically invoked. If it fails, a message box is displayed, and the
properties current value is updated and displayed.
4. Drag and Drop
The Running Object
Table Browser control as well as the Object Browser control and the Invoke
dialog support "Drag 'n Drop operations of COM-Objects". This is necessary since
many methods/properties take at least one parameter of that type, and I didn't
find a easier way to specify those parameters.
In the Running Object Table Browser you can drag one of the listed
objects through pressing the mouse button on it and moving the mouse while keeping
the button pressed. In the Object Browser control, such an
operation is initiated when you select the text "<Valid Object>" in the
column Value, and in the Invoke dialog, when you select the
same text in the Return Value
edit field.
When dropping in the Running Object Table Browser, the object is added to the
Added Objects category, from where its hierarchy can be
browsed. In the Object Browser control, dropping is only allowed over the
Value column, when the corresponding property is read/write and
the property takes only one argument of type "COM-Object". This will
automatically invoke the property with the dropped object. In the Invoke dialog,
dropping is only allowed over the Value column of the
Required Parameters listview, when the
corresponding parameter needs to be of this type.
Implementation
Notes
The controls do not
implement every possible data type browsing. For example, interactively
setting or browsing a parameter of type SAFEARRAY isn't supported; problems
occur as well when the type is a pure VARIANT (those parameters are always
handled as strings). If something isn't working as expected, you should run the
controls in debug mode, an assertion should occur each time a unsupported data
type is encountered.
As with almost all
projects as this, there are some known and surely several unknown bugs. One
problem e.g. occurs when browsing MS Word - after closing the Demo VB
Application, Word crashes when closing.
The interface/object wrapping done by the Interface Browser control is
achieved by several COM objects implemented in the DispAdapter DLL. This DLL has
been developed by Vlad Volkov and Dave Rogers. I found the link to the code for
it at Chris
Sell 's site, but this link isn't valid any more.
Since i'm not 100% sure about the copyright for the code, I do only include the
DLL as a binary with no source code.
If you want to
debug/browse your own application build on a COM Object model with the supplied
Demo VB application, you need to register your application object in the
running object table via the "RegisterActiveObject" API function.
The source code is
pretty much undocumented. I know that's a big mistake, but my job takes too much
time, and documentation is very much time-eating....
Demo VB
Application
I included a small
VB executable demonstrating the combined usage of the three controls. In most cases, this should be sufficient for debugging/testing
purposes.
In order to be able to run the application, you have to
register the DispAdapter.dll and the ObjectBrowser.dll using
regsvr32.exe.