解决方案 »

  1.   

    能打开呵!贴内容:
    Example: A Service "Wrapper"Program 13-2 carries out the serverSK conversion discussed previously. The conversion to a service depends on carrying out all the tasks described earlier. The existing server code, with some very minor modifications, is placed in a function, ServiceSpecific. Therefore, the code shown here is essentially a wrapper around an existing server program whose entry point has been changed from main to ServiceSpecific.Another addition, not shown here but included on the book's Web site, is the use of a log file because services frequently run "headless" without an interactive console. When a log file is specified on the command to ServiceMain, significant events will be logged to that file.
    Program 13-2. SimpleService: A Service Wrapper/* Chapter 13. serviceSK.c
       serverSK modified to be a Windows service.
       This is, however, a general-purpose wrapper. */#include "EvryThng.h"
    #include "ClntSrvr.h"
    #define UPDATE_TIME 1000 /* One second between updates. */VOID LogEvent (LPCTSTR, DWORD, BOOL);
    void WINAPI ServiceMain (DWORD argc, LPTSTR argv []);
    VOID WINAPI ServerCtrlHandlerEx(DWORD, DWORD, LPVOID, LPVOID);
    void UpdateStatus (int, int); /* Calls SetServiceStatus. */
    int ServiceSpecific (int, LPTSTR *); /* Former main program. */
    volatile static BOOL ShutDown = FALSE, PauseFlag = FALSE;
    static SERVICE_STATUS hServStatus;
    static SERVICE_STATUS_HANDLE hSStat; /* Handle to set status. */static LPTSTR ServiceName = _T ("SocketCommandLineService");
    static LPTSTR LogFileName = _T ("CommandLineServiceLog.txt");/* Main routine that starts the service control dispatcher. */
    VOID _tmain (int argc, LPTSTR argv [])
    {
       SERVICE_TABLE_ENTRY DispatchTable [] =
       {
          { ServiceName, ServiceMain },
          { NULL, NULL }
       };   StartServiceCtrlDispatcher (DispatchTable);
       return 0;
    }/* ServiceMain entry point, called when the service is created. */
    void WINAPI ServiceMain (DWORD argc, LPTSTR argv [])
    {
       DWORD i, Context = 1;
       /* Set the current directory and open a log file, appending to
          an existing file. */   /* Set all server status data members. */
       hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       hServStatus.dwCurrentState = SERVICE_START_PENDING;
       hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
              SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
       hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIF0C_ERROR;
       hServStatus.dwServiceSpecificExitCode = 0;
       hServStatus.dwCheckPoint = 0;
       hServStatus.dwWaitHint = 2 * CS_TIMEOUT;   hSStat = RegisterServiceCtrlHandlerEx (ServiceName,
          ServerCtrlHandler, &Context);
       SetServiceStatus (hSStat, &hServStatus);   /* Start service-specific work; generic work is complete. */
       if (ServiceSpecific (argc, argv) != 0) {
          hServStatus.dwCurrentState = SERVICE_STOPPED;
          hServStatus.dwServiceSpecificExitCode = 1;
                 /* Server initialization failed. */
          SetServiceStatus (hSStat, &hServStatus);
          return;
       }
       /* We will only return here when the ServiceSpecific function
          completes, indicating system shutdown. */
       UpdateStatus (SERVICE_STOPPED, 0);
       return;
    }void UpdateStatus (int NewStatus, int Check)
    /* Set a new service status and checkpoint --
       either specific value or increment. */
    {
       if (Check < 0) hServStatus.dwCheckPoint++;
       else hServStatus.dwCheckPoint = Check;
       if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
       SetServiceStatus (hSStat, &hServStatus);
       return;
    }/* Control handler function, invoked by the SCM to run */
    /* in the same thread as the main program. */
    /* The last three parameters are not used, and the pre-NT5 */
    /* handlers would also work in this example. */
    VOID WINAPI ServerCtrlHandlerEx (DWORD Control, DWORD EventType,
             LPVOID lpEventData, LPVOID lpContext)
    {
       switch (Control) {
          case SERVICE_CONTROL_SHUTDOWN:
          case SERVICE_CONTROL_STOP:
             ShutDown = TRUE; /* Set the global shutdown flag. */
             UpdateStatus (SERVICE_STOP_PENDING, -1);
             break;
          case SERVICE_CONTROL_PAUSE:
             PauseFlag = TRUE; /* Interrogated periodically. */
             break;
          case SERVICE_CONTROL_CONTINUE:
             PauseFlag = FALSE;
             break;
          case SERVICE_CONTROL_INTERROGATE:
             break;
          default:
             if (Control > 127 && Control < 256) /* User defined. */
             break;
       }
       UpdateStatus (-1, -1); /* Increment checkpoint. */
       return;
    }/* This is the service-specific function, or "main," and is
       called from the more generic ServiceMain.
       In general, you can take any server, such as ServerNP.c, and
       rename "main" as "ServiceSpecific"; putting code right here.
       But some changes are required to update status. */int ServiceSpecific (int argc, LPTSTR argv [])
    {
       UpdateStatus (-1, -1); /* Increment the checkpoint. */
       /* ... Initialize system ... */
       /* Be sure to update the checkpoint periodically. */   return 0;
    }