Skip to content

First chance exceptions and missing logging when a service isn't given a service name #62923

@ericstj

Description

@ericstj

See #62579 (comment)

The default behavior for ServiceBase when a ServiceName isn't specified is to use an empty string. Per https://docs.microsoft.com/en-us/windows/win32/api/winsvc/ns-winsvc-service_table_entrya

If the service is installed with the SERVICE_WIN32_OWN_PROCESS service type, this member is ignored, but cannot be NULL. This member can be an empty string ("").

The problem, however, is that later on we use ServiceName to construct a log:

_eventLog = new EventLog("Application")
{
Source = ServiceName
};

And EventLog will throw for an empty Source:

if (Source.Length == 0)
throw new ArgumentException(SR.NeedSourceToWrite);

So in this common scenario all of these calls to WriteEventLog result in first chance exceptions, and nothing is logged:

private void WriteLogEntry(string message, EventLogEntryType type = EventLogEntryType.Information)
{
// EventLog failures shouldn't affect the service operation
try
{
if (AutoLog)
{
EventLog.WriteEntry(message, type);
}
}
catch
{
// Do nothing. Not having the event log is bad, but not starting the service as a result is worse.
}
}

In this scenario we can actually acquire the service name from SCM, it's returned in the ServiceMain callback https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nc-winsvc-lpservice_main_functiona

the first argument (lpServiceArgVectors[0]) is the name of the service

I have confirmed this to be the case. So we can simply capture it here and set ServiceName rather than skipping it:

if (argCount > 0)
{
char** argsAsPtr = (char**)argPointer.ToPointer();
//Lets read the arguments
// the first arg is always the service name. We don't want to pass that in.
args = new string[argCount - 1];
for (int index = 0; index < args.Length; ++index)
{
// we increment the pointer first so we skip over the first argument.
argsAsPtr++;
args[index] = Marshal.PtrToStringUni((IntPtr)(*argsAsPtr))!;
}
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions