Re: ServiceBase denies access to service name

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



I just did a simple test and confirmed my prior statement: the first argument
to a Win32 own service is the service name. My service executable name is
MyService.exe. I registered the service as follows:

sc create FooService binPath= c:\...\MyService.exe ...

In my service main I do the following:

void WINAPI Service::ServiceMain(DWORD /*argc*/, const char * const *argv)
{
// Cleanup
Service *service = NULL;
// Cleanup
wchar_t *name = NULL;
SERVICE_STATUS_HANDLE statusHandle;
unsigned long cch;
int result;

cch = strlen(argv[0]) + 1;

HANDLE file;
HRESULT hr;
DWORD bytesWritten;
if ((file = CreateFile("c:\\servicename", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE)
{
hr = GetLastError();
hr = HRESULT_FROM_WIN32(hr);
goto cleanup;
}
WriteFile(file, argv[0], strlen(argv[0]), &bytesWritten, NULL);
CloseHandle(file);

When I checked c:\servicename I see 'FooService'.
--
Thanks,
Nick

nicknospamdu@xxxxxxxxxxxxxxxx
remove "nospam" change community. to msn.com


"Stephen Martin" wrote:

#1 is done pretty much exactly the same way in .Net as it is in unmanaged
C/C++. The service name is not and has never been part of the command line
to a service executable. A service executable is just a normal Win32 binary
and has the exact same command line components as any other executable.
Let's say that arg[0] of the command line parameters to a service process
was the service name, what would arg[0] be in a service process that
contained two services named: MyServiceOne and MyServiceTwo?

#2 is easy enough using the Xml namespaces to parse your <service
name>.config file. Config files and the Configuration namespace classes are
a nice convenience but hardly necessary.

"nickdu" <nicknospamdu@xxxxxxxxxxxxxxxx> wrote in message
news:F916D1E1-2917-4EA5-8CF2-5AF2819158B2@xxxxxxxxxxxxxxxx
I don't mind being educated on any misconceptions I have, but I don't think
you're correct on every point. The goal of what I'm trying to do is:

1. I've created a single managed service process that I want to use to
handle multiple services, each in their own process.

2. Since each service would be using the same binary and each would need
its
own configuration, there needs to be some way for each service to have its
own configuration file. Similar to how web apps work I can envision some
service code create a new app domain and setting up the application config
to
be <service name>.config.

#1 is easy to do in the unmanaged world because I have access to the
command
line arguments and I'm pretty sure that the first command line argument is
the service name not the binary name. And unfortunately the .NET
implementation skips over the first command line argument.

--
Thanks,
Nick

nicknospamdu@xxxxxxxxxxxxxxxx
remove "nospam" change community. to msn.com


"Stephen Martin" wrote:

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" <nicknospamdu@xxxxxxxxxxxxxxxx> wrote in message
news:8A5E51C3-F8F4-4267-A299-EE7FFC0F5C5F@xxxxxxxxxxxxxxxx
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[i] = 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

nicknospamdu@xxxxxxxxxxxxxxxx
remove "nospam" change community. to msn.com




.



Relevant Pages

  • Re: ServiceBase denies access to service name
    ... A service executable is just a normal Win32 binary and has the exact same command line components as any other executable. ... Let's say that argof the command line parameters to a service process was the service name, what would argbe in a service process that contained two services named: ... the same service class but the names must be set in the Main method of the ... > each with its own application configuration file. ...
    (microsoft.public.dotnet.framework)
  • Re: ServiceBase denies access to service name
    ... service code create a new app domain and setting up the application config to ... line arguments and I'm pretty sure that the first command line argument is ... the same service class but the names must be set in the Main method of the ... each with its own application configuration file. ...
    (microsoft.public.dotnet.framework)
  • Re: ServiceBase denies access to service name
    ... The .NET service class should not be skipping over this value. ... and has the exact same command line components as any other executable. ... Let's say that argof the command line parameters to a service process ... each with its own application configuration file. ...
    (microsoft.public.dotnet.framework)
  • Re: ServiceBase denies access to service name
    ... configuration file so that any other code dependent on the application config ... and has the exact same command line components as any other executable. ... Let's say that argof the command line parameters to a service process ... Your service class ...
    (microsoft.public.dotnet.framework)
  • Re: Windows Remote Desktop over ssh
    ... > Did you really have a space between the first colon and the 10? ... On my windows - I am running the cygwin sshd and X server. ... when I paste the command elsewhere. ... # This is the ssh client system-wide configuration file. ...
    (comp.security.ssh)