It is known, that Visual Basic isn't most appropriate tool for developing of Windows NT/2000/XP
services. The problem is, for service development is necessary to use API function CreateThread, which is not supported nether in VB5, nor in VB6. VB allows creation of
multi-thread programs, but not using CreateThread function. VB5 utilizes
Err object, common for all threads created by CreateThread function. It is inadmissible, because values of this object may be changed
from different threads in unpredictable order, and ever simultaneously on multi-processor computers. On the
contrary, VB6 uses Thread Local Storage (TLS) for Err object (and not only for
it), but TLS isn't initialized when CreateThread function creates new
thread, and therefore, after simple recompilation of the program in VB6 it doesn't work at all (rather, it
works only being compiled in p-code with common Err object).
Matthew Curland suggested rather complicated method of threads creation in VB (see links), but for purpose
of service development more simple solution may be applied. The program will work without TLS, if in new thread
used only arithmetic operators and API functions, declared in type library, and Err object isn't used at all. It is well known that the properties of Err object became changed in two cases: when occurs Run-Time error (Err.Number) and after every API call (Err.LastDllError). The
first may be avoided by writing error-free code, the second - by declaring API calls in Type Library (API
functions declarations must not contain usesgetlasterror attributes,
therefore type libraries from the popular Bruce McKinney's book are not suitable). Functional part of the
service must work in main thread, and above limitations doesn't apply to it. This approach must work both
in VB6 and VB5.
Of course, you can use free NTSVC.OCX control from Microsoft to create your service, and this way is simple
and reliable, but it has one disadvantage: you can't set "Unattended execution" option for it.
You can't use any OCX controls when "Unattended execution" is set while this mode is preferable
for service. In addition, because this control distributed in form of source code, there are some incompatible
compiled versions of it.
This sample is written using VB6 without any external components. As service is compiled for unattended
execution, it has no visual interface. Use Event Viewer to read messages written by the service to the
Application Log.
The functional part of service (which is absent in this sample) must be driven by the events from Service
Dispatcher. All events must be processed during few seconds, otherwise the service will be unable to respond on
requests from Service Dispatcher.
See also:
Microsoft Knowledge Base Q137890, Q170883, Q175948,
An OLE Control for
Creating Win32 Services in Visual Basic,
Manipulate Windows NT Services by
Writing a Service Control Program,
Creating an Agent NT Service with VB,
How-To Run Your Application as a
Service,
How-To Run Your Application as a
Service - Part II,
Matthew Curland's article "Create
Worker Threads in DLLs" in June/1999 issue of "Visual Basic Programmer's Journal".
|