DMH.ocx - A Visual Basic DMH Active-X Control
Hume Integration has created an Active-X control for integrating
Visual Basic (VB) programs into a distributed system using the Distributed
Message Hub (DMH) message system. The VB DMH control component
provides high-level methods for sending and receiving messages, with either
send-and-reply synchronous-style interactions, or higher performance asynchronous-style
interactions. Message exchanges are typically directed
to application servers such as the Hume Integration Datahub, or the dmh_SQLsrv
persistent database interface. The DMH message system is remarkably
easy to use with these DMH Tcl processes because the messages are typically
SQL, Tcl, or VFEI text that is directly interpreted by the receiver.
To extend this ease of use to the VB DMH client, methods are provided with
the control to convert Tcl list text strings into native VB data types,
or to create Tcl list text strings from VB data. Also, a method is
provided to convert SEMATECH VFEI formatted text into Dictionary entries.
(The Dictionary class is the native VB associative array. VFEI is
a self-describing, name-equals-value text format that is used for equipment
integration.) The VB DMH Active-X control fully supports peer-to-peer
interactions.
Feature Summary
-
High performance asynchronous message sending and receiving
-
Convenient synchronous send-and-reply server or peer interaction provided
as well
-
Fully compatible with Internationalization
-
Transparent conversion of Unicode <-> UTF-8 International capable character
sets
-
Comprehensive support of DMH message system features such as mailbox manipulation
-
TclSplit( ), ListElement( ), and TclJoin( ) methods provided for convenient
manipulation of Datahub SQL replies or similar Tcl list results in Visual
Basic applications
-
Disconnected events and Error events provided for application recovery
and resume logic
-
Usable in multiple instances for high performance access to multiple DMH
servers
-
Fully integrated with the VB development environment with IntelliSense
specification of methods and parameters, and controllable debug output
-
Fully integrated into the VB runtime environment with high-performance
use of threading, event dispatching, controllable trace output, and error
handling
-
No static maximum sizes for DMH messages
-
VFEI2Dictionary( ) method provided to parse SEMATECH VFEI formatted messages.
User Guide
The DMH Active-X control for Visual Basic is provided as a file,
DMH.ocx,
for the Windows 2000 and Windows NT x86 architecture platform.
The .ocx binary file is provided with a test and demonstration application,
TestDMHProj.exe, along with the test application source code, and project
file. The files are distributed in a .zip archive file, DMHocx.zip.
The documentation files in the archive are copies of the same files that
are incorporated into the main online documentation.
The control is designed to successfully interoperate with any recent
version of the Tcl/Tk DMH software running on any platform.
Installation
If you received the DMH software on CDROM, the DMHocx.zip archive
is found in the subdirectory LAN_IMAGE. The DMHocx.zip distribution
archive needs to be unzipped into a path of your choosing; for example,
c:\usr\local. The archive includes the subdirectory DMHocx, so the complete
pathname to the DMH.ocx file becomes your_path\DMHocx\DMH.ocx. Only
the DMH.ocx file is needed for a runtime deployment. For runtime-only machines,
you may choose to copy just this file to the directory where your VB application
.exe files and .dll files are installed.
As with any Active-X component, the ocx file needs to be registered
on a computer system before being used. Registration is a one-time
activity. The installation path should be chosen carefully since
you need to unregister and re-register the .ocx if you move it. Registration
logic is also built into programs that are built using VB6. For example,
if you run the test and demonstration program that comes with the control,
TESTDMHProj.exe, the DMH.ocx control gets registered using its current
file system location. The registration can also be performed at the
command line by executing
regsvr32 pathname\DMH.ocx
where pathname is your pathname to the file. The
VB6 Development Environment can also register a component - refer to its
documentation.
At runtime, the control uses the VB6 runtime DLL, the Microsoft
Scripting Runtime, and the Microsoft Winsock Control 6.0 (%SystemRoot%\System32\MSWINSCK.OCX).
These DLLs/controls may need to be copied from a development machine
to any runtime machine where VB6 has not been installed. If they
are copied, they also need to be registered.
Development
The control is used from Visual Basic Version 6 as follows. Use the
menu item Project/Components... to bring up a list of available components.
Check the "Hume Integration DMH VB Active-X Control" checkbox to make the
control available to your project. Press the Ok button.
Now when you visually edit your main form, you should see the "DMH"
control as a selectable component on your toolbar.
Add one instance of the DMH control to your form by double-clicking
on the "DMH" component icon. VB gives your instance the name DMH1
but you may wish to assign a name of your choosing. We will use the
name "dmh" for example. You only need one instance of the control
- it should be shared among all your forms, as discussed later in this
section. The control will be invisible at runtime. Place it
on your form as you see fit.
As a developer, per the licensing terms, you are required to have the
Tcl/Tk DMH software installed on your development system. One
reason for this requirement is to insure that you have the online
documentation for the DMH system. A second major reason is so
that you can run your own DMH server process to test and debug against
without affecting a factory production system.
If you are not familar with the DMH message system, you may want to
read the mbx document which is usually installed at \usr\local\htm83\mann\mbx.html.
Your VB application acts a DMH message system client, and attaches to a
running DMH server. Once you are connected to the DMH system, you
can exchange messages with other attached processes.
To get started, you only need to know the hostname where the DMH server
is running, and the DMH Groupname that has been assigned to the server.
If you click on the "Programs"/"Tcl 8.3 - Tk 8.3 - DMH"/"Datahub" program
item, you will start a DMH server running on your host, with the default
DMH groupname of "mbx".
The usual application design, and the one that provides the best performance,
is to connect to the DMH server during initialization, and to use this
connection during the life of the application. The Init(
) method is used to connect to the server. The server's hostname
and groupname can be provided as arguments to the Init( ) method, or set
as property values during development or runtime. One idea is to
set the production system hostname and groupname at development time as
property values, and then at runtime check to see if environment variables
of your choice are pointing to an alternate DMH server. You can call
the Init( ) method from your Form_Load subroutine.
Error Handling
A long running program such as a user interface or automation application
needs to handle intermittant errors with network outages or server shutdowns.
There are two styles of handling errors; you can mix both styles in your
application as you see fit.
The first style of error handling is to avoid them by disabling buttons
and window controls that make use of DMH features when there is not a server
connection. You write the statements that enable your buttons in
the control "Connected" event handler, and you write statements that disable
the buttons in your "Disconnected" event handler. During initialization,
before you have a connection, call the Disconnected event handler yourself
to disable the buttons. Also during initialization, call the Init(
) method. When the Init( ) succeeds, a "Connected" event occurs and
your buttons become enabled. This technique requires less coding
than the method described next. Your code may look something like
this:
Private Sub dmh_Connected()
TraceAppend ("Connected Event")
butInit.Caption = "Disconnect"
'enable buttons that require a connection
butDoXact.Enabled = True
butSend.Enabled = True
'etcetera
End Sub
Private Sub dmh_Disconnected()
TraceAppend ("Disconnected Event")
butInit.Caption = "Initialize"
'disable buttons that need dmh to avoid errors
butDoXact.Enabled = False
butSend.Enabled = False
'etcetera
End Sub
Private Sub Form_Load()
butInit.Caption = "Initialize"
' could disable all buttons that need a connection
' for example have that code in the disconnected
event and call it here
Call dmh_Disconnected
' and then enable buttons in the Connect() event
' connect using property values
Call dmh.Init( )
End Sub
The second style of error handling is to add explicit error trapping
to your procedures. This is the safest style since an untrapped error
will end your program. An example procedure with error trapping
follows:
Private Sub butClose_Click()
'this button stays enabled when there is no
connection so it
' needs error trapping
On Error GoTo butClose_Err
dmh.CloseMailbox txtreplybox.Text
Exit Sub
butClose_Err:
MsgBox "Trapped Error " & Err.Number &
vbCrLf & Err.Description
End Sub
If your application does asynchronous receiving, you should probably
avoid using the MsgBox call. During our testing we found that receiving
did not work if a MsgBox dialog was being shown. The good news is
that receiving works fine if a VB modal form is being displayed.
Here is a summary of the kinds of errors that the DMH control will raise.
When you make a method call that requires a DMH server connection, and
you do not have one, the method call will exit with error 40006 being raised.
If you use an improper mailbox name such as one with whitespace in it,
the method call will exit with error 380 being raised. These are
the two main errors when initiating a method call. These errors are
raised using the Err.Raise( ) facility of Visual Basic. Most of the
DMH control method calls are then processed asynchronously. In other
words, your method call returns, and the message communication you initiated
happens as events are processed. An error that occurs during event
processing results in the DMH control Error( ) event occuring. A
DMH Error( ) event is different than an error raised by Err.Raise( ).
You do not need to write an Error( ) event handler, and these events do
not end your application. In contrast, an error created by
Err.Raise( ) will terminate your program unless it is trapped with an On
Error statement. You probably should write a handler for the DMH
Error( ) event to communicate to the users of your program errors that
occur. When the Error( ) event occurs, the Disconnected( ) event
will also occur. You can place logic in your Disconnected( ) event
handler to initiate recovery and resume logic, exit the program, etc.
Child Forms
Here is the recommended technique to use a single DMH control with all
of the form code of your application. If you have a child form (window)
with the name subtest, include a variable for use in referencing the parent
form DMH control. So in the child form declarations, you include:
' Child Form declaration
Public dmh As DMH
'Child Form code
Private Sub butChild_Click()
Dim reply as String
reply = dmh.DoXact("DATAHUB", "eval localtime
16");
' etc
End Sub
And the logic in your main form will look something like this:
' Parent form declaration
' a child window - how to access the dmh control
' that exists on the parent
Private subwin As subtest
Private Sub Form_Load()
' have an example child window that can also
use our DMH connection
' you should share a single DMH control as in
this example
Set subwin = New subtest
' you MUST use "Set" in the object assignment
Set subwin.dmh = dmh
End Sub
Private Sub butSubtest_Click()
subwin.Show vbModeless
'subwin.Show vbModal, Me
End Sub
In the code for the child window logic, we use the variable "dmh" just
as we do when coding logic for the parent form.
Sending and Receiving - Basics
The programming model of the DMH message system is that you send a plain
text message to a destination mailbox. When sending the message,
you can optionally specify the name of a second mailbox for the recipient
to send a reply message to. Usually you send a message to an application
logic server such as a Datahub. The message is usually SQL,
Tcl, or VFEI code that the recipient executes. If the sender has
designated a reply mailbox, the result of executing the command is sent
to the reply mailbox.
Lets discuss sending without asking for replies using the Send(
) method. For example, suppose you are integrating
a barcode reader. When data is read from the barcode reader device,
your code is supposed to update a record in a Datahub table. You
will send messages without asking for reply messages - if there is a system
shutdown or communication failure, your application will know from the
Disconnected( ) event. This is more efficient than asking for a reply
message at every barcode read.
' update latest read record in table barcode_reader at the Datahub
Dim message as String
message = "update barcode_reader set data_in='" & newdata &
"' where device_id='" & myID & "'"
call dmh.Send(Hub, message)
When you send a message without waiting for a reply, it is referred
to as an asynchronous send.
Often, you will want to send a message to obtain reply data. The
most convenient method to use is the DoXact( ) method.
This method will take care of specifying and using a unique mailbox for
your reply message, and it will take care of managing a timer in case a
reply message is not forthcoming. Suppose you want to query a database
table, and the DB variable is assigned the mailbox name of the dmh_SQLsrv
process. The online documentation shows that the SQL standard
"select" command sends multiple reply messages, but the "telect" command
sends a single reply message with all of the requested data formatted as
a Tcl list. The DoXact( ) method is designed for a single reply message,
so your code looks like:
Dim reply as String
reply = dmh.DoXact(DB, "telect device_id from barcode_config where
display='" & dmh.LocalHostname( ) & "'")
if reply = "TIMEOUT" then
' ...
Exit Sub
End If
' Parse the Tcl List
' element(6) = rows of data, then (0) = first row, then (0) = first
item in row
device_id = dmh.ListElement(reply, 6, 0, 0)
Sending and Receiving - Advanced
If your application needs to receive unsolicited messages from other processes,
you use the Whenever( ) method to setup asynchronous
receiving. When an unsolicited message is received, your MessageArrival(
) event handler is called. If you are receiving to multiple mailbox
names, you will need to code a Select/Case statement or some if...then...else
logic in your MessageArrival( ) event handler. By convention you
should use mailbox names for receiving that end in _SQL if SQL messages
are expected, _VFEI if VFEI messages are expected, and _RPC if Tcl messages
are expected. There is no limit to the number of mailboxes
that you use for receiving, but the design convention is that you use unique
names based on the server function(s) provided. There should be only
one receiving process per mailbox name in a DMH group. You may wish
to create a unique mailbox name for receiving by basing the name on your
hostname - see the DMH method LocalHostname( ).
The Whenever( ) method is used for ongoing receiving - your application
will continue to receive the messages that are sent to your specified mailbox.
The Disarm( ) method can be used to stop asynchronous
receiving.
The Whenmsg( ) method is similar to Whenever(
) except that it functions to receive only one message. If Whenmsg_Again(
) is executed from the MessageArrival( ) event handler, then the control
is re-armed to receive the next message. So the combination of Whenmsg(
) and WhenmsgAgain( ) are equivalent to the Whenever( ) method.
Lets revisit the DoXact( ) method. In some situations, you may
want higher performance by sending messages and collecting the replies
asynchronously, instead of waiting for each reply before sending the next
message. You do this by setting up one or more reply mailboxes and
arming them for receiving using the Whenmsg( ) or Whenever( ) methods.
Instead of using DoXact( ) use the Send( ) command and specify the reply
mailbox argument. Typically a high performance application
will create a small number of unique mailbox names for replies, and re-use
them. If you are creating unique mailboxes for each reply message,
use the CloseMailbox( ) method when you are
done with each one, to recover resource usage.
Event Handling Notes
Your application should not "live" inside of your event handling code.
Be sure to return in due course. Avoid calling DoEvents or performing
long running computations.
Be careful with the Trace( ) event. If you turn on character conversion
tracing and are exchanging long messages, your application will be manipulating
huge amounts of string data.
Do not call MsgBox( ) or invoke similar modal windows from inside of
an event handler. Instead, have a list box or text field on a Form
window that you append to.
International Character Sets
International characters can be part of your data messages that you exchange
with Tcl applications and store in Datahub or ODBC tables. The DMH
control translates the Unicode wide characters used in VB to the multibyte
UTF-8 characters used by Tcl. When declaring database tables to hold
international text, base the VARCHAR( ) sizes on UTF-8 byte counts, not
on the number of characters. In the most conservative case,
you need to allow 3 bytes per displayed character.
Lets do a "hello world" example. On a US English keyboard, the
character é (e with an acute accent) is entered by holding down
the Alt key and typing 1 3 0 on the numeric keypad. Start the
Datahub by clicking on the Tcl 8.3 program item. Start the TestDMHProj.exe
test program. Click the Initialize button to connect to the Datahub.
In the entryfield for "Message or Input Data", type the command
eval set hello héllo
Press the "DoXact(Mailbox,Message)" button to send this to the Datahub.
This command tells the Datahub to evaluate the Tcl statement "set hello
héllo". You will see the text "DoXact( ) Reply:héllo"
in the "Reply or Output Data" field. Bring up the Datahub console
window using the menu item "File/Tcl command..." on the Datahub application,
or just send the message "eval console show". On the datahub console,
type the command "set hello". This statement asks to display the
value of the global variable hello. You should see the text result
héllo. If you type the command "string length $hello", the
result is the value 5. If you execute "string bytelength $hello"
the result is 6. These results tell you that the value of the hello
variable is a 5 character string that uses 6 bytes for its internal representation.
If you turn on String Conversion tracing on the TestDMHProj.exe program,
you will see that the é character is represented in Tcl using the
two bytes (hex C3 and hex A9).
For Internationalization to succeed as well for your language(s), you
need to make sure that you have installed fonts and chosen fonts in your
application that are capable of displaying the characters you require.
Termination
When your application is shutting down, you should call the Disconnect(
) method to disconnect gracefully from the DMH server. Practically
speaking the DMH server routinely takes care of situations where clients
leave ungracefully, but proper software manners are encouraged.
Miscellaneous Notes
An actual network connection is not attempted until Init() is called.
The programming model is that you will not have more than one connection
to a particular DMH server. It is typical to have only one DMH connection
per application process. Communication across DMH groups can be accomplished
by sending to mailbox@groupname. It is also possible to use multiple
controls, each connected to a different DMH Group.
There should be only one reader per mailbox name in a given DMH group.
The VB DMH control is able to use and resolve DMH groupname aliases
as described in the online Tcl documentation. Groupname aliases are
resolved at the DMH server and not at the client.
Mailbox Naming rules:
-
A mailbox name should be limited to 31 or fewer characters but there is
no firm limit.
-
The name must start with an ASCII letter, digit, or the underscore
-
Other characters in the name may include - or !.
-
The period, colon, or @ symbol should only be used to specify optional
groupname qualification of a mailbox name as in boxname[@host_or_ip_address:groupname]
DMH.ocx Control Reference
DMH.ocx Control Properties
Property Name |
Data Type |
Description |
DefaultTimeout |
Long |
The default timeout interval for send and reply transactions, or timed
receive invocations. In seconds - the default value is 30.
Settable range: 1 - 86399. |
RemoteGroup |
String |
The name of the DMH server message group, such as "PIC". The
DMH software maps the specified groupname to a TCP/IP socket port.
The value may also be specified as numeric text which is interpreted
as directly specifying the TCP/IP port the DMH server is using. The
default value is "mbx" which enables connection to a Datahub program started
with default values. This property can be set at design or runtime,
or set when calling the Init method. |
RemoteHost |
String |
The TCP/IP hostname of the DMH server. The default value is "localhost"
which is a standard way to specify the computer that the control is executing
on. The value can also specify an IP address such as "192.168.2.12".
This property can be set at design or runtime, or set when calling the
Init( ) method. |
State |
Enumerated
Integer |
The state property is a read-only value available at runtime.
The value can be read to determine if a healthy communication connection
exists, etc. Applications will ordinarily use event methods
and not poll the state property value. The transient and error states
may not last long, so testing for the values 0 or 7 would be the most common
scenario.
0 disconnected
4 hostname is being resolved
6 connection setup in progress
7 healthy connection exists
8 connection close in progress
9 a communication error has occured
519 DMH protocol setup in progress (519 = &H100 Or 7)
|
Tracebits |
Long |
The Tracebits property controls output of diagnostic data to the Trace
event. This value is used as a bitfield with the bit values controlling
the following categories of output:
01 data reads
02 data writes
04 message receiving
08 message sending
16 logic tracing
32 UTF-8, BSTR character conversions |
mhgroup |
String |
The mhgroup property is a readonly runtime value indicating the hostname:port
of the DMH server when connected, else as empty string. Hostname
is the server's idea of his hostname which may be different from the RemoteHost
that was specified at the client. |
|
|
|
DMH.ocx Control Generated Events
Event Signature |
Description |
|
|
|
|
Connected( ) |
Happens after successfully connecting to the DMH server in the wake
of the Init method invocation. |
Disconnected( ) |
The DMH connection has been closed from any circumstance such as remote
closure, communication failure, error, or invocation of the Disconnect
method. This event is similar to the Tcl lostserver procedure invocation |
Error(
error number as Long,
description as String) |
The Error event happens when the Init method fails, or there has been
communication failure. In most cases when the Error event happens,
the control state will transition to the disconnected state, and the Disconnected(
) event will occur shortly.
Init errors include
-
10051 the network is unreachable
-
10060 Connection has timed out. This error indicates that the
remote host may not be online.
-
10061 Connection attempt is refused.
-
10061 Connection is forcefully rejected.
-
The remote host is online and reachable, but there is not a DMH server
at the specified group or port. In some cases we have improperly
seen this error when using the hostname "localhost", and have worked around
it using the actual hostname. This seems to be a buggy behavior that
is being investigated.
-
11001 Hostname not found (DNS authoritative). This error
may indicate an improperly spelled hostname, or a hostname that is not
known to your name server.
-
11002 Hostname not found (non-authoritative name resolution).
This error may indicate that your name server is down.
-
50003 DMH Server refuses our client connection
-
This error indicates that customer modified software running in the
DMH server has rejected the connection. It is likely that you are
in violation of your site's security policy.
-
50004 DMH Protocol error - improper setup reply.
-
You should never see this error.
-
Broken connection errors include:
-
10051 the network is unreachable
-
10060 Connection has timed out
-
11053 Connection is aborted due to timeout or other failure
-
10054 Connection is reset by remote system
-
10058 Connection has been shutdown
-
50001 DMH Protocol error - missing data. You should never
see this error.
-
50002 DMH Protocol error - improper packet. You should
never see this error.
-
Attempting to use a method that requires a connection when a healthy
connection does not exist results in the error:
-
40006 Wrong connection state for the request
-
40006 No DMH Server Connection
|
MessageArrival(
DestinationMailbox as String,
ReplyMailbox as String,
Data as String) |
A message has arrived. The DestinationMailbox parameter is a
mailbox name that your application has specified when initiating receiving.
If the sender of the message indicated a reply mailbox, it is passed as
the second argument, ReplyMailbox. If no reply mailbox has been specified,
the ReplyMailbox argument is an empty string. The Data argument is
the text of the sent message. The DMH control's logic protects you
from receiving another message for the DestinationMailbox, and re-entering
your MessageArrival logic until you have returned from the MessageArrival(
) call
String data is represented in Tcl as multibyte UTF-8 character sequences,
and as double byte character sequences in Visual Basic. Conversion
between the two representations occurs transparently. |
Shutdown(ByRef StayAlive as Boolean) |
A remote request has been received to terminate the process.
If you do not set the StayAlive flag true, the control will cause the application
to disconnect from the DMH message system. Because of implementation
constraints the control is not able to cause your application to exit.
If you want to exit, you need to write a Shutdown event handler that executes
"End" or "Unload me". |
Trace(Message as String) |
This event provides diagnostic and debug information per the Tracebit
property setting. Your application needs to avoid creating new DMH
activity in the Trace event callback, that in return causes Trace events.
A cycle of positive feedback is possible which will cause a software fission
reaction. |
DMH.ocx Control Methods
|
|
Abort( ) |
Any in-progress send-and-reply or modal wait transactions such as the
Init( ) method or DoXact( ) calls are aborted with return values indicating
TIMEOUT. Invoking the Abort method does not affect asynchronous receiving
that is setup using the Whenmsg( ) or Whenever( ) methods. |
CloseMailbox(boxname ) |
Stop using a mailbox - Disarm receiving if listening, Flush if not
empty, and remove from existence if it exists. The Tcl version
of this call, differs because it will not flush existing messages.
You must be connected to use this call. |
Count(boxname) as long(3) |
Returns a three element array giving the total count of messages that
have been sent to the mailbox, the total count of messages that have been
consumed from the mailbox, and last, the current count of pending messages.
A pending message is one that exists in the queue associated with the mailbox,
and has not been consumed by reading or flushing.
You must be connected to use this call. |
Disarm(optional boxname as String) |
Un-register the listener from a specified mailbox. This
call may be used to cancel an earlier whenever( ) or whenmsg( ) call.
If called with no arguments, all Whenever( ) and Whenmsg( ) receiving registrations
are cancelled. The Abort( ) method will cancel in-progress DoXact(
) calls.
You must be connected to use this call. |
Disconnect( ) |
The counterpart of Init( ); disconnects from the DMH server.
The Abort( ) method gets called to end any in-progress transactions.
The Disarm( ) method gets called with no arguments to cancel all receiving. |
DoXact(DestinationMailbox as String,
Message as String,
optional TimeoutSeconds as Long,
optional ReplyMailbox as String)
As String |
Performs a complete send and reply transaction with timeout management.
Creates and manages a unique reply mailbox for the send and reply transaction
if the replybox argument is defaulted. If the timeout is not specified,
the DefaultTimeout value is used. The usual reply is the text of
the reply message. The String literal TIMEOUT is returned in case of failure.
You can only have one instance, of DoXact( ) or TimedReceive( ) active
at a time. If you specify a ReplyMailbox, you need to insure that
the name you specify is only used by your application. It is usual
to create a unique reply mailbox name, perhaps based on the hostname, assign
it to a variable, and use it repeatedly.
You must be connected to use this call. |
Flush(MailboxName) |
Empty a mailbox of any pending messages. A pending message is
one that has been sent to the mailbox but has not been consumed.
In other words, a pending message is waiting in a queue associated with
the mailbox name. Messages are consumed by reading or flushing.
You must be connected to use this call. |
GroupnamePort(Groupname as String)
As Long |
Used to determine the TCP/IP port number that is used by the DMH server
to listen for client connections. The method is equivalent to the
mh_name_to_socket Tcl procedure. Most applications will not have
a use for this method since the server socket port is managed by the DMH
software. |
Init(Optional DMHGroupname as String,
Optional RemoteHostname) As Long |
Performs the initial connection to the DMH message server. The connection
will be setup or an error result will be obtained before returning.
If no DMHGroupname or RemoteHostname is specified, the control property
values are used.
If the connection succeeds, the return value is 0. A non-zero
result is an error number indicating why the initialization failed.
See the Error( ) event for specific codes.
When the initialization is successfully completed, the Connected( )
event is fired. If the Init call fails, the Error( ) event is fired.
If the connection to the DMH server is ever lost, the Disconnected(
) event is fired. |
ListElement(TclList as String,
index1 as Long,
optional index2 as Long,
optional index3 as Long ) As String |
This method is similar to the lindex method of Tcl. It will parse
text formatted as a Tcl list and return the specified element. Additional
indexes may be specified to parse nested lists. If a specified index
is out of bounds, an empty string is returned. Error 50008 is raised
if an invalid list is parsed.
Dim reply as String
Dim item as String
reply = dmh.DoXact(Datahub, telect_query)
' index 6 = rows of data, 0 = first row, 0 = first item in row
item = dmh.ListElement(reply, 6, 0, 0) |
LocalHostname( ) as String |
Returns the TCP/IP hostname of the computer that the control is executing
on. The name is guaranteed to be stripped of domain information,
and imbedded white spaces which are not valid in hostnames are replaced
with underscores. |
ReceiveList( ) as String |
Returns a list of the mailboxes you are listening for messages on.
Does not show mailbox names that have in-progress MessageArrival( ) events.
This command may be useful for debugging, and it is not used in a typical
application.
You must be connected to use this call. |
Send( DestinationMailbox as String,
Message as String,
optional ReplyMailbox as String) |
Send a message to a mailbox, optionally with a reply mailbox indicated.
By convention, when a reply mailbox is indicated for a command message
sent to a Datahub mailbox or equipment interface mailbox, the command is
processed, and a reply message is sent to the reply mailbox.
Specifying the reply mailbox as an empty string or as the literal value
"NULL" is equivalent to not specifying a reply mailbox.
Sending to the mailbox name "TRACE" sends the message to the DMH Server
Trace Facility.
The Send method corresponds to the Tcl mbx put and mbx putr commands.
Note that "Put" is a keyword in Visual Basic and could not be used for
this method.
You must be connected to use this call. |
ServerStatus( ) as String |
Returns a Tcl list containing the information presented in the Tcl
DMH status window. The information can be parsed by the application
to determine status information on every mailbox that is currently
in use. This command may be useful for debugging, and is not used
by ordinary applications.
The first element of the list is a list of 5 elements:
{ hostname:port messages_received messages_sent messages_queued
tcl_version }
Subsequent elements in the list are lists of four or five elements:
{ mailboxname count_in count_out count_pending [reader_handle]
}
Additional elements may exist in the list if there are DMH clients that
are not currently waiting to receive messages. These elements are
formatted as:
{{{no whenmsg pending}} - - - reader_handle}
You must be connected to use this call. |
TclJoin(elements( ) as String,
optional joinstring = " ")
as String |
Joins together strings as Tcl list elements forming a result string
that is a Tcl list. Similar to the Join( ) command of Basic except
that braces are added as needed to delimit empty elements, or to delimit
special Tcl character sequences involving backslashes , square brackets,
etc. |
TclJoinV(elements as Variant,
optional joinstring = " ")
as String |
Same as TclJoin( ) except the list elements are passed as a Variant
array. The Variant array is also the output type of the array( )
function.
Dim s as String
s = TclJoinV(array("hello world", "arg 2", "last"))
= "{hello world} {arg 2} last" |
TclSplit( Tcllist as String,
ByRef elements() as String,
optional ByRef ErrorInfo as String)
as Long |
TclSplit( ) parses a string formatted as a Tcl list into an array of
string elements. The method is similar to the Split( ) function of
VB except that it understands the Tcl usage of quotes, braces and backslash
sequences. Not all strings are valid Tcl lists. The return
value is 0 on success. In case of error, the elements array is set
to an empty array, and the return value and ErrorInfo are set as follows:
return value, ErrorInfo
0, ""
1, list element in braces followed by non-whitespace
2, list element in quotes followed by non-whitespace
3, unmatched open quote in list
4, unmatched open brace in list
|
TimedReceive(ReceiveMailbox as String,
optional TimeoutSeconds as Long)
As String |
Waits for a message to be received in the specified mailbox.
If the call succeeds, the return value is the message data.
If the call fails, the return value is the literal string "TIMEOUT".
You must be connected to use this call. |
Version( ) as String |
Current software returns the string "1.1" to indicate compatibility
with DMH versions 1.1 and earlier. |
VFEI2Dictionary(VFEItext as String,
ByRef NameValues as Dictionary) as Long
|
The VFEI2Dictionary method parses a SEMATECH VFEI formatted text string
into (name, value) items in a Visual Basic Dictionary. VFEI is a
SEMATECH standard for the format of messages used for equipment integration.
This command parses a VFEI version 2.2 (or 2.1) message for the name and
value of the data items. The return value is the count of items that
have been added to the dictionary as a result of parsing the text.
This implementation succeeds in parsing VFEI messages that do not strictly
adhere to the SEMATECH description. In general, quotes are only needed
to delineate a data item that has imbedded white space. There is no problem
with additional white space between any of the lexical elements. The "/"
and format code are optional and may be omitted.
Private Sub butVFEI_Click()
Dim dic As New Dictionary
Dim tsts As Variant
Dim key As Variant
Dim rc As Long
Dim text As String
Dim teststring As String
On Error Resume Next
tsts = Array( _
"DESC=|The VFEI parser can parse name
= value strings!| ", _
"Filename=|dmh.ocx| directory=|\\server\path1\path2|
", _
"Command=|you can have \|imbedded quotes\|
| ", _
"CMD / A = |ALARM SETUP| MID/A=|STP1|
MTY/A=|C| TID/U4=2 ENABLE/U1=0 ALARM_ID/I4[3]=[ 1 |2| 3 ]", _
"CMD/A=|INITIALIZE| MID/A=|STP1| MTY/A=|C|
TID/U4=1", _
"CMD / A = |ALARM SETUP| MID/A=|STP1|
MTY/A=|C| TID/U4=2 ENABLE/U1=0 ALARM_ID/I4[3]=[1 2 3]", _
"xx/U1 = 0 xU2/U2=0 xI4/I4= 1234 xI8/
I8 = 2 xF4/F4 = 1.2 xBL/BL=0", _
"CMD/A=|INITIALIZE| LL/L[3]=[MID/A=|STP1|
MTY/A=|C| TID/U4=1]", _
"CMD=INITIALIZE MID=STP1 THING1=|hello
world| thing2=355 thing3=6.02e23", _
"CMD/A=TEST5 REPORT2/L[3]=[EVENT_ID/A=|MB_COMPLETE|
CLOCK/A=|1992| XX/L[3]=[FIRST/A=|TEXT 1st| SECOND/U2=255 THIRD/F4=0.003]]",
_
"")
text = ""
For Each tst In tsts
'replace | with quote (cannot
imbed quotes directly)
teststring = Replace(tst,
"|", Chr(34))
text = text & teststring
& vbCrLf
rc = -1
Err.Number = 0
rc = dmh.VFEI2Dictionary(teststring,
dic)
text = text & "rc="
& rc & vbCrLf
For Each key In dic
text = text & key & "=" & dic.Item(key) & vbCrLf
Next
If Err.Number <> 0 Then
text = text & "trapped error: " & Err.Number & Err.Description
& vbCrLf & vbCrLf
Else
text = text & vbCrLf
End If
txtoutput.text = text
dic.removeall
Next
End Sub |
Whenever(MailboxName as String) |
Registers to receive all messages directed to the specified mailbox.
When the MessageArrival( ) event handler returns, the control re-arms for
receiving the next message directed to the specified mailbox. The
Disarm( ) method is used to stop receiving.
You must be connected to use this call. |
Whenmsg(MailboxName as String) |
Register for receiving the next available message directed to the specified
mailbox. Calling WhenmsgAgain( ) in the MessageArrival( ) event handling
code re-arms the receive registration for the next message.
You must be connected to use this call. |
WhenmsgAgain( ) |
The Whenmsg( ) method functions as a one-shot. In other words,
receiving is stopped after receiving one message. Calling the WhenmsgAgain
method from the MessageArrival handler re-registers to receive the next
message.
You must be connected to use this call. |
Err.Raise Method Errors
These are errors that may be raised as a result of a method invocation.
380 mailbox name must start with
an ASCII letter, digit, or underscore
380 mailbox name must contain
only ASCII letters, digits, -, _, ., !, :, or @
380 The property value is invalid.
40006 No DMH Server Connection
40006 Cannot re-enter synchronous send and reply
logic
40006 Cannot initialize in current state
50005 Already processing a DoXact( ) call for this
ReplyMailbox
50006 Timeout or other error obtaining count
50007 String to byte conversion failure
50008 improper Tcl List
50009 invalid VFEI text
50010 improper use of NULL mailbox
License Terms
Subject to Change Without Notice
The VB DMH Active-X control is licensed for development and runtime
use at no additional charge for computers that are licensed for development use of the
Hume Integration Datahub SDK. We ask that
VB developers install the Tcl executables and actively use the Tcl executables
for testing and development, instead of developing against their factory's
production servers. Also, we ask that VB developers install the Tcl
online documentation and use it to supplement the material presented in
this document.
Hume Integration is also pleased to offer separate runtime licenses
for using the DMH control on systems that are not licensed as development systems.
Runtime usage of the DMH client
software is licensed separately from the Datahub SDK runtime license.
References
The author wrote his first Basic program in 1966 using his father's Teletype
dialed in to an IBM timesharing system at 115 baud or so. The
language has changed quite a bit, and the following books were found helpful.
-
VB & VBA In A Nutshell: The Language by Paul Lomax, O'Reilly
& Associates Inc. 1998. This book was by far the most useful.
It is awkward to use the online VB documentation because each topic is
a separate document and the navigation between related topics is difficult.
-
Visual Basic Controls In a Nutshell: The Controls of the Professional
and Enterprise Editions by Evan S. Dictor, O'Reilly & Associates
Inc. 1999.
-
Hardcode Visual Basic Second Edition by Bruce McKinney, Microsoft
Press, 1997. I wish this book was updated for VB6, but it is based
on VB5. Nonetheless it covers topics that the above references do
not address.
Document Version
Date of last revision: $Date: 2017/08/10 18:22:08 $