Hi,
You seem to have a few misconceptions about .Net services and how the
ServiceName is set.
First of all you are misunderstanding the ServiceMainCallback and its
arguments. The arguments to ServiceMainCallback are not the command line
arguments of the executable but rather the arguments sent to the service
itself by the Service Control Manager. There is no service name argument, in
fact the arguments to ServiceMainCallback are almost always argCount = 0,
argPointer = null. These are the arguments sent to the OnStart method of
your service.
Even if these were the command line parameters arg[0] would be the name of
the executable not the service.
Also, this would not work for your purpose anyway since the
ServiceMainCallback is called by the SCM after ServiceBase.Run is called and
the ServiceName property has to be set before Run is called or the service
cannot properly connect to the SCM.
It is possible, and relatively easy, to run multiple named services using
the same service class but the names must be set in the Main method of the
service process before ServiceBase.Run is called. Your service class should
accept a name parameter in its constructor that is used to set the
ServiceName property.
You can then set up your service to run with a command line parameter that
is parsed in Main and sent to the service class in its constructor, each
named service would run in a different service process with a different
command line parameter. This, unfortunately, causes additional complexity
for installation and you may not want a separate executable for each
service.
Another method is to have a config file for the service executable that
contains the names of all the services in, say, its appSettings section.
This config file would be read in the Main method and a separate instance of
the service class would be created with each name and sent to the Run
method. This is easier to install and manage but many people do not go for
this for lack of isolation reasons.
If you wanted to go further and set up separate AppDomains for each service
you would do as above but your service class would just be a shell that
would spin up a worker thread and create a separate AppDomain into which
your real ServiceWork class would be loaded.
Hope this helps.
nickdu said:
It appears the ServiceBase class denies a derived class access to the
service
name. It does this in its ServiceMainCallback by the fact that it skips
over the first argument:
public unsafe void ServiceMainCallback(int argCount, IntPtr argPointer)
{
fixed (NativeMethods.SERVICE_STATUS* service_statusRef = &this.status)
{
string[] state = null;
if (argCount > 0)
{
char** chPtr = (char**) argPointer.ToPointer();
state = new string[argCount - 1];
for (int i = 0; i < state.Length; i++)
{
chPtr++;
state = Marshal.PtrToStringUni(*((IntPtr*) chPtr));
}
}
.
.
.
Can this be fixed to either:
1. Provide the parameter in the args value. I assume this would break a
bunch of apps so it's probably not possible.
or
2. Process the service name argument (arg[0]) and set the ServiceName
property on the service object.
Actually the feature I'm trying to implement is one where I can have
multiple instances of the same service (different service names of course)
each with its own application configuration file. To accomplish this the
ServiceBase class could have created a new appdomain and run the service
component in that domain setting the app configuration file to the name of
the service, similar to how ASP.NET sets the app configuration to
web.config.
--
Thanks,
Nick
(e-mail address removed)
remove "nospam" change community. to msn.com