|
Как сделать NT Service?
|
|||
---|---|---|---|
#18+
Доброго Всем дня или вечера! Помогите пожал. сделать из этой проги NT Service. Я не имею опыта написания таких прогов. .............. #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #define DEFAULT_PORT 5001 #define DEFAULT_PROTO SOCK_STREAM // TCP void Usage(char *progname) { fprintf(stderr,"Usage\n%s -p [protocol] -e [endpoint] -i [interface]\n", progname); fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n"); fprintf(stderr,"\tendpoint is the port to listen on\n"); fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)"); fprintf(stderr," to bind to\n"); fprintf(stderr,"Defaults are TCP,5001 and INADDR_ANY\n"); WSACleanup(); exit(1); } int main(int argc, char **argv) { char Buffer[128]; char *interface= NULL; unsigned short port=DEFAULT_PORT; int retval; int fromlen; int i; int socket_type = DEFAULT_PROTO; struct sockaddr_in local, from; WSADATA wsaData; SOCKET listen_socket, msgsock; /* Parse arguments */ if (argc >1) { for(i=1;i <argc;i++) { if ( (argv [0] == '-') || (argv[0] == '/') ) { switch(tolower(argv)) { case 'p': if (!stricmp(argv[i+1], "TCP") ) socket_type = SOCK_STREAM; else if (!stricmp(argv[i+1], "UDP") ) socket_type = SOCK_DGRAM; else Usage(argv[0]); i++; break; case 'i': interface = argv[++i]; break; case 'e': port = atoi(argv[++i]); break; default: Usage(argv[0]); break; } } else Usage(argv[0]); } } if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) { fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError()); WSACleanup(); return -1; } if (port == 0){ Usage(argv[0]); } local.sin_family = AF_INET; local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface); /* * Port MUST be in Network Byte Order */ local.sin_port = htons(port); listen_socket = socket(AF_INET, socket_type,0); // TCP socket if (listen_socket == INVALID_SOCKET){ fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError()); WSACleanup(); return -1; } // // bind() associates a local address and port combination with the // socket just created. This is most useful when the application is a // server that has a well-known port that clients know about in advance. // if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) ) == SOCKET_ERROR) { fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError()); WSACleanup(); return -1; } // // So far, everything we did was applicable to TCP as well as UDP. // However, there are certain steps that do not work when the server is // using UDP. // // We cannot listen() on a UDP socket. if (socket_type != SOCK_DGRAM) { if (listen(listen_socket,5) == SOCKET_ERROR) { fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError()); WSACleanup(); return -1; } } printf("%s: 'Listening' on port %d, protocol %s\n",argv[0],port, (socket_type == SOCK_STREAM)?"TCP":"UDP"); while(1) { fromlen =sizeof(from); // // accept() doesn't make sense on UDP, since we do not listen() // if (socket_type != SOCK_DGRAM) { msgsock = accept(listen_socket,(struct sockaddr*)&from, &fromlen); if (msgsock == INVALID_SOCKET) { fprintf(stderr,"accept() error %d\n",WSAGetLastError()); WSACleanup(); return -1; } printf("accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port)) ; } else msgsock = listen_socket; // // In the case of SOCK_STREAM, the server can do recv() and // send() on the accepted socket and then close it. // However, for SOCK_DGRAM (UDP), the server will do // recvfrom() and sendto() in a loop. if (socket_type != SOCK_DGRAM) retval = recv(msgsock,Buffer,sizeof (Buffer),0 ); else { retval = recvfrom(msgsock,Buffer,sizeof (Buffer),0, (struct sockaddr *)&from,&fromlen); printf("Received datagram from %s\n",inet_ntoa(from.sin_addr)); } if (retval == SOCKET_ERROR) { fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError()); closesocket(msgsock); continue; } if (retval == 0) { printf("Client closed connection\n"); closesocket(msgsock); continue; } printf("Received %d bytes, data [%s] from client\n",retval,Buffer); printf("Echoing same data back to client\n"); if (socket_type != SOCK_DGRAM) retval = send(msgsock,Buffer,sizeof(Buffer),0); else retval = sendto(msgsock,Buffer,sizeof (Buffer),0, (struct sockaddr *)&from,fromlen); if (retval == SOCKET_ERROR) { fprintf(stderr,"send() failed: error %d\n",WSAGetLastError()); } if (socket_type != SOCK_DGRAM){ printf("Terminating connection\n"); closesocket(msgsock); } else printf("UDP server looping back for more requests\n"); continue; } } ... |
|||
:
Нравится:
Не нравится:
|
|||
28.10.2002, 23:29 |
|
Как сделать NT Service?
|
|||
---|---|---|---|
#18+
В примерах MSDN есть пример реализации сервиса. Ищите файлы Client.c, Service.c, Service.h, Simple.c ... |
|||
:
Нравится:
Не нравится:
|
|||
29.10.2002, 10:42 |
|
Как сделать NT Service?
|
|||
---|---|---|---|
#18+
Я попробовал вставить кусок программы в Simple.c, но программа не выполняется, иницилизируется pipe и стартует сервис. Вот пример, может здесь чегото не так? // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved. // // MODULE: simple.c // // PURPOSE: Implements the body of the service. // The default behavior is to open a // named pipe, \\.\pipe\simple, and read // from it. It the modifies the data and // writes it back to the pipe. // // FUNCTIONS: // ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv); // ServiceStop( ); // // COMMENTS: The functions implemented in simple.c are // prototyped in service.h // // // AUTHOR: Craig Link - Microsoft Developer Support // #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <process.h> #include <tchar.h> #include "service.h" //------------------------------------------ #define WIN32_LEAN_AND_MEAN //#include <stdio.h> //#include <stdlib.h> //#include <windows.h> //#include <tchar.h> #include <string.h> #include <winsock.h> #include <io.h> #include <direct.h> #include <time.h> #include <string.h> #include <sql.h> #include <sqlext.h> #include <odbcss.h> //------------------------------------------ #define MAX_CONNECTION_NUM 100 #define MAX_REC_LEN 512 #define DATE_LEN 7 #define IPADDR_LEN 16 #define PORT_LEN 7 #define VERSION_LEN 11 #define MAX_NAME_LEN 32 #define MAX_CHASSIS_NUM 100 #define MAX_FILE_NAME_LEN 128 #define MAX_PATH_LEN 256 #define MAX_ESQN_LEN 10 #define MAX_PASSWORD_LEN 16 #define MAX_CDR_NUM 10000 #define MAX_RESETNUM_LEN 11 // States of the CDR Server #define AVAIL -1 #define START 0 #define WELCOMED 1 #define CONNECTED 2 #define PASSWORDSENT 3 #define PASSWORDOK 4 #define GOTGWIP 5 #define GOTUNITNAME 6 #define GOTLASTSEQNO 7 #define READY 8 // // Structure definition // // The context key keeps track of how the I/O // is progressing for each individual file handle. struct ContextKey { SOCKET sock; // Input char InBuffer[MAX_REC_LEN]; OVERLAPPED ovIn; // Output int nCDRBuffIndex; int nOutBuffIndex; char CDRBuffer[MAX_REC_LEN]; char OutBuffer[MAX_REC_LEN]; OVERLAPPED ovOut; DWORD dwWritten; int sid; }; // // Global variables // struct ContextKey *pCntx[MAX_CONNECTION_NUM]; HANDLE ghFile; HANDLE ghCompletionPort[MAX_CONNECTION_NUM]; HANDLE hFile[MAX_CONNECTION_NUM]; OVERLAPPED overlap[MAX_CONNECTION_NUM]; char cdrfile_path[MAX_PATH_LEN]; char cdrpassword[MAX_PASSWORD_LEN]; char cdrport[PORT_LEN]; char cfgfile_path[MAX_PATH_LEN]; char version[VERSION_LEN]; int cid; //Current Connection Identifier int state[MAX_CONNECTION_NUM]; int maxchano = MAX_CHASSIS_NUM; int maxcdrno = MAX_CDR_NUM; short cdrserverport; typedef struct chassis { short avail; char IpAddr[IPADDR_LEN]; char unitname[MAX_NAME_LEN]; char resetnum[MAX_RESETNUM_LEN]; long resetno; long curr_resetno; } CHASSIS; CHASSIS cha[MAX_CHASSIS_NUM]; //----------------------------------------------------------------------- char cmd; char slog1[20]; char spwd1[20]; char sdsn1[20]; SQLHENV henv2 = SQL_NULL_HENV; SQLHDBC hdbc2 = SQL_NULL_HDBC; SQLHSTMT hstmt2 = SQL_NULL_HSTMT; RETCODE retcode; // SQLBindParameter variables. SQLINTEGER cbmu=SQL_NTS,cba1=SQL_NTS,cbb1=SQL_NTS,cbc1=SQL_NTS,cbd1=SQL_NTS,cbe1=SQL_NTS,cbf1=SQL_NTS, cbg1=SQL_NTS,cbh1=SQL_NTS,cbi1=SQL_NTS,cbj1=SQL_NTS,cbk1=SQL_NTS,cbl1=SQL_NTS,cbm1=SQL_NTS,cbn1=SQL_NTS, cbo1=SQL_NTS,cbp1=SQL_NTS,cbq1=SQL_NTS,cbr1=SQL_NTS,cbs1=SQL_NTS,cbt1=SQL_NTS,cbu1=SQL_NTS, cbv1=SQL_NTS,cbw1=SQL_NTS,cbx1=SQL_NTS,cby1=SQL_NTS,cbz1=SQL_NTS,cbz11=SQL_NTS,cbz21=SQL_NTS; SQLINTEGER cbrecno=SQL_NTS,cbipadr=SQL_NTS; //SQLCHAR ipadr[16]; //SQLUINTEGER recno; SQLUINTEGER a11; SQLCHAR mu[5]; SQLCHAR a1[20]; SQLCHAR b1[20]; SQLCHAR c1[20]; SQLCHAR d1[20]; SQLCHAR e1[20]; SQLCHAR f1[20]; SQLCHAR g1[20]; SQLCHAR h1[20]; SQLCHAR i1[20]; SQLCHAR j1[20]; SQLCHAR k1[20]; SQLCHAR l1[20]; SQLCHAR m1[20]; SQLCHAR n1[20]; SQLCHAR o1[20]; SQLCHAR p1[20]; SQLCHAR q1[20]; SQLCHAR r1[20]; SQLCHAR s1[20]; SQLCHAR t1[20]; SQLCHAR u1[20]; SQLCHAR v1[20]; SQLCHAR w1[20]; SQLCHAR x1[20]; SQLCHAR y1[20]; SQLCHAR z1[20]; SQLCHAR z11[20]; SQLCHAR z21[20]; //----------------------------------------------------------------------- // this event is signalled when the // service should end // HANDLE hServerStopEvent = NULL; // // FUNCTION: ServiceStart // // PURPOSE: Actual code of the service // that does the work. // // PARAMETERS: // dwArgc - number of command line arguments // lpszArgv - array of command line arguments // // RETURN VALUE: // none // // COMMENTS: // The default behavior is to open a // named pipe, \\.\pipe\simple, and read // from it. It the modifies the data and // writes it back to the pipe. The service // stops when hServerStopEvent is signalled // VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) { HANDLE hPipe = INVALID_HANDLE_VALUE; HANDLE hEvents = {NULL, NULL}; OVERLAPPED os; PSECURITY_DESCRIPTOR pSD = NULL; SECURITY_ATTRIBUTES sa; TCHAR szIn[80]; TCHAR szOut[80]; LPTSTR lpszPipeName = TEXT("\\\\.\\pipe\\simple"); BOOL bRet; DWORD cbRead; DWORD cbWritten; DWORD dwWait; UINT ndx; //------------------------------------------------------ SOCKET listener; SOCKET AcceptSocket; WSADATA WsaData; struct sockaddr_in serverAddress; struct sockaddr_in clientAddress; int clientAddressLength; int err; int i = 0; struct ContextKey *pKey[MAX_CONNECTION_NUM]; char *curr_path; char ver[VERSION_LEN]; //------------------------------------------------------ /////////////////////////////////////////////////// // // Service initialization // // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; // create the event object. The control handler function signals // this event when it receives the "stop" control code. // hServerStopEvent = CreateEvent( NULL, // no security attributes TRUE, // manual reset event FALSE, // not-signalled NULL); // no name if ( hServerStopEvent == NULL) goto cleanup; hEvents[0] = hServerStopEvent; // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; // create the event object object use in overlapped i/o // hEvents = CreateEvent( NULL, // no security attributes TRUE, // manual reset event FALSE, // not-signalled NULL); // no name if ( hEvents == NULL) goto cleanup; // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; // create a security descriptor that allows anyone to write to // the pipe... // pSD = (PSECURITY_DESCRIPTOR) malloc( SECURITY_DESCRIPTOR_MIN_LENGTH ); if (pSD == NULL) goto cleanup; if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) goto cleanup; // add a NULL disc. ACL to the security descriptor. // if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)) goto cleanup; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = TRUE; // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; // allow user tp define pipe name for ( ndx = 1; ndx < dwArgc-1; ndx++ ) { if ( ( (*(lpszArgv[ndx]) == TEXT('-')) || (*(lpszArgv[ndx]) == TEXT('/')) ) && _tcsicmp( TEXT("pipe"), lpszArgv[ndx]+1 ) == 0 ) { lpszPipeName = lpszArgv[++ndx]; } } // open our named pipe... // hPipe = CreateNamedPipe( lpszPipeName , // name of pipe FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, // pipe open mode PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, // pipe IO type 1, // number of instances 0, // size of outbuf (0 == allocate as necessary) 0, // size of inbuf 1000, // default time-out value &sa); // security attributes if (hPipe == INVALID_HANDLE_VALUE) { AddToMessageLog(TEXT("Unable to create named pipe")); goto cleanup; } // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_RUNNING, // service state NO_ERROR, // exit code 0)) // wait hint goto cleanup; // // End of initialization // //////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // // Service is now running, perform work until shutdown // while ( 1 ) { // init the overlapped structure // memset( &os, 0, sizeof(OVERLAPPED) ); os.hEvent = hEvents; ResetEvent( hEvents ); // wait for a connection... // ConnectNamedPipe(hPipe, &os); if ( GetLastError() == ERROR_IO_PENDING ) { dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE ); if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred, // break; // or server stop signaled goto cleanup; } // init the overlapped structure // memset( &os, 0, sizeof(OVERLAPPED) ); os.hEvent = hEvents; ResetEvent( hEvents ); // grab whatever's coming through the pipe... // /* bRet = ReadFile( hPipe, // file to read from szIn, // address of input buffer sizeof(szIn), // number of bytes to read &cbRead, // number of bytes read &os); // overlapped stuff, not needed if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) ) { dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE ); if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred, break; // or server stop signaled } // munge the string // _stprintf(szOut, TEXT("Hello! [%s]"), szIn); // init the overlapped structure // memset( &os, 0, sizeof(OVERLAPPED) ); os.hEvent = hEvents; ResetEvent( hEvents ); // send it back out... // bRet = WriteFile( hPipe, // file to write to szOut, // address of output buffer sizeof(szOut), // number of bytes to write &cbWritten, // number of bytes written &os); // overlapped stuff, not needed */ // Initialize cdrip to 9002 as the default value // the cfg file path and cdr file path to the working directory path strcpy(version, "10.06.2002.V2"); strcpy(cdrport, "9002"); curr_path = _getcwd(NULL, MAX_PATH_LEN); strcpy(cfgfile_path, curr_path); // printf("cfgfile_path = %s, cdrfile_path = %s\n", cfgfile_path, cdrfile_path); free(curr_path); cdrserverport = atoi(cdrport); // convert cdr tcp ip port number into integer // fprintf(stdout, "TCP IP PORT = %d\n", cdrserverport); // // Now we are ready to open the cdrserver.cfg file to get the cdr password, // the maximum number of gateways that it will collect CDRs from, // the maximum records that each cdr file can contain. ghFile = CreateFile( cfgfile_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if (ghFile == INVALID_HANDLE_VALUE) { // FatalError("Open Cdrserver Configuration File Failed\n"); goto cleanup; } else { GetConfigInfo(&(cdrpassword[0]), &maxchano, &maxcdrno, &(slog1[0]), &(spwd1[0]), &(sdsn1[0])); } //---------------------------------------------------------------- // Allocate the ODBC environment and save handle. retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv2); // Notify ODBC that this is an ODBC 3.0 app. retcode = SQLSetEnvAttr(henv2, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); // Allocate ODBC connection handle and connect. retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv2, &hdbc2); retcode = SQLConnect(hdbc2, sdsn1, SQL_NTS,slog1, SQL_NTS, spwd1, SQL_NTS); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) { //fprintf(stdout,"Connect failed ODBC connection RetCode = %d\n",retcode); //fprintf(stdout,"sdsn1 = %s slog1 = %s spwd1 = %s\n", sdsn1,slog1,spwd1); // return EXIT_FAILURE; goto cleanup; } //---------------------------------------------------------------- for (i=0; i < MAX_CHASSIS_NUM; i++) { strcpy(cha .IpAddr, "0.0.0.0\0"); strcpy(cha.unitname, "unit1\0"); strcpy(cha.resetnum, "-1\0"); cha.curr_resetno = -1; cha.resetno = -1; cha.avail = 1; } CheckOsVersion(); err = WSAStartup (0x0101, &WsaData); if (err == SOCKET_ERROR) { // FatalError("WSAStartup Failed"); // return EXIT_FAILURE; goto cleanup; } listener = socket(AF_INET, SOCK_STREAM, 0); if (listener < 0) { // FatalError("socket() failed"); // return EXIT_FAILURE; goto cleanup; } // set socket option to so_keepalive memset(&serverAddress, 0, sizeof(serverAddress)); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(cdrserverport); err = bind(listener, (struct sockaddr *)&serverAddress, sizeof(serverAddress) ); if (err < 0) { // FatalError("bind() failed"); goto cleanup; } else { int keepalivestat = 1; setsockopt(listener, IPPROTO_TCP, SO_KEEPALIVE, (char *)&keepalivestat, sizeof(int)); } // // Create a IO completion port for each incoming gateway connection // for (i = 0; i < MAX_CONNECTION_NUM; i++) { ghCompletionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, // No prior port 0, // No key 0 // Use default # of threads ); if (ghCompletionPort == NULL) // FatalError("CreateIoCompletionPort() failed"); goto cleanup; CreateWorkerThreads(i); state = AVAIL; } listen(listener, 10); // // Loop forever accepting requests new connections // and starting reading from them. // cid = -1; for (;;) { clientAddressLength = sizeof(clientAddress); AcceptSocket = accept(listener, (struct sockaddr *)&clientAddress, &clientAddressLength); if (AcceptSocket < 0) { // FatalError("accept() Failed"); // return EXIT_FAILURE; goto cleanup; } for (i=0; i < MAX_CONNECTION_NUM; i++) { if (state == AVAIL) { cid = i; // printf("AVAIL CONN ID = %d\n", cid); break; } } if (cid == -1) // FatalError("NO AVAILABLE TCP/IP Connections"); goto cleanup; pKey[cid] = calloc(1, sizeof(struct ContextKey)); pKey[cid]->sock = AcceptSocket; pKey[cid]->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Set the event for writing so that packets // will not be sent to the completion port when // a write finishes. pKey[cid]->ovOut.hEvent = (HANDLE)((DWORD)pKey[cid]->ovOut.hEvent | 0x1); pKey[cid]->sid = cid; // Associate the socket with the completion port CreateIoCompletionPort( (HANDLE)AcceptSocket, ghCompletionPort[cid], (DWORD)pKey[cid], // No key 0 // Use default # of threads ); // Kick off the first read state[cid] = START; if (IssueRead(pKey[cid]) < 0) { free(pKey[cid]); state[cid] = AVAIL; // fprintf(stderr, "CONNID = %d, IssueRead Failed\n", cid); } } //------------------------------------------------------------------------------------ /* // if ( !bRet && ( GetLastError() == ERROR_IO_PENDING ) ) if ( GetLastError() == ERROR_IO_PENDING ) { dwWait = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE ); if ( dwWait != WAIT_OBJECT_0+1 ) // not overlapped i/o event - error occurred, break; // or server stop signaled } // drop the connection... // */ DisconnectNamedPipe(hPipe); } cleanup: /* Clean up. */ SQLFreeHandle(SQL_HANDLE_STMT, hstmt2); SQLDisconnect(hdbc2); SQLFreeHandle(SQL_HANDLE_DBC, hdbc2); SQLFreeHandle(SQL_HANDLE_ENV, henv2); if (hPipe != INVALID_HANDLE_VALUE ) CloseHandle(hPipe); if (hServerStopEvent) CloseHandle(hServerStopEvent); if (hEvents) // overlapped i/o event CloseHandle(hEvents); if ( pSD ) free( pSD ); } // // FUNCTION: ServiceStop // // PURPOSE: Stops the service // // PARAMETERS: // none // // RETURN VALUE: // none // // COMMENTS: // If a ServiceStop procedure is going to // take longer than 3 seconds to execute, // it should spawn a thread to execute the // stop code, and return. Otherwise, the // ServiceControlManager will believe that // the service has stopped responding. // VOID ServiceStop() { if ( hServerStopEvent ) SetEvent(hServerStopEvent); } //--------------------------------------------------------------------------------------------- ... |
|||
:
Нравится:
Не нравится:
|
|||
29.10.2002, 15:36 |
|
Как сделать NT Service?
|
|||
---|---|---|---|
#18+
Пример из Platform SDK: /*--------------------------------------------------------------------------- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. MODULE: service.c PURPOSE: Implements functions required by all Windows NT services FUNCTIONS: main(int argc, char **argv); service_ctrl(DWORD dwCtrlCode); service_main(DWORD dwArgc, LPTSTR *lpszArgv); CmdInstallService(); CmdRemoveService(); CmdDebugService(int argc, char **argv); ControlHandler ( DWORD dwCtrlType ); GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); ---------------------------------------------------------------------------*/ #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <process.h> #include <tchar.h> #include "service.h" // internal variables SERVICE_STATUS ssStatus; // current status of the service SERVICE_STATUS_HANDLE sshStatusHandle; DWORD dwErr = 0; BOOL bDebug = FALSE; TCHAR szErr[256]; // internal function prototypes VOID WINAPI service_ctrl(DWORD dwCtrlCode); VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv); VOID CmdInstallService(); VOID CmdRemoveService(); VOID CmdDebugService(int argc, char **argv); BOOL WINAPI ControlHandler ( DWORD dwCtrlType ); LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); // // FUNCTION: main // // PURPOSE: entrypoint for service // // PARAMETERS: // argc - number of command line arguments // argv - array of command line arguments // // RETURN VALUE: // none // // COMMENTS: // main() either performs the command line task, or // call StartServiceCtrlDispatcher to register the // main service thread. When the this call returns, // the service has stopped, so exit. // void __cdecl main(int argc, char **argv) { SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; if ( (argc > 1) && ((*argv == '-') || (*argv == '/')) ) { if ( _stricmp( "install", argv+1 ) == 0 ) { CmdInstallService(); } else if ( _stricmp( "remove", argv+1 ) == 0 ) { CmdRemoveService(); } else if ( _stricmp( "debug", argv+1 ) == 0 ) { bDebug = TRUE; CmdDebugService(argc, argv); } else { goto dispatch; } exit(0); } // if it doesn't match any of the above parameters // the service control manager may be starting the service // so we must call StartServiceCtrlDispatcher dispatch: // this is just to be friendly printf( "%s -install to install the service\n", SZAPPNAME ); printf( "%s -remove to remove the service\n", SZAPPNAME ); printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME ); printf( "\nStartServiceCtrlDispatcher being called.\n" ); printf( "This may take several seconds. Please wait.\n" ); if (!StartServiceCtrlDispatcher(dispatchTable)) AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed.")); } // // FUNCTION: service_main // // PURPOSE: To perform actual initialization of the service // // PARAMETERS: // dwArgc - number of command line arguments // lpszArgv - array of command line arguments // // RETURN VALUE: // none // // COMMENTS: // This routine performs the service initialization and then calls // the user defined ServiceStart() routine to perform majority // of the work. // void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv) { // register our service control handler: // sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl); if (!sshStatusHandle) goto cleanup; // SERVICE_STATUS members that don't change in example // ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ssStatus.dwServiceSpecificExitCode = 0; // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; ServiceStart( dwArgc, lpszArgv ); cleanup: // try to report the stopped status to the service control manager. // if (sshStatusHandle) (VOID)ReportStatusToSCMgr( SERVICE_STOPPED, dwErr, 0); return; } // // FUNCTION: service_ctrl // // PURPOSE: This function is called by the SCM whenever // ControlService() is called on this service. // // PARAMETERS: // dwCtrlCode - type of control requested // // RETURN VALUE: // none // // COMMENTS: // VOID WINAPI service_ctrl(DWORD dwCtrlCode) { // Handle the requested control code. // switch (dwCtrlCode) { // Stop the service. // // SERVICE_STOP_PENDING should be reported before // setting the Stop Event - hServerStopEvent - in // ServiceStop(). This avoids a race condition // which may result in a 1053 - The Service did not respond... // error. case SERVICE_CONTROL_STOP: ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); ServiceStop(); return; // Update the service status. // case SERVICE_CONTROL_INTERROGATE: break; // invalid control code // default: break; } ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); } // // FUNCTION: ReportStatusToSCMgr() // // PURPOSE: Sets the current status of the service and // reports it to the Service Control Manager // // PARAMETERS: // dwCurrentState - the state of the service // dwWin32ExitCode - error code to report // dwWaitHint - worst case estimate to next checkpoint // // RETURN VALUE: // TRUE - success // FALSE - failure // // COMMENTS: // BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) { static DWORD dwCheckPoint = 1; BOOL fResult = TRUE; if ( !bDebug ) // when debugging we don't report to the SCM { if (dwCurrentState == SERVICE_START_PENDING) ssStatus.dwControlsAccepted = 0; else ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; ssStatus.dwCurrentState = dwCurrentState; ssStatus.dwWin32ExitCode = dwWin32ExitCode; ssStatus.dwWaitHint = dwWaitHint; if ( ( dwCurrentState == SERVICE_RUNNING ) || ( dwCurrentState == SERVICE_STOPPED ) ) ssStatus.dwCheckPoint = 0; else ssStatus.dwCheckPoint = dwCheckPoint++; // Report the status of the service to the service control manager. // if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) { AddToMessageLog(TEXT("SetServiceStatus")); } } return fResult; } // // FUNCTION: AddToMessageLog(LPTSTR lpszMsg) // // PURPOSE: Allows any thread to log an error message // // PARAMETERS: // lpszMsg - text for message // // RETURN VALUE: // none // // COMMENTS: // VOID AddToMessageLog(LPTSTR lpszMsg) { TCHAR szMsg[256]; HANDLE hEventSource; LPTSTR lpszStrings; if ( !bDebug ) { dwErr = GetLastError(); // Use event logging to log the error. // hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr); lpszStrings[0] = szMsg; lpszStrings = lpszMsg; if (hEventSource != NULL) { ReportEvent(hEventSource, // handle of event source EVENTLOG_ERROR_TYPE, // event type 0, // event category 0, // event ID NULL, // current user's SID 2, // strings in lpszStrings 0, // no bytes of raw data lpszStrings, // array of error strings NULL); // no raw data (VOID) DeregisterEventSource(hEventSource); } } } /////////////////////////////////////////////////////////////////// // // The following code handles service installation and removal // // // FUNCTION: CmdInstallService() // // PURPOSE: Installs the service // // PARAMETERS: // none // // RETURN VALUE: // none // // COMMENTS: // void CmdInstallService() { SC_HANDLE schService; SC_HANDLE schSCManager; TCHAR szPath[512]; if ( GetModuleFileName( NULL, szPath, 512 ) == 0 ) { _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256)); return; } schSCManager = OpenSCManager( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS // access required ); if ( schSCManager ) { schService = CreateService( schSCManager, // SCManager database TEXT(SZSERVICENAME), // name of service TEXT(SZSERVICEDISPLAYNAME), // name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // service's binary NULL, // no load ordering group NULL, // no tag identifier TEXT(SZDEPENDENCIES), // dependencies NULL, // LocalSystem account NULL); // no password if ( schService ) { _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); CloseServiceHandle(schService); } else { _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256)); } CloseServiceHandle(schSCManager); } else _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); } // // FUNCTION: CmdRemoveService() // // PURPOSE: Stops and removes the service // // PARAMETERS: // none // // RETURN VALUE: // none // // COMMENTS: // void CmdRemoveService() { SC_HANDLE schService; SC_HANDLE schSCManager; schSCManager = OpenSCManager( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS // access required ); if ( schSCManager ) { schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS); if (schService) { // try to stop the service if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) { _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME)); Sleep( 1000 ); while ( QueryServiceStatus( schService, &ssStatus ) ) { if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) { _tprintf(TEXT(".")); Sleep( 1000 ); } else break; } if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) ); else _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) ); } // now remove the service if ( DeleteService(schService) ) _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); else _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256)); CloseServiceHandle(schService); } else _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); CloseServiceHandle(schSCManager); } else _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); } /////////////////////////////////////////////////////////////////// // // The following code is for running the service as a console app // // // FUNCTION: CmdDebugService(int argc, char ** argv) // // PURPOSE: Runs the service as a console application // // PARAMETERS: // argc - number of command line arguments // argv - array of command line arguments // // RETURN VALUE: // none // // COMMENTS: // void CmdDebugService(int argc, char ** argv) { DWORD dwArgc; LPTSTR *lpszArgv; #ifdef UNICODE lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) ); #else dwArgc = (DWORD) argc; lpszArgv = argv; #endif _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); SetConsoleCtrlHandler( ControlHandler, TRUE ); ServiceStart( dwArgc, lpszArgv ); #ifdef UNICODE // Must free memory allocated for arguments GlobalFree(lpszArgv); #endif // UNICODE } // // FUNCTION: ControlHandler ( DWORD dwCtrlType ) // // PURPOSE: Handled console control events // // PARAMETERS: // dwCtrlType - type of control event // // RETURN VALUE: // True - handled // False - unhandled // // COMMENTS: // BOOL WINAPI ControlHandler ( DWORD dwCtrlType ) { switch ( dwCtrlType ) { case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); ServiceStop(); return TRUE; break; } return FALSE; } // // FUNCTION: GetLastErrorText // // PURPOSE: copies error message text to string // // PARAMETERS: // lpszBuf - destination buffer // dwSize - size of buffer // // RETURN VALUE: // destination buffer // // COMMENTS: // LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ) { DWORD dwRet; LPTSTR lpszTemp = NULL; dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&lpszTemp, 0, NULL ); // supplied buffer is not long enough if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) lpszBuf[0] = TEXT('\0'); else { lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() ); } if ( lpszTemp ) LocalFree((HLOCAL) lpszTemp ); return lpszBuf; } ... |
|||
:
Нравится:
Не нравится:
|
|||
30.10.2002, 17:22 |
|
|
start [/forum/topic.php?fid=57&msg=32062781&tid=2036522]: |
0ms |
get settings: |
18ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
217ms |
get topic data: |
5ms |
get forum data: |
1ms |
get page messages: |
190ms |
get tp. blocked users: |
1ms |
others: | 142ms |
total: | 581ms |
0 / 0 |