Browse Source

Log messages properly.

Format messages from resource.  Use NSSM binary as the message source.
Note that replacing the binary is prevented if the event viewer is open.
Iain Patterson 14 years ago
parent
commit
4440946ecc
7 changed files with 211 additions and 77 deletions
  1. 9 27
      event.cpp
  2. 1 2
      event.h
  3. 149 0
      messages.mc
  4. 1 3
      nssm.cpp
  5. 14 14
      nssm.vcproj
  6. 17 17
      registry.cpp
  7. 20 14
      service.cpp

+ 9 - 27
event.cpp

@@ -1,40 +1,22 @@
 #include "nssm.h"
 
-/* Convert error code to error string - must call LocalFree() on return value */
-char *error_string(unsigned long error) {
-  static char message[65535];
-  if (! FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, 0, NSSM_MESSAGE_DEFAULT, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), message, sizeof(message), 0)) return 0;
-  return message;
-}
-
 /* Log a message to the Event Log */
-void eventprintf(unsigned short type, unsigned long id, char *format, ...) {
-  char message[4096];
-  char *strings[2];
-  int n, size;
+void log_event(unsigned short type, unsigned long id, ...) {
   va_list arg;
+  int count;
+  char *s;
+  char *strings[6];
 
-  /* Construct the message */
-  size = sizeof(message);
-  va_start(arg, format);
-  n = _vsnprintf(message, size, format, arg);
-  va_end(arg);
-
-  /* Check success */
-  if (n < 0 || n >= size) return;
-
-  /* Construct strings array */
-  strings[0] = message;
-  strings[1] = 0;
-    
   /* Open event log */
   HANDLE handle = RegisterEventSource(0, TEXT(NSSM));
   if (! handle) return;
 
   /* Log it */
-  if (! ReportEvent(handle, type, 0, id, 0, 1, 0, (const char **) strings, 0)) {
-    printf("ReportEvent(): %s\n", error_string(GetLastError()));
-  }
+  count = 0;
+  va_start(arg, id);
+  while ((s = va_arg(arg, char *))) strings[count++] = s;
+  va_end(arg);
+  ReportEvent(handle, type, 0, id, 0, count, 0, (const char **) strings, 0);
 
   /* Close event log */
   DeregisterEventSource(handle);

+ 1 - 2
event.h

@@ -1,7 +1,6 @@
 #ifndef EVENT_H
 #define EVENT_H
 
-char *error_string(unsigned long);
-void eventprintf(unsigned short, unsigned long, char *, ...);
+void log_event(unsigned short, unsigned long, ...);
 
 #endif

+ 149 - 0
messages.mc

@@ -0,0 +1,149 @@
+LanguageNames=(English=0x0409:MSG00409)
+
+MessageId = 1001
+SymbolicName = NSSM_EVENT_DISPATCHER_FAILED
+Severity = Error
+Language = English
+StartServiceCtrlDispatcher() failed:
+%1
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OPENSCMANAGER_FAILED
+Severity = Error
+Language = English
+Unable to connect to service manager!
+Perhaps you need to be an administrator...
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OUT_OF_MEMORY
+Severity = Error
+Language = English
+Out of memory for %1 in %2!
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_GET_PARAMETERS_FAILED
+Severity = Error
+Language = English
+Failed to get startup parameters for service %1.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED
+Severity = Error
+Language = English
+RegisterServiceCtrlHandlerEx() failed:
+%1
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_START_SERVICE_FAILED
+Severity = Error
+Language = English
+Can't start %1 for service %2.
+Error code: %3.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_RESTART_SERVICE_FAILED
+Severity = Warning
+Language = English
+Failed to restart %1 for service %2.
+Sleeping...
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_STARTED_SERVICE
+Severity = Informational
+Language = English
+Started %1 %2 for service %3 in %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED
+Severity = Warning
+Language = English
+Service %1 may claim to be still running when %2 exits.
+RegisterWaitForSingleObject() failed:
+%3
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_CREATEPROCESS_FAILED
+Severity = Error
+Language = English
+Failed to start service %1.  Program %2 couldn't be launched.
+CreateProcess() failed:
+%3
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_TERMINATEPROCESS
+Severity = Informational
+Language = English
+Requested stop of service %1.  Killing program %2.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_PROCESS_ALREADY_STOPPED
+Severity = Informational
+Language = English
+Requested stop of service %1.  No action is required as program %2 is not running.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_ENDED_SERVICE
+Severity = Informational
+Language = English
+Program %1 for service %2 exited with return code %3.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_RESTART
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+Attempting to restart %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_IGNORE
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+No action will be taken to restart %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_REALLY
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+Exiting.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OPENKEY_FAILED
+Severity = Error
+Language = English
+Failed to open registry key HKLM\%1:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_QUERYVALUE_FAILED
+Severity = Error
+Language = English
+Failed to read registry value %1:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_SETVALUE_FAILED
+Severity = Error
+Language = English
+Failed to write registry value %1:
+%2
+.

+ 1 - 3
nssm.cpp

@@ -45,9 +45,7 @@ int main(int argc, char **argv) {
   /* Start service magic */
   SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } };
   if (! StartServiceCtrlDispatcher(table)) {
-    char *message = error_string(GetLastError());
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "StartServiceCtrlDispatcher() failed: %s", message);
-    if (message) LocalFree(message);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, GetLastError(), 0);
     return 100;
   }
 

+ 14 - 14
nssm.vcproj

@@ -33,9 +33,9 @@
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
-				Description="Compiling messages"
-				CommandLine="mc -A &quot;$(InputDir)\$(InputName).mc&quot; -r &quot;$(InputDir)&quot; -h &quot;$(InputDir)&quot;"
-				Outputs="$(InputDir)\$(InputName).rc;$(InputDir)\$(InputName).h"
+				Description=""
+				CommandLine=""
+				Outputs=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
@@ -125,9 +125,9 @@
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
-				Description="Compiling messages"
-				CommandLine="mc -A &quot;$(InputDir)\$(InputName).mc&quot; -r &quot;$(InputDir)&quot; -h &quot;$(InputDir)&quot;"
-				Outputs="$(InputDir)\$(InputName).rc;$(InputDir)\$(InputName).h"
+				Description=""
+				CommandLine=""
+				Outputs=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
@@ -654,8 +654,8 @@
 				<Tool
 					Name="VCCustomBuildTool"
 					Description="Compiling messages"
-					CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"
-					Outputs="$(InputFileName).rc;$(InputFileName).h"
+					CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"
+					Outputs="$(InputName).rc;$(InputName).h"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -664,8 +664,8 @@
 				<Tool
 					Name="VCCustomBuildTool"
 					Description="Compiling messages"
-					CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"
-					Outputs="$(InputFileName).rc;$(InputFileName).h"
+					CommandLine="mc -A $(InputDir)\$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"
+					Outputs="$(InputName).rc;$(InputName).h"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -674,9 +674,9 @@
 				<Tool
 					Name="VCCustomBuildTool"
 					Description="Compiling messages"
-					CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"
+					CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"
 					AdditionalDependencies=""
-					Outputs="$(InputFileName).rc;$(InputFileName).h"
+					Outputs="$(InputName).rc;$(InputName).h"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -685,9 +685,9 @@
 				<Tool
 					Name="VCCustomBuildTool"
 					Description="Compiling messages"
-					CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"
+					CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"
 					AdditionalDependencies=""
-					Outputs="$(InputFileName).rc;$(InputFileName).h"
+					Outputs="$(InputName).rc;$(InputName).h"
 				/>
 			</FileConfiguration>
 		</File>

+ 17 - 17
registry.cpp

@@ -5,12 +5,12 @@ int create_messages() {
 
   char registry[MAX_PATH];
   if (_snprintf(registry, sizeof(registry), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", NSSM) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for eventlog registry()!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "eventlog registry", "create_messages()", 0);
     return 1;
   }
 
   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open eventlog registry!", NSSM_REGISTRY);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);
     return 2;
   }
 
@@ -30,32 +30,32 @@ int create_parameters(char *service_name, char *exe, char *flags, char *dir) {
   /* Get registry */
   char registry[MAX_PATH];
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY, service_name) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REGISTRY in create_parameters()!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REGISTRY", "create_parameters()", 0);
     return 1;
   }
 
   /* Try to open the registry */
   HKEY key;
   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service registry settings!", NSSM_REGISTRY);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);
     return 2;
   }
 
   /* Try to create the parameters */
   if (RegSetValueEx(key, NSSM_REG_EXE, 0, REG_SZ, (const unsigned char *) exe, strlen(exe) + 1) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_EXE, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     return 3;
   }
   if (RegSetValueEx(key, NSSM_REG_FLAGS, 0, REG_SZ, (const unsigned char *) flags, strlen(flags) + 1) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_FLAGS, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     return 4;
   }
   if (RegSetValueEx(key, NSSM_REG_DIR, 0, REG_SZ, (const unsigned char *) dir, strlen(dir) + 1) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_DIR, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     return 5;
@@ -71,7 +71,7 @@ int create_exit_action(char *service_name, const char *action_string) {
   /* Get registry */
   char registry[MAX_PATH];
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY "\\%s", service_name, NSSM_REG_EXIT) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REG_EXIT in create_exit_action()!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REG_EXIT", "create_exit_action()", 0);
     return 1;
   }
 
@@ -79,7 +79,7 @@ int create_exit_action(char *service_name, const char *action_string) {
   HKEY key;
   unsigned long disposition;
   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &disposition) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service exit action registry settings!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);
     return 2;
   }
 
@@ -91,7 +91,7 @@ int create_exit_action(char *service_name, const char *action_string) {
 
   /* Create the default value */
   if (RegSetValueEx(key, 0, 0, REG_SZ, (const unsigned char *) action_string, strlen(action_string) + 1) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add default registry value %s: %s", NSSM_REG_EXIT, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXIT, GetLastError(), 0);
     RegCloseKey(key);
     return 3;
   }
@@ -106,14 +106,14 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
   /* Get registry */
   char registry[MAX_PATH];
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY, service_name) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REGISTRY in get_parameters()!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REGISTRY", "get_parameters()", 0);
     return 1;
   }
 
   /* Try to open the registry */
   HKEY key;
   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, KEY_READ, &key) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service registry settings!", NSSM_REGISTRY);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);
     return 2;
   }
 
@@ -121,21 +121,21 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
 
   /* Try to get executable file - MUST succeed */
   if (RegQueryValueEx(key, NSSM_REG_EXE, 0, &type, (unsigned char *) exe, (unsigned long *) &exelen) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application path (registry value %s): %s", NSSM_REG_EXE, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);
     RegCloseKey(key);
     return 3;
   }
 
   /* Try to get flags - may fail */
   if (RegQueryValueEx(key, NSSM_REG_FLAGS, 0, &type, (unsigned char *) flags, (unsigned long *) &flagslen) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application flags (registry value %s): %s", NSSM_REG_FLAGS, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);
     RegCloseKey(key);
     return 4;
   }
 
   /* Try to get startup directory - may fail */
   if (RegQueryValueEx(key, NSSM_REG_DIR, 0, &type, (unsigned char *) dir, (unsigned long *) &dirlen) != ERROR_SUCCESS) {
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application startup directory (registry value %s): %s", NSSM_REG_DIR, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);
     RegCloseKey(key);
     return 5;
   }
@@ -150,7 +150,7 @@ int get_exit_action(char *service_name, unsigned long *ret, unsigned char *actio
   /* Get registry */
   char registry[MAX_PATH];
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY "\\%s", service_name, NSSM_REG_EXIT) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REG_EXIT in get_exit_action()!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REG_EXIT", "get_exit_action()", 0);
     return 1;
   }
 
@@ -158,7 +158,7 @@ int get_exit_action(char *service_name, unsigned long *ret, unsigned char *actio
   HKEY key;
   long error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, KEY_READ, &key);
   if (error != ERROR_SUCCESS && error != ERROR_FILE_NOT_FOUND) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open registry %s!", registry);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);
     return 2;
   }
 

+ 20 - 14
service.cpp

@@ -16,7 +16,7 @@ static const char *exit_action_strings[] = { "Restart", "Ignore", "Exit", 0 };
 SC_HANDLE open_service_manager() {
   SC_HANDLE ret = OpenSCManager(0, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
   if (! ret) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Unable to connect to service manager!\nPerhaps you need to be an administrator...");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENSCMANAGER_FAILED, 0);
     return 0;
   }
 
@@ -139,7 +139,7 @@ int remove_service(char *name) {
 /* Service initialisation */
 void WINAPI service_main(unsigned long argc, char **argv) {
   if (_snprintf(service_name, sizeof(service_name), "%s", argv[0]) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): Out of memory for service_name!");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "service_name", "service_main()", 0);
     return;
   }
 
@@ -159,14 +159,14 @@ void WINAPI service_main(unsigned long argc, char **argv) {
   /* Get startup parameters */
   int ret = get_parameters(argv[0], exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir));
   if (ret) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): Can't get startup parameters: error %d", ret);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, argv[0], 0);
     return;
   }
 
   /* Register control handler */
   service_handle = RegisterServiceCtrlHandlerEx(NSSM, service_control_handler, 0);
   if (! service_handle) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): RegisterServiceCtrlHandlerEx() failed: %s", error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED, GetLastError(), 0);
     return;
   }
 
@@ -180,14 +180,16 @@ int monitor_service() {
   /* Set service status to started */
   int ret = start_service();
   if (ret) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't start service %s: error code %d", service_name, ret);
+    char code[16];
+    snprintf(code, sizeof(code), "%d", ret);
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, exe, service_name, ret, 0);
     return ret;
   }
-  eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Started process %s %s in %s for service %s", exe, flags, dir, service_name);
+  log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_STARTED_SERVICE, exe, flags, service_name, dir, 0);
 
   /* Monitor service service */
   if (! RegisterWaitForSingleObject(&wait_handle, pid, end_service, 0, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION)) {
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "RegisterWaitForSingleObject() returned %s - service may claim to be still running when %s exits ", error_string(GetLastError()), exe);
+    log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service_name, exe, GetLastError(), 0);
   }
 
   return 0;
@@ -222,11 +224,11 @@ int start_service() {
   /* Launch executable with arguments */
   char cmd[MAX_PATH];
   if (_snprintf(cmd, sizeof(cmd), "%s %s", exe, flags) < 0) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Error constructing command line");
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "command line", "start_service", 0);
     return stop_service(2);
   }
   if (! CreateProcess(0, cmd, 0, 0, 0, 0, 0, dir, &si, &pi)) {
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't launch %s.  CreateProcess() returned %s", exe, error_string(GetLastError()));
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service_name, exe, GetLastError(), 0);
     return stop_service(3);
   }
   pid = pi.hProcess;
@@ -247,9 +249,11 @@ int stop_service(unsigned long exitcode) {
   /* Nothing to do if server isn't running */
   if (pid) {
     /* Shut down server */
+    log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_TERMINATEPROCESS, service_name, exe, 0);
     TerminateProcess(pid, 0);
     pid = 0;
   }
+  else log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_PROCESS_ALREADY_STOPPED, service_name, exe, 0);
 
   /* Signal we stopped */
   service_status.dwCurrentState = SERVICE_STOPPED;
@@ -272,7 +276,9 @@ void CALLBACK end_service(void *arg, unsigned char why) {
   unsigned long ret = 0;
   GetExitCodeProcess(pid, &ret);
 
-  eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Process %s for service %s exited with return code %u", exe, service_name, ret);
+  char code[16];
+  _snprintf(code, sizeof(code), "%d", ret);
+  log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_ENDED_SERVICE, exe, service_name, code, 0);
 
   /* What action should we take? */
   int action = NSSM_EXIT_RESTART;
@@ -290,22 +296,22 @@ void CALLBACK end_service(void *arg, unsigned char why) {
   switch (action) {
     /* Try to restart the service or return failure code to service manager */
     case NSSM_EXIT_RESTART:
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Attempting to restart %s for service %s", ret, exit_action_strings[action], exe, service_name);
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_RESTART, service_name, code, exit_action_strings[action], exe, 0);
       while (monitor_service()) {
-        eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Failed to restart %s - sleeping ", exe, ret);
+        log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_RESTART_SERVICE_FAILED, exe, service_name, 0);
         Sleep(30000);
       }
     break;
 
     /* Do nothing, just like srvany would */
     case NSSM_EXIT_IGNORE:
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Not attempting to restart %s for service %s", ret, exit_action_strings[action], exe, service_name);
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_IGNORE, service_name, code, exit_action_strings[action], exe, 0);
       Sleep(INFINITE);
     break;
 
     /* Tell the service manager we are finished */
     case NSSM_EXIT_REALLY:
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Stopping service %s", ret, exit_action_strings[action], service_name);
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_REALLY, service_name, code, exit_action_strings[action], 0);
       stop_service(ret);
     break;
   }