mysqlwatch.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:19k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /****************************************************************************
  2.    MySqlWatch    - WinNT service program MySQL
  3.                  - Re-start MySql server in case of failure
  4. *****************************************************************************/
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <process.h>
  9. #include <tchar.h>
  10. // name of the executable
  11. #define SZAPPNAME            "mysqlwatch"
  12. // internal name of the service
  13. #define SZSERVICENAME        "MySqlWatch"
  14. // displayed name of the service
  15. #define SZSERVICEDISPLAYNAME "MySqlWatch"
  16. // list of service dependencies - "dep1dep2"
  17. #define SZDEPENDENCIES       ""
  18. VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
  19. VOID ServiceStop(void);
  20. BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
  21. void AddToMessageLog(LPTSTR lpszMsg);
  22. // internal variables
  23. SERVICE_STATUS          ssStatus;       // current status of the service
  24. SERVICE_STATUS_HANDLE   sshStatusHandle;
  25. DWORD                   dwErr = 0;
  26. BOOL                    bDebug = FALSE;
  27. TCHAR                   szErr[256];
  28. // internal function prototypes
  29. void WINAPI service_ctrl(DWORD dwCtrlCode);
  30. void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
  31. void CmdInstallService(void);
  32. void CmdRemoveService(void);
  33. void CmdDebugService(int argc, char **argv);
  34. BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
  35. LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
  36. //
  37. //  FUNCTION: main
  38. //
  39. //  PURPOSE: entrypoint for service
  40. //
  41. //  PARAMETERS:
  42. //    argc - number of command line arguments
  43. //    argv - array of command line arguments
  44. //
  45. //  RETURN VALUE:
  46. //    none
  47. //
  48. //  COMMENTS:
  49. //    main() either performs the command line task, or
  50. //    call StartServiceCtrlDispatcher to register the
  51. //    main service thread.  When the this call returns,
  52. //    the service has stopped, so exit.
  53. //
  54. void main(int argc, char **argv)
  55. {
  56.     SERVICE_TABLE_ENTRY dispatchTable[] =
  57.     {
  58.         { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },
  59.         { NULL, NULL }
  60.     };
  61.     if ( (argc > 1) &&
  62.          ((*argv[1] == '-') || (*argv[1] == '/')) )
  63.     {
  64.         if ( stricmp( "install", argv[1]+1 ) == 0 )
  65.         {
  66.             CmdInstallService();
  67.         }
  68.         else if ( stricmp( "remove", argv[1]+1 ) == 0 )
  69.         {
  70.             CmdRemoveService();
  71.         }
  72.         else if ( stricmp( "debug", argv[1]+1 ) == 0 )
  73.         {
  74.             bDebug = TRUE;
  75.             CmdDebugService(argc, argv);
  76.         }
  77.         else
  78.         {
  79.             goto dispatch;
  80.         }
  81.         exit(0);
  82.     }
  83.     // if it doesn't match any of the above parameters
  84.     // the service control manager may be starting the service
  85.     // so we must call StartServiceCtrlDispatcher
  86.     dispatch:
  87.         // this is just to be friendly
  88.         printf( "%s -install          to install the servicen", SZAPPNAME );
  89.         printf( "%s -remove           to remove the servicen", SZAPPNAME );
  90.         printf( "%s -debug <params>   to run as a console app for debuggingn", SZAPPNAME );
  91.         printf( "nStartServiceCtrlDispatcher being called.n" );
  92.         printf( "This may take several seconds.  Please wait.n" );
  93.         if (!StartServiceCtrlDispatcher(dispatchTable))
  94.             AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
  95. }
  96. //
  97. //  FUNCTION: service_main
  98. //
  99. //  PURPOSE: To perform actual initialization of the service
  100. //
  101. //  PARAMETERS:
  102. //    dwArgc   - number of command line arguments
  103. //    lpszArgv - array of command line arguments
  104. //
  105. //  RETURN VALUE:
  106. //    none
  107. //
  108. //  COMMENTS:
  109. //    This routine performs the service initialization and then calls
  110. //    the user defined ServiceStart() routine to perform majority
  111. //    of the work.
  112. //
  113. void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
  114. {
  115.     // register our service control handler:
  116.     //
  117.     sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
  118.     if (!sshStatusHandle)
  119.         goto cleanup;
  120.     // SERVICE_STATUS members that don't change in example
  121.     //
  122.     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  123.     ssStatus.dwServiceSpecificExitCode = 0;
  124.     // report the status to the service control manager.
  125.     //
  126.     if (!ReportStatusToSCMgr(
  127.         SERVICE_START_PENDING, // service state
  128.         NO_ERROR,              // exit code
  129.         3000))                 // wait hint
  130.         goto cleanup;
  131.     ServiceStart( dwArgc, lpszArgv );
  132. cleanup:
  133.     // try to report the stopped status to the service control manager.
  134.     //
  135.     if (sshStatusHandle)
  136.         ReportStatusToSCMgr(
  137.                             SERVICE_STOPPED,
  138.                             dwErr,
  139.                             0);
  140.     return;
  141. }
  142. //
  143. //  FUNCTION: service_ctrl
  144. //
  145. //  PURPOSE: This function is called by the SCM whenever
  146. //           ControlService() is called on this service.
  147. //
  148. //  PARAMETERS:
  149. //    dwCtrlCode - type of control requested
  150. //
  151. //  RETURN VALUE:
  152. //    none
  153. //
  154. //  COMMENTS:
  155. //
  156. void WINAPI service_ctrl(DWORD dwCtrlCode)
  157. {
  158.     // Handle the requested control code.
  159.     //
  160.     switch(dwCtrlCode)
  161.     {
  162.         // Stop the service.
  163.         //
  164.         case SERVICE_CONTROL_STOP:
  165.             ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
  166.             ServiceStop();
  167.             break;
  168.         // Update the service status.
  169.         //
  170.         case SERVICE_CONTROL_INTERROGATE:
  171.             break;
  172.         // invalid control code
  173.         //
  174.         default:
  175.             break;
  176.     }
  177.     ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
  178. }
  179. //
  180. //  FUNCTION: ReportStatusToSCMgr()
  181. //
  182. //  PURPOSE: Sets the current status of the service and
  183. //           reports it to the Service Control Manager
  184. //
  185. //  PARAMETERS:
  186. //    dwCurrentState - the state of the service
  187. //    dwWin32ExitCode - error code to report
  188. //    dwWaitHint - worst case estimate to next checkpoint
  189. //
  190. //  RETURN VALUE:
  191. //    TRUE  - success
  192. //    FALSE - failure
  193. //
  194. //  COMMENTS:
  195. //
  196. BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
  197.                          DWORD dwWin32ExitCode,
  198.                          DWORD dwWaitHint)
  199. {
  200.     static DWORD dwCheckPoint = 1;
  201.     BOOL fResult = TRUE;
  202.     if ( !bDebug ) // when debugging we don't report to the SCM
  203.     {
  204.         if (dwCurrentState == SERVICE_START_PENDING)
  205.             ssStatus.dwControlsAccepted = 0;
  206.         else
  207.             ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  208.         ssStatus.dwCurrentState = dwCurrentState;
  209.         ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  210.         ssStatus.dwWaitHint = dwWaitHint;
  211.         if ( ( dwCurrentState == SERVICE_RUNNING ) ||
  212.              ( dwCurrentState == SERVICE_STOPPED ) )
  213.             ssStatus.dwCheckPoint = 0;
  214.         else
  215.             ssStatus.dwCheckPoint = dwCheckPoint++;
  216.         // Report the status of the service to the service control manager.
  217.         //
  218.         if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
  219.             AddToMessageLog(TEXT("SetServiceStatus"));
  220.         }
  221.     }
  222.     return fResult;
  223. }
  224. //
  225. //  FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
  226. //
  227. //  PURPOSE: Allows any thread to log an error message
  228. //
  229. //  PARAMETERS:
  230. //    lpszMsg - text for message
  231. //
  232. //  RETURN VALUE:
  233. //    none
  234. //
  235. //  COMMENTS:
  236. //
  237. void AddToMessageLog(LPTSTR lpszMsg)
  238. {
  239.     TCHAR   szMsg[256];
  240.     HANDLE  hEventSource;
  241.     LPTSTR  lpszStrings[2];
  242.     if ( !bDebug )
  243.     {
  244.         dwErr = GetLastError();
  245.         // Use event logging to log the error.
  246.         //
  247.         hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
  248.         _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
  249.         lpszStrings[0] = szMsg;
  250.         lpszStrings[1] = lpszMsg;
  251.         if (hEventSource != NULL) {
  252.             ReportEvent(hEventSource, // handle of event source
  253.                 EVENTLOG_ERROR_TYPE,  // event type
  254.                 0,                    // event category
  255.                 0,                    // event ID
  256.                 NULL,                 // current user's SID
  257.                 2,                    // strings in lpszStrings
  258.                 0,                    // no bytes of raw data
  259.                 lpszStrings,          // array of error strings
  260.                 NULL);                // no raw data
  261.              DeregisterEventSource(hEventSource);
  262.         }
  263.     }
  264. }
  265. ///////////////////////////////////////////////////////////////////
  266. //
  267. //  The following code handles service installation and removal
  268. //
  269. //
  270. //  FUNCTION: CmdInstallService()
  271. //
  272. //  PURPOSE: Installs the service
  273. //
  274. //  PARAMETERS:
  275. //    none
  276. //
  277. //  RETURN VALUE:
  278. //    none
  279. //
  280. //  COMMENTS:
  281. //
  282. void CmdInstallService()
  283. {
  284.     SC_HANDLE   schService;
  285.     SC_HANDLE   schSCManager;
  286.     TCHAR szPath[512];
  287.     if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
  288.     {
  289.         _tprintf(TEXT("Unable to install %s - %sn"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
  290.         return;
  291.     }
  292.     schSCManager = OpenSCManager(
  293.                         NULL,                   // machine (NULL == local)
  294.                         NULL,                   // database (NULL == default)
  295.                         SC_MANAGER_ALL_ACCESS   // access required
  296.                         );
  297.     if ( schSCManager )
  298.     {
  299.         schService = CreateService(
  300.             schSCManager,               // SCManager database
  301.             TEXT(SZSERVICENAME),        // name of service
  302.             TEXT(SZSERVICEDISPLAYNAME), // name to display
  303.             SERVICE_ALL_ACCESS,         // desired access
  304.             SERVICE_WIN32_OWN_PROCESS,  // service type
  305.             SERVICE_DEMAND_START,       // start type
  306.             SERVICE_ERROR_NORMAL,       // error control type
  307.             szPath,                     // service's binary
  308.             NULL,                       // no load ordering group
  309.             NULL,                       // no tag identifier
  310.             TEXT(SZDEPENDENCIES),       // dependencies
  311.             NULL,                       // LocalSystem account
  312.             NULL);                      // no password
  313.         if ( schService )
  314.         {
  315.             _tprintf(TEXT("%s installed.n"), TEXT(SZSERVICEDISPLAYNAME) );
  316.             CloseServiceHandle(schService);
  317.         }
  318.         else
  319.         {
  320.             _tprintf(TEXT("CreateService failed - %sn"), GetLastErrorText(szErr, 256));
  321.         }
  322.         CloseServiceHandle(schSCManager);
  323.     }
  324.     else
  325.         _tprintf(TEXT("OpenSCManager failed - %sn"), GetLastErrorText(szErr,256));
  326. }
  327. //
  328. //  FUNCTION: CmdRemoveService()
  329. //
  330. //  PURPOSE: Stops and removes the service
  331. //
  332. //  PARAMETERS:
  333. //    none
  334. //
  335. //  RETURN VALUE:
  336. //    none
  337. //
  338. //  COMMENTS:
  339. //
  340. void CmdRemoveService()
  341. {
  342.     SC_HANDLE   schService;
  343.     SC_HANDLE   schSCManager;
  344.     schSCManager = OpenSCManager(
  345.                         NULL,                   // machine (NULL == local)
  346.                         NULL,                   // database (NULL == default)
  347.                         SC_MANAGER_ALL_ACCESS   // access required
  348.                         );
  349.     if ( schSCManager )
  350.     {
  351.         schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
  352.         if (schService)
  353.         {
  354.             // try to stop the service
  355.             if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
  356.             {
  357.                 _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
  358.                 Sleep( 1000 );
  359.                 while( QueryServiceStatus( schService, &ssStatus ) )
  360.                 {
  361.                     if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
  362.                     {
  363.                         _tprintf(TEXT("."));
  364.                         Sleep( 1000 );
  365.                     }
  366.                     else
  367.                         break;
  368.                 }
  369.                 if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
  370.                     _tprintf(TEXT("n%s stopped.n"), TEXT(SZSERVICEDISPLAYNAME) );
  371.                 else
  372.                     _tprintf(TEXT("n%s failed to stop.n"), TEXT(SZSERVICEDISPLAYNAME) );
  373.             }
  374.             // now remove the service
  375.             if( DeleteService(schService) )
  376.                 _tprintf(TEXT("%s removed.n"), TEXT(SZSERVICEDISPLAYNAME) );
  377.             else
  378.                 _tprintf(TEXT("DeleteService failed - %sn"), GetLastErrorText(szErr,256));
  379.             CloseServiceHandle(schService);
  380.         }
  381.         else
  382.             _tprintf(TEXT("OpenService failed - %sn"), GetLastErrorText(szErr,256));
  383.         CloseServiceHandle(schSCManager);
  384.     }
  385.     else
  386.         _tprintf(TEXT("OpenSCManager failed - %sn"), GetLastErrorText(szErr,256));
  387. }
  388. //
  389. //  FUNCTION: CmdRestartService()
  390. //
  391. //  PURPOSE: Stops and removes the service
  392. //
  393. //  PARAMETERS:
  394. //    none
  395. //
  396. //  RETURN VALUE:
  397. //    none
  398. //
  399. //  COMMENTS:
  400. //
  401. void CmdRestartService(char *szServiceName)
  402. {
  403.     SC_HANDLE   schService;
  404.     SC_HANDLE   schSCManager;
  405.     schSCManager = OpenSCManager(
  406.                         NULL,                   // machine (NULL == local)
  407.                         NULL,                   // database (NULL == default)
  408.                         SC_MANAGER_ALL_ACCESS   // access required
  409.                         );
  410.     if ( schSCManager )
  411.     {
  412.         schService = OpenService(schSCManager, TEXT(szServiceName), SERVICE_ALL_ACCESS);
  413.         if (schService)
  414.         {
  415.             if(! ControlService( schService, SERVICE_CONTROL_INTERROGATE, &ssStatus ) )
  416.             //if(QueryServiceStatus( schService, &ssStatus )==0)
  417.             {
  418.                 if(GetLastError()==ERROR_SERVICE_NOT_ACTIVE)
  419.                 {
  420.                    //AddToMessageLog(TEXT("Start service..."));
  421.                    StartService( schService, 0,NULL);
  422.                 }
  423.                 else
  424.                 {  ;
  425.                    //AddToMessageLog(TEXT("QueryService..."));
  426.                    //AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
  427.                 }
  428.             }
  429.             CloseServiceHandle(schService);
  430.         }
  431.         else
  432.         {    _tprintf(TEXT("OpenService failed - %sn"), GetLastErrorText(szErr,256));
  433.               AddToMessageLog(TEXT("OpenService..."));
  434.               AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
  435.         }
  436.         CloseServiceHandle(schSCManager);
  437.     }
  438.     else
  439.     {    _tprintf(TEXT("OpenSCManager failed - %sn"), GetLastErrorText(szErr,256));
  440.           AddToMessageLog(TEXT("OpenSCMManager.."));
  441.     }
  442. }
  443. ///////////////////////////////////////////////////////////////////
  444. //
  445. //  The following code is for running the service as a console app
  446. //
  447. //
  448. //  FUNCTION: CmdDebugService(int argc, char ** argv)
  449. //
  450. //  PURPOSE: Runs the service as a console application
  451. //
  452. //  PARAMETERS:
  453. //    argc - number of command line arguments
  454. //    argv - array of command line arguments
  455. //
  456. //  RETURN VALUE:
  457. //    none
  458. //
  459. //  COMMENTS:
  460. //
  461. void CmdDebugService(int argc, char ** argv)
  462. {
  463.     DWORD dwArgc;
  464.     LPTSTR *lpszArgv;
  465. #ifdef UNICODE
  466.     lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
  467. #else
  468.     dwArgc   = (DWORD) argc;
  469.     lpszArgv = argv;
  470. #endif
  471.     _tprintf(TEXT("Debugging %s.n"), TEXT(SZSERVICEDISPLAYNAME));
  472.     SetConsoleCtrlHandler( ControlHandler, TRUE );
  473.     ServiceStart( dwArgc, lpszArgv );
  474. }
  475. //
  476. //  FUNCTION: ControlHandler ( DWORD dwCtrlType )
  477. //
  478. //  PURPOSE: Handled console control events
  479. //
  480. //  PARAMETERS:
  481. //    dwCtrlType - type of control event
  482. //
  483. //  RETURN VALUE:
  484. //    True - handled
  485. //    False - unhandled
  486. //
  487. //  COMMENTS:
  488. //
  489. BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
  490. {
  491.     switch( dwCtrlType )
  492.     {
  493.         case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
  494.         case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
  495.             _tprintf(TEXT("Stopping %s.n"), TEXT(SZSERVICEDISPLAYNAME));
  496.             ServiceStop();
  497.             return TRUE;
  498.             break;
  499.     }
  500.     return FALSE;
  501. }
  502. //
  503. //  FUNCTION: GetLastErrorText
  504. //
  505. //  PURPOSE: copies error message text to string
  506. //
  507. //  PARAMETERS:
  508. //    lpszBuf - destination buffer
  509. //    dwSize - size of buffer
  510. //
  511. //  RETURN VALUE:
  512. //    destination buffer
  513. //
  514. //  COMMENTS:
  515. //
  516. LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
  517. {
  518.     DWORD dwRet;
  519.     LPTSTR lpszTemp = NULL;
  520.     dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
  521.                            NULL,
  522.                            GetLastError(),
  523.                            LANG_NEUTRAL,
  524.                            (LPTSTR)&lpszTemp,
  525.                            0,
  526.                            NULL );
  527.     // supplied buffer is not long enough
  528.     if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
  529.         lpszBuf[0] = TEXT('');
  530.     else
  531.     {
  532.         lpszTemp[lstrlen(lpszTemp)-2] = TEXT('');  //remove cr and newline character
  533.         _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
  534.     }
  535.     if ( lpszTemp )
  536.         LocalFree((HLOCAL) lpszTemp );
  537.     return lpszBuf;
  538. }
  539. //-------------------------------------------------
  540. // this event is signalled when the
  541. // service should end
  542. //-------------------------------------------------
  543. HANDLE  hServerStopEvent = NULL;
  544. //-------------------------------------------------
  545. //  FUNCTION: ServiceStart
  546. //
  547. //  PURPOSE: Actual code of the service
  548. //           that does the work.
  549. //-------------------------------------------------
  550. void ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
  551. {
  552.     DWORD  dwWait,dwTimeout=1000*60*1;
  553.     if (!ReportStatusToSCMgr(
  554.         SERVICE_START_PENDING, // service state
  555.         NO_ERROR,              // exit code
  556.         3000))                 // wait hint
  557.         goto cleanup;
  558.     // create the event object. The control handler function signals
  559.     // this event when it receives the "stop" control code.
  560.     //
  561.     hServerStopEvent = CreateEvent(
  562.         NULL,    // no security attributes
  563.         TRUE,    // manual reset event
  564.         FALSE,   // not-signalled
  565.         NULL);   // no name
  566.     if ( hServerStopEvent == NULL) goto cleanup;
  567.     // report the status to the service control manager.
  568.     //
  569.     if (!ReportStatusToSCMgr(
  570.         SERVICE_START_PENDING, // service state
  571.         NO_ERROR,              // exit code
  572.         3000))                 // wait hint
  573.         goto cleanup;
  574.     // report the status to the service control manager.
  575.     //
  576.     if (!ReportStatusToSCMgr(
  577.         SERVICE_START_PENDING, // service state
  578.         NO_ERROR,              // exit code
  579.         3000))                 // wait hint
  580.         goto cleanup;
  581.     // report the status to the service control manager.
  582.     //
  583.     if (!ReportStatusToSCMgr(
  584.         SERVICE_RUNNING,       // service state
  585.         NO_ERROR,              // exit code
  586.         0))                    // wait hint
  587.         goto cleanup;
  588.     //
  589.     // End of initialization
  590.     // Service is now running, perform work until shutdown
  591.     //
  592.     while ( 1 )
  593.     {
  594.         dwWait = WaitForSingleObject(  hServerStopEvent, dwTimeout);
  595.         if(dwWait==WAIT_FAILED)
  596.         {
  597.            AddToMessageLog(TEXT("Error in WaitForSingleObject"));
  598.            break;
  599.         }
  600.         else if(dwWait==WAIT_TIMEOUT)
  601.         {
  602.             CmdRestartService("MySql");
  603.         }
  604.         else
  605.         {   break;  //shutdown
  606.         }
  607.     }
  608.   cleanup:
  609.     if (hServerStopEvent)
  610.         CloseHandle(hServerStopEvent);
  611. }
  612. //-------------------------------------------------
  613. //  FUNCTION: ServiceStop
  614. //
  615. //  PURPOSE: Stops the service
  616. //-------------------------------------------------
  617. void ServiceStop()
  618. {
  619.     if ( hServerStopEvent )
  620.         SetEvent(hServerStopEvent);
  621. }
  622. //-the end ----------------------------------------