Services
Commands for configuring and monitoring Windows services
package require
twapi
This module provides procedures for managing and controlling
Windows services and also allows for writing Windows services in
Tcl.
The commands get_service_internal_name and get_service_display_name map back and forth between
the internal name and display name of a service.
The command service_exists checks for the existence of a service
while get_service_state returns its state. The commands
get_service_status, get_multiple_service_status and get_dependent_service_status retrieve status
information for one or more services. interrogate_service
can be used to request a service to update its status with the
service control manager (SCM).
Service configuration changes, including creation of new
services and deletion of existing ones, can be done through the
commands create_service, delete_service, get_service_configuration and set_service_configuration.
The commands start_service, stop_service, pause_service and continue_service control
the run state of a service.
The command run_as_service allows an application to run as a
Windows service. Services are implemented as callback handlers that
are invoked in response to control signals received from the
system. These signals include controls to stop the service, to
pause and continue, or may be notifications of events such as
session changes. The list of such signals and their handling is
detailed in run_as_service.
While running as a service, applications need can update their
status with the SCM, either asynchronously or in response to
control signals. This can be done through update_service_status.
Most commands allow the following options to be specified:
-system SYSTEMNAME |
Specifies the name of the system on which the
command should be invoked. By default, this is the local
system. |
-database DATABASE |
Specifies the service control database to be
operated on. By default, this is the active service control
database on the target system. |
- continue_service INTERNAL_SERVICE_NAME
?options?
- This command resumes the specified service which must be in a
paused state. INTERNAL_SERVICE_NAME must be the
internal name of the service, not the display name. The command
returns 1 if the service has resumed to a running state when the
command completes and 0 otherwise. Note that a return value of 0
does not imply an error, just that the service had not completely
resumed by the time the command returned.
The standard options described in Standard Options may be specified with this
command. In addition, if the option "-wait
MILLISECONDS" is specified the command will wait
until the service is running or until MILLISECONDS milliseconds have expired.
- create_service INTERNAL_SERVICE_NAME
COMMAND ?options?
- This command creates a new Windows service in the service
control manager database.
INTERNAL_SERVICE_NAME is the internal name by
which the service is identified by the service control
manager.
COMMAND contains the system command to be
executed to start the service. This includes the path to the
executable as well as arguments to be passed to it. If the path
contains spaces, it must be specifically quoted else the operating
system will interpret all characters after the first space as
arguments to be passed to the service. For example,
"\"C:\\Program Files\\MyService\\service.exe\" arg1 arg2"
In addition to the Standard Options,
the following additional options may be specified which control
various aspects of the service:
-displayname DISPLAYNAME |
Specifies the user visible name for the service.
This is the name that is shown in the net
start command and the SCM control panel applet. |
-servicetype SERVICETYPE |
Specifies the service type and may have one of the
following values:
win32_own_process |
Service that runs in its own process. This
corresponds to the SERVICE_WIN32_OWN_PROCESS in the Windows SDK
documentation. This is the default if the option is not
specified. |
win32_share_process |
Service that runs inside a process shared with
other services. This corresponds to the SERVICE_WIN32_SHARE_PROCESS in the Windows SDK
documentation. |
file_system_driver |
File system driver. This corresponds to the
SERVICE_FILE_SYSTEM_DRIVER in the
Windows SDK documentation. |
kernel_driver |
Kernel driver. This corresponds to the SERVICE_KERNEL_DRIVER in the Windows SDK
documentation. |
|
-interactive BOOLEAN |
This option specifies whether the service should be
allowed to interact with the desktop. This is only valid when
-servicetype is specified to be win32_own_process or win32_share_process. The -account option must not be used with this option since
interactive services must run under the LocalSystem account. |
-starttype STARTTYPE |
Specifies how the service is to be started.
STARTTYPE should have one of the following
values:
auto_start |
The service should be automatically started by the
service control manager during system startup. This is the default
if the option is not specified. |
boot_start |
The service should be automatically started by the
system loader during system boot. This is only valid when -servicetype is specified to be kernel_driver or file_system_driver. |
demand_start |
The service should be started by the system upon
receiving an explicit program request. |
disabled |
The service is disabled and cannot be started even
on program request. |
system_start |
The service is a driver that is started by the
operating system IoInitSystem function during
system initialization. This is only valid when -servicetype is specified to be kernel_driver or file_system_driver. |
|
-errorcontrol ERRORCONTROLMODE |
This option specifies how errors during service
start are to be handled. ERRORCONTROLMODE may
have one of the following values:
ignore |
An error message will be logged to the Windows
event log. The system startup will continue. |
normal |
An error message will be logged to the Windows
event log and a popup displayed to the user. The system startup
will continue. This is the default. |
severe |
An error message will be logged to the Windows
event log. The system startup will continue only if the last known
good configuration is active. Otherwise, the system is restarted
with the last known good configuration. |
critical |
An error message will be logged to the Windows
event log if possible. If the last known good configuration is
active, the system startup is aborted. Otherwise, the system is
restarted with the last known good configuration. |
|
-loadordergroup GROUPNAME |
Specifies GROUPNAME to be the
service load order group to which the service belongs. If the
option is not specified, the service is assumed to not belong to
any load order group. |
-dependencies DEPENDENCYLIST |
Specifies the services and service load order
groups that are required by this service and that must start before
this service. DEPENDENCYLIST is a list of
service names and load order groups. A load order group name must
be prefixed with a + character to
indicate that it is a group name and not a service. |
-account ACCOUNTNAME |
Specifies ACCOUNTNAME to be the
user account under which the service should run. ACCOUNTNAME takes the form domain\username. If the account is a local account,
ACCOUNTNAME may be specified as .\username or username. If this option
is not specified, the service will run under the LocalSystem account. When -servicetype is kernel or
filesystem, ACCOUNTNAME should be the name of the driver object that
the system uses to load the driver. |
-password PASSWORD |
Specifies the password corresponding to the user
account specified in the -account option. This
option is ignored if the -account option is not
specified. |
- delete_service INTERNAL_SERVICE_NAME
?options?
- This command deletes the specified service from the service
control manager database. INTERNAL_SERVICE_NAME
must be the internal name of the service, not the display name. The
standard options described in Standard
Options may be specified with this command.
- get_dependent_service_status INTERNAL_SERVICE_NAME ?options?
- Retrieves the status of services that are dependent on
INTERNAL_SERVICE_NAME and that match a specified
service state. The standard options described in Standard Options may be specified with this
command. In addition, the following options may be specified to
only include services in a given state. If neither of these is
specified, services in all states are included in the returned
list.
-inactive |
Specifying this option will result in inclusion of
services that are in the stopped
state. |
-active |
Specifying this option will result in inclusion of
services that are not in the stopped
state. |
The command returns a list of alternating elements, the first being
the internal name of the service, and the second being a keyed list
that describes a single service. The format of this keyed list is
identical to that returned by the get_multiple_service_status.
- get_multiple_service_status ?options?
- Retrieves the status of multiple services matching the
specified service type and/or state. The standard options described
in Standard Options may be specified
with this command. In addition, the options may be specified to
only include services of a given type and in a given state.
One or more from the following service type options may be
specified to limit the types of services that are included in the
returned list: -kernel_driver, -file_system_driver, -win32_own_process, -win32_share_process, -adapter or
-recognizer_driver. See the description of the
-servicetype option in the create_service command for
the semantics of these values. If no service type options are
specified, all types of services are included in the returned
list.
One of the following options may be specified to limit the returned
services to those in a specific state. If neither of these is
specified, services in all states are included in the returned
list.
-inactive |
Specifying this option will result in inclusion of
services that are in the stopped
state. |
-active |
Specifying this option will result in inclusion of
services that are not in the stopped
state. |
The command returns a list of alternating elements, the first being
the internal name of the service, and the second being a keyed list
that describes a single service. The format of the sublist is a
keyed list of the form field1 value1 ... with
the following fields:
serviceflags |
Integer value. If the low bit is set, the service
runs in a system process that must alway be running. |
checkpoint |
Contains the last checkpoint value reported by the
service during a lengthy operation. |
controls_accepted |
Contains a bitmask indicating the control commands
accepted by the service. Refer to the Windows SDK documentation for
ControlService for details. |
displayname |
Indicates the user visible name of the service |
exitcode |
The last exit code of the service. If this value is
1066, a service specific error code is returned in the service_code field. |
interactive |
Indicates whether the service is allowed to
interact with the desktop (1) or not
(0). |
name |
Indicates the internal name of the service |
pid |
The PID of the process in which the service is
running. A value of -1 indicates the service is stopped or that the
process id of the service cannot be determined. |
service_code |
In case the exitcode
field contains 1066, this field contains a service specific code
stored by the service. |
servicetype |
Indicates the type of the service, and is one of
win32_own_process, win32_share_process, kernel_driver, file_system_driver, adapter, recognizer_driver or an integer denoting the type
if not one of the above. |
state |
Contains the latest reported status of the service
and may have one of the values stopped,
start_pending, stop_pending, running,
continue_pending, pause_pending, paused
or an integer value indicating the status of the service if not one
of the above. |
wait_hint |
Estimated time required to complete an start, stop,
pause or continue operation as last reported by the service. |
- get_service_configuration INTERNAL_SERVICE_NAME ?options?
- This command returns the current configuration data for the
specified service. INTERNAL_SERVICE_NAME is the
internal name by which the service is identified by the service
control manager. The standard options described in Standard Options may be specified with this
command.
The return value is a flat list of the form option1
value1 ... that can be directly passed to the set_service_configuration command. The returned
values depend on which of the following options are specified:
-all |
Returns all option values |
-description |
Returns description of the service if available,
otherwise the empty string. |
-displayname |
Returns the user visible name of the service. |
-errorcontrol |
Returns an indication of how errors during service
startup will be handled. See description of create_service for
details. |
-servicetype |
Returns the service type. See description of
create_service for
details. |
-interactive |
Returns 1 if the
service is allowed to interact with the desktop and 0 otherwise. |
-loadordergroup |
Returns the name of the service load order group to
which the service belongs. |
-dependencies |
Returns a list of names of services and service
load order groups that are required by this service and that must
start before this service. |
-account |
Returns the user account under which the service
runs. |
-starttype |
See description of create_service for details. |
-command |
Returns the command, including the executable name
and parameters, that is invoked to run the Windows service. |
- get_service_display_name SERVICE_NAME
?options?
- This command returns the display name of the specified service.
If SERVICE_NAME is the display name of a
service, it is returned. If it is the internal name of a service,
the corresponding display name is returned. Otherwise, an error is
raised. The standard options described in Standard Options may be specified with this
command.
- get_service_internal_name SERVICE_NAME
?options?
- This command returns the internal name of the specified
service. If SERVICE_NAME is the internal name of
a service, it is returned. If it is the display name of a service,
the corresponding internal name is returned. Otherwise, an error is
raised. The standard options described in Standard Options may be specified with this
command.
- get_service_state INTERNAL_SERVICE_NAME
- Returns the last reported state of the service. See the
description of the state field for the
command get_service_status for possible values.
- get_service_status INTERNAL_SERVICE_NAME ?options?
- This command returns the latest status information sent by the
given service to the service control manager. The standard options
described in Standard Options may be
specified with this command. The return value is a flat list of the
form field1 value1 .... The following fields are
returned:
serviceflags |
Integer value. If the low bit is set, the service
runs in a system process that must alway be running. |
controls_accepted |
Contains a bitmask indicating the control commands
accepted by the service. Refer to the Windows SDK documentation for
ControlService for details. |
exitcode |
The last exit code of the service. If this value is
1066, a service specific error code is returned in the service_code field. |
interactive |
Indicates whether the service is allowed to
interact with the desktop (1) or not
(0). |
servicetype |
Indicates the type of the service, and is one of
win32_own_process, win32_share_process, kernel_driver, file_system_driver, adapter, recognizer_driver or an integer denoting the type
if not one of the above. |
state |
Contains the latest reported status of the service
and may have one of the values stopped,
start_pending, stop_pending, running,
continue_pending, pause_pending, paused
or an integer value indicating the status of the service if not one
of the above. |
service_code |
In case the exitcode
field contains 1066, this field contains a service specific code
stored by the service. |
checkpoint |
Contains the last checkpoint value reported by the
service during a lengthy operation. |
wait_hint |
Estimated time required to complete an start, stop,
pause or continue operation as last reported by the service. |
pid |
The PID of the process in which the service is
running. A value of -1 indicates that the process id of the service
cannot be determined or is stopped. |
- interrogate_service
INTERNAL_SERVICE_NAME ?options?
- This command asks the specified service to update the service
control manager with its current status. INTERNAL_SERVICE_NAME must be the internal name of the
service, not the display name. The standard options described in
Standard Options may be specified
with this command.
- pause_service INTERNAL_SERVICE_NAME
?options?
- This command pauses the specified service. INTERNAL_SERVICE_NAME is the internal name of the
service, not the display name. The command returns 1 if the service
is paused when the command completes and 0 otherwise. Note that a
return value of 0 does not imply an error, just that the service
had not completely changed to a paused state by the time the
command returned. A Tcl error is generated if the service was not
running.
The options described in Standard
Options may be specified with this command. In addition, if the
option "-wait MILLISECONDS"
is specified the command will wait until the service is paused or
until MILLISECONDS milliseconds have
expired.
- run_as_service SERVICES ?-interactive BOOLEAN? ?-controls CONTROLLIST?
- This command sets up the mechanisms that allow a Tcl
application to act as a Windows service. It must be only called
when the application is started by the Windows SCM as a Windows
service, else it will fail silently. The command does not return
until the service is ready to exit. Rather, it invokes the service
handlers that implement each service in response to notifications
received from the system as described below.
SERVICES is a list of SERVICENAME
HANDLER pairs that describe the services that will run in the
process. Note a single process may host multiple services.
SERVICENAME is the internal name of a service.
HANDLER is a script that will be invoked for
that service in response to various system notifications as
described below.
The option -interactive indicates whether the
services running in the application will require interaction with
the desktop.
The option -controls configures what controls
messages from the system, signals and notifications, are understood
by the services. The SCM will restrict itself to sending only these
although for robustness it is recommended that all services
gracefully handle all signals as described below. Note that it is
not possible to specify different values for this on a per-service
basis. By default, CONTROLLIST includes control
signals stop and shutdown. Note the notification start is implicit and must be handled by every
service.
When the application is started by the SCM, it should perform its
basic application-wide initialization and then call run_as_service. The
command will then set up the communication mechanisms with the SCM
and register the specified services. The control signals sent by
the SCM to the service are passed on to the HANDLER script registered for the service by the
application.
The messages sent to a service fall into two categories - control
signals and notifications. Control signals generally require the
service to take some action, often a state change such as stopping
or pausing the service. Notifications are generally of an
informational nature to apprise the service of some system event
such as session changes or power events.
There are five controls signals sent by the SCM to control the
state of a service. These correspond to the tokens start, stop,
shutdown, pause and continue. For
each of these, HANDLER is invoked with four
additional arguments. The first is control signal token itself. The
second is the name of the service for which the control was sent
and should match (ignoring case) the corresponding the SERVICENAME values passed to run_as_service. The third argument is a sequence number
(more on this later). The fourth argument is a numeric value that
is the actual value of the control signal sent by the SCM.
start |
Sent to start the service. |
stop |
Sent to stop the service. |
pause |
Sent to pause the service without terminating it.
This is only received if pause_continue
has been specified as an element in the -controls option. |
continue |
Sent to contiue a service that was previously
paused. This is only received if pause_continue has been specified as an element in
the -controls option. |
shutdown |
Sent to indicate the system is shutting down.
Should be treated similar to stop. |
interrogate |
Sent to enquire about the service status. TWAPI
handles this internally and never actually sends this to the
application. |
In response to a control signal, the handler must take whatever
action necessary and then notify the SCM by calling update_service_status, passing it new the process
state. For example, in response to a pause control, the application may take whatever
actions required to temporarily pause the service operation and
then respond by passing the paused
state to update_service_status. Alternatively, if the service
cannot be paused for whatever reason, it may respond by passing the
state running. Refer to update_service_status for details on valid responses.
It is very important to correctly notify the
service control manager of the state change.
The application must respond to every control notification with a
corresponding call to update_service_status. There is no hard time limit
during which this call must be made but it is a good idea not to
delay the response too long. update_service_status can be either invoked from the
handler itself or scheduled at some later point after the necessary
actions have been taken by the application. During this time, TWAPI
may internally send responses to the SCM essentially asking it to
keep waiting for an answer without timing out.
Because multiple controls may be received from the SCM before
previous controls have been fully processed, and to allow for
asynchronous responses from the application, a sequence number is
passed as the third argument to the callback. When the application
responds using update_service_status, this sequence number should be
passed to the call. When responses are made out-of-order, those
with older sequence numbers will be ignored.
In addition to the above control signals that may be sent by the
SCM, it may also send notifications to the service to inform it of
system events. These are passed on to the appropriate service
callback handler in the same fashion as the control signals. Unlike
for control signals, the application need not, and generally should
not, respond with a call to update status. However, it should
ensure the script returns an appropriate return value. Generally,
the return value should be an integer error code that is passed
back to the service control manager (0 being success). In some
cases, the script may also return allow
or deny.
In addition to the four arguments described for control signals,
some notifications may have additional arguments. The various
notifiations are shown in the able below.
all_stopped |
The all_stopped
notification is sent to the last running service in the application
when all other services in the process have been stopped. The
application should normally clean up and exit when this control is
received. The remaining arguments passed to the handler are either
empty strings or 0 and should not be
used. This notification is internally generated by TWAPI and not
sent by the system. |
hardwareprofilechange |
Notifies the application of events related to
changes to the system hardware profile. An additional argument
provides the specifics of the change and may be one of configchanged, configchangecanceled or querychangeconfig. In the case of querychangeconfig, the callback script may return
allow or deny to allow or deny the request. |
paramchange |
Notifies the application that one of its
configuration parameters has changed and it should re-read its
service information from the Windows registry. This is only
received if paramchange has been
specified as an element in the -controls option
to indicate to the service manager that the service can read and
change its configuration while running. |
netbindadd |
Refer to the Windows SDK. This is only received if
netbindchange has been specified as an
element in the -controls option. |
netbinddisable |
Refer to the Windows SDK. This is only received if
netbindchange has been specified as an
element in the -controls option. |
netbindenable |
Refer to the Windows SDK. This is only received if
netbindchange has been specified as an
element in the -controls option. |
netbindremove |
Refer to the Windows SDK. This is only received if
netbindchange has been specified as an
element in the -controls option. |
powerevent |
This notifies the application of a change in the
power status of the system. This is only received if powerevent has been specified as an element in the
-controls option. In addition to the standard
arguments, an additional argument is appended detailing the nature
of the change. This may be one of apmsuspend, apmstandby,
apmresumecritical, apmresumesuspend, apmresumestandby, apmbatterylow, apmpowerstatuschange, apmoemevent, apmresumeautomatic, apmquerysuspend, apmquerysuspendfailed, apmquerystandby, or apmquerystandbyfailed.
In the case of apmquerysuspend and
apmquerystandby, the callback script
may return allow or deny to allow or deny the request.
Note that not all events are present in every version of Windows.
See the Windows SDK for platform specific details. |
sessionchange |
Notifies that a session change event has occurred.
This is only received if sessionchange
has been specified as an element in the -controls option. In addition to the standard arguments,
two additional arguments are appended. The first of these indicates
the nature of the session change and is one of console_connect, console_disconnect, remote_connect, remote_disconnect, session_login, session_logoff, session_lock, session_unlock or session_remote_control.
The second additional argument is the session identifier for which
the event is being reported. |
user_defined |
The userdefined control
is strictly application-dependent and not used by the SCM. User
defined controls can be sent to a service using command line
utilities such as the Windows sc program. The
standard four arguments are passed on except that the fourth
argument, the numeric value of the control, will vary within the
range 128-255 and can be used by the application to distinguish
between different signals. |
Running as a service requires a threaded build of Tcl. An exception
will be raised on non-threaded builds.
- service_exists SERVICE_NAME ?options?
- This command returns 1 or 0 depending on whether a service with
the specified name exists or not. SERVICE_NAME
may be either the internal name of the service or the display name.
The options described in Standard
Options may be specified with this command.
- set_service_configuration INTERNAL_SERVICE_NAME ?options?
- This command allows modification of configuration data for the
service specified by INTERNAL_SERVICE_NAME. In
addition to the options described in Standard Options, the following options may
be specified to set configuration data. The values for any
unspecified options will remain unchanged.
-displayname DISPLAYNAME |
Specifies the user visible name for the service.
This is the name that is shown in the net
start command and the SCM control panel applet. |
-command COMMAND |
COMMAND contains the system
command to be executed to start the service. See description of
create_service for
details. |
-servicetype SERVICETYPE |
Specifies the service type. See description of
create_service for
details. |
-interactive BOOLEAN |
This option specifies whether the service should be
allowed to interact with the desktop. See description of this
option in command create_service for details. |
-starttype STARTTYPE |
Specifies how the service is to be started. See
description of this option in command create_service for valid
values for STARTTYPE. |
-errorcontrol ERRORCONTROLMODE |
This option specifies how errors during service
start are to be handled. See description of this option in command
create_service for
valid values for ERRORCONTROL. |
-loadordergroup GROUPNAME |
Specifies GROUPNAME to be the
service load order group to which the service belongs. If the
option is not specified, the service is assumed to not belong to
any load order group. |
-dependencies DEPENDENCYLIST |
Specifies the services and service load order
groups that are required by this service and that must start before
this service. See description of this option in command create_service for
details. |
-account ACCOUNTNAME |
Specifies ACCOUNTNAME to be the
user account under which the service should run. See description of
this option in command create_service for details. |
-password PASSWORD |
Specifies the password corresponding to the user
account specified in the -account option. This
option is ignored if the -account option is not
specified. |
- start_service INTERNAL_SERVICE_NAME
?options?
- This command starts the specified service if it is not already
running. INTERNAL_SERVICE_NAME must be the
internal name of the service, not the display name. The command
returns 1 if the service is up and running when the command
completes and 0 otherwise. Note that a return value of 0 does not
imply an error, just that the service had not completely started by
the time the command returned.
The options described in Standard
Options may be specified with this command. In addition, if the
option "-wait MILLISECONDS"
is specified the command will wait until the service is running or
until MILLISECONDS milliseconds have
expired.
- stop_service INTERNAL_SERVICE_NAME
?options?
- This command stops the specified service if it is currently
running. INTERNAL_SERVICE_NAME must be the
internal name of the service, not the display name. The command
returns 1 if the service has stopped by the time the command
completes and 0 otherwise. Note that a return value of 0 does not
imply an error, just that the service had not completely stopped by
the time the command returned.
The options described in Standard
Options may be specified with this command. In addition, if the
option "-wait MILLISECONDS"
is specified the command will wait until the service is stopped or
until MILLISECONDS milliseconds have
expired.
- update_service_status
SERVICENAME SEQNO STATE ?options?
- This command should be called by applications, running as a
Windows service, to update their status information with the
Windows service control manager (SCM). The command may be called
asynchronously at any time, but is most often called in response to
a control notification from the SCM requesting a state change. See
run_as_service for
more detail.
SERVICENAME is the name of the service whose
status is being updated.
SEQ is the sequence number of the control
notification to which this is the response. See the discussion in
the run_as_service
documentation. If the call is not in response to a control
notification, SEQ should be set to 0.
STATE is the of the application and should be
one of the values stopped, running or paused. Note
that an application can stop at any time, but should not generally
change state to running or paused on its own without a control notification
from the SCM. Doing so will in all likelihood confuse the SCM
manager sufficiently to make the service unmanageable.
If the service state being specified is stopped, the application may also indicate a
standard Windows exit code and a service-specific exit code by
specifying their values through the options -exitcode and -servicecode
respectively.
Copyright © 2003-2008 Ashok P. Nadkarni