|
Как известно, Visual Basic - не самое подходящее средство для написания служб (Service) Windows NT/2000/XP.
Проблема заключается в том, что для написания службы требуется использование функции API CreateThread , что не поддерживается ни VB5, ни VB6. VB позволяет создавать многопоточные
программы, но не с помощью функции CreateThread. VB5 использует общий объект
Err для всех потоков, созданных функцией API CreateThread. Это недопустимо, поскольку изменение значений этого объекта может
происходить из разных потоков в непредсказуемой последовательности и даже одновременно на многопроцессорных
компьютерах. Напротив, VB6 использует для объекта Err (и не только для него)
локальную память потока (TLS), но в момент создания потока функцией CreateThread TLS не инициализирована, и поэтому после простой перекомпиляции в VB6
программа не работает совсем (точнее, работает только при компиляции в p-code с общим объектом Err).
Довольно сложный способ решения проблемы создания потоков в VB предложил Мэтью Кэрланд (см. ссылки), но для
создания службы можно применить более простое решение. Программа будет работать и без TLS, если в новом потоке
совсем не использовать объект Err, а кроме этого использовать только
арифметические операторы и вызовы API, описанные в библиотеке типов. Как известно, свойства объекта Err обновляются в двух случаях: когда происходит Run-time ошибка (Err.Number), и после выполнения каждой функции API (Err.LastDllError). Первого можно избежать написанием безошибочного кода, второго - описанием
функций API с помощью библиотеки типов (описание функций API не должно содержать атрибутов usesgetlasterror, поэтому библиотеки типов из известной книги Брюса Мак-Кинни не
годятся). Функциональная часть службы должна работать в главном потоке, и на нее указанные ограничения не
распространяются. Этот подход работает как в VB6, так и в VB5.
Разумеется, для создания своей службы вы можете использовать бесплатный элемент управления NTSVC.OCX от
Microsoft, и этот способ достаточно прост и надежен, но имеет один недостаток: вы не можете применять опцию
"Unattended execution". Совместно с этой опцией элементы управления OCX применяться не могут, а
именно такой режим работы для службы является предпочтительным. Кроме того, поскольку этот элемент управления
распространяется в виде исходного кода, существует несколько откомпилированных версий этого компонента, не
вполне совместимых между собой.
Этот пример написан при помощи VB6 без использования каких-либо внешних компонентов. Поскольку служба
скомпилирована с опцией "Unattended execution", она не имеет визуального интерфейса. Для просмотра
сообщений, записываемых службой в Application Log, используйте Event Viewer.
Функциональная часть службы (отсутствующая в данном примере) должна управляться событиями, поступающими от
Диспетчера Служб. Все события должны обрабатываться в течение нескольких секунд, в противном случае служба не
будет иметь возможности обрабатывать запросы Диспетчера Служб.
См. также:
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,
Статью Мэтью Кэрланда "Create
Worker Threads in DLLs" в журнале "Visual
Basic Programmer's Journal" за июнь 1999 года.
|