소스 검색

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 년 전
부모
커밋
4440946ecc
7개의 변경된 파일211개의 추가작업 그리고 77개의 파일을 삭제
  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;
   }