![]() |
General Reading »
Hardware & System »
Windows Services
Intermediate
License: The Code Project Open License (CPOL)
Start Your Windows Programs From An NT ServiceBy Xiangyang Liu 刘向阳Make your MFC, VB and other Windows programs behave like NT services. |
VC6Win2K, Visual Studio, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
Typically, a Windows service -- used to be called NT service -- is a console application that does not have a message pump. A Windows service can be started without the user having to log into the computer and it won't die after the user logs off. However, it is hard -- sometimes impossible -- to use many existing ActiveX controls within a console application.
On the other hand, MFC and VB applications are Windows applications, so using ActiveX controls in MFC or VB programs is extremely easy. It would be nice to make your MFC and VB programs run like a Windows service, so that:
It is possible to write a Windows service as a Windows program, but here I am proposing a much easier solution. I have included with this article the source code for a simple Windows service program that can start and shut down other programs. All you need to do is install this service and modify the INI file. Here are the advantages of using this simple Windows service:
My desktop PC in the office was recently re-imaged by the support folks of my company. The first time I signed in, I noticed that a Java program was busy doing something in the background. When I looked deeper, it became clear that this Java program was started by a modified version of the Windows service explained in this article. Later, I found out that another development team in my company got this "great open source tool" from the internet and they modified it to run their Java programs :-).
XYNTService.exe is the name of the executable for this Windows service program. You may get this Windows service from other websites, but Code Project is the official place to get the most recent version. You can freely use and modify the source code included with this article. I am aware that there are other utility programs providing almost the same functionality as XYNTService. However, as you will see, XYNTService has more features and is a lot easier to use. For example, no editing of the registry is required. Here is how to use the program:
XYNTService -i. XYNTService -u. By default, the installed service will be started automatically when you reboot the computer. You can also start and shut down the service from the Control Panel or the Administrative Tools using the Services option. When the service is started, it will create all of the processes you defined in the XYNTService.ini file one by one. When the service is shut down, it will terminate each of the processes it created in reverse order. The XYNTService.ini file should be placed in the same directory as the executable. Here is a sample of the file:
[Settings]
ServiceName = XYNTService
CheckProcessSeconds = 30
[Process0]
CommandLine = c:\winnt\system32\notepad.exe
WorkingDir= c:\
PauseStart= 1000
PauseEnd= 1000
UserInterface = Yes
Restart = Yes
[Process1]
CommandLine = java.exe MyPackage.MyClass
Restart = No
UserName =
Domain =
Password =
The ServiceName property specifies the name you want to use for this NT service. The default name is XYNTService. If you copy the executable and the INI file into a different directory and then modify the ServiceName property in the INI file, you can install and configure a different service!
The sections [Process0], [Process1], ..., etc. define the properties related to each of these processes. As you can see, there are two processes to create in this example. notepad.exe and java.exe are the names of these programs. You can specify the parameters for each of these processes in the CommandLine property. You must specify the full path of the executable file for the corresponding process in the CommandLine property unless the executable is already in the system path.
The CheckProcessSeconds property specifies if and how often you want to check the processes started by XYNTService. If the property has value 0, then no checking is done. If, for example, the property value is 30 then every 30 seconds XYNTService will query the operating system to see if the processes it started are still running. The dead ones will be restarted if the Restart property value (explained later) is defined as Yes for that process. The default value of this property, if you don't specify it, is 600 (10 minutes).
Note: In the previous versions of XYNTService, the ProcCount value specified how many processes were started by XYNTService. This is no longer required. The CheckProcess value is the number of minutes instead of seconds. The current version will work as before if you use CheckProcess instead of CheckProcessSeconds; you should not use both.
The WorkingDir property is the working directory of the current process. If you don't specify this property, then the working directory of the current process will be c:\winnt\system32. The PauseStart property is the number of milliseconds the service will wait after starting the current process and before starting the next process. This is useful where the next process depends on the previous process. For example, the second process has to "connect" to the first process in such a way that it does not run until the first process is finished with initialization. If you don't specify the PauseStart property, the default value will be 100 milliseconds.
When XYNTService is shut down, it will post WM_QUIT messages to the processes it created first and then call the Win32 function TerminateProcess. The PauseEnd property is the number of milliseconds the service will wait before TerminateProcess is called. This property can be used to give a process (started by XYNTService) a chance to clean up and shutdown itself. If you don't specify the PauseEnd property, the default value will be 100 milliseconds.
The UserInterface property controls whether a logged-in user can see the processes created by XYNTService. However, this only works when XYNTService is running under the local system account, which is the default. In this case, processes created by XYNTService will not be able to access a specific user's settings, such as mapped network drives, etc. You can configure XYNTService to run under a user account, which is done easily from the Control Panel or Administrative Tools. Just select Services and then double click XYNTService in the installed services list to bring up a dialog box.
The Restart property is used to decide whether you want XYNTService to restart a dead process. If this property is No, which is the default if you don't specify any value, then the corresponding process will not be restarted. If this property is Yes, then the dead process will be restarted by XYNTService. See the CheckProcess property above on how often dead processes are restarted. You can bounce (stop and restart) any process defined in the INI file from the command line. For example, the following command...
XYNTService -b 2
...will stop and restart the process defined in the [Process2] section of the INI file. XYNTService can also be used to start and stop other services from the command line. Here are the commands to start (run) and stop (kill) other services:
XYNTService -r NameOfServiceToRun
XYNTService -k NameOfServiceToKill
In particular, you can use the above commands to start and stop XYNTService from the command line! Important note: You cannot start XYNTService by running it from the command prompt without an argument.
All errors while running XYNTService are written into a log file in the same directory as the executable. The error code in the log file is a decimal number returned by the GetLastError API. You can look for it on MSDN.
The UserName, Domain, and Password properties are used to impersonate a user. If UserName and Password are not empty, then the corresponding process will be started using the specified user account. If Domain is empty, then the specified user account must be an account on the local machine instead of a network account. In order to impersonate a user, the service must be run by a local system. Also, the corresponding user account must have the "logon as service" privilege. If you configure a service to run under a user account, that account will acquire the "logon as service" privilege. Please note that you won't be able to see the user interface of an impersonated process.
Since we may need to put a user password in the INI file, it is important to make sure that the INI file is only accessible by administrators and the local system. The following command will protect the current folder, making it accessible only by administrators and the local system.
cacls . /g system:F administrators:F
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 22 Feb 2008 Editor: Chris Maunder |
Copyright 2000 by Xiangyang Liu 刘向阳 Everything else Copyright © CodeProject, 1999-2009 Web10 | Advertise on the Code Project |