Creating a Multithreaded Service
来源:互联网 发布:日本行知学园熟官网 编辑:程序博客网 时间:2024/04/30 03:59
Creating a Multithreaded Service
The following sample code demonstrates how a simple service can spawn worker threads, respond to the SCM, notify the threads to exit, keep the SCM notified of the state and progress of the service, and report to the SCM that the service is stopped. To install the service, build it as a console application and use the SC utility included with the Platform SDK. Use the Service Control utility in the Control Panel to start and stop the service.
#include <windows.h>#include <tchar.h>#include <stdio.h>HANDLE hStopEvent;HANDLE hThreads[3] = {NULL,NULL,NULL};LPTSTR lpszServiceName;SERVICE_STATUS_HANDLE ssh;DWORD WINAPI ThreadProc(LPVOID lpParameter);void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);void WINAPI Service_Ctrl(DWORD dwCtrlCode);void ErrorStopService(LPTSTR lpszAPI);void SetTheServiceStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);// Entry point for service. Calls StartServiceCtrlDispatcher// and then blocks until the ServiceMain function returns.void _tmain(int argc, TCHAR *argv[]){ SERVICE_TABLE_ENTRY ste[] = {{TEXT(""),(LPSERVICE_MAIN_FUNCTION)Service_Main}, {NULL,NULL}}; OutputDebugString(TEXT("Entered service code/n")); if (!StartServiceCtrlDispatcher(ste)) { TCHAR error[256]; wsprintf(error, TEXT("Error code for StartServiceCtrlDispatcher: %u./n"), GetLastError()); OutputDebugString(error); } else OutputDebugString(TEXT("StartServiceCtrlDispatcher OK/n"));}// Called by the service control manager after the call to // StartServiceCtrlDispatcher.void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv){ DWORD ThreadId; DWORD t; DWORD dwWaitRes; // Obtain the name of the service. lpszServiceName = lpszArgv[0]; // Register the service ctrl handler. ssh = RegisterServiceCtrlHandler(lpszServiceName, (LPHANDLER_FUNCTION)Service_Ctrl); // Create the event to signal the service to stop. hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (hStopEvent == NULL) ErrorStopService(TEXT("CreateEvent")); // // Insert one-time work that you want to complete before starting. // for (t=0;t<3;t++) { hThreads[t] = CreateThread(NULL,0,ThreadProc, (LPVOID)t,0,&ThreadId); if (hThreads[t] == INVALID_HANDLE_VALUE) ErrorStopService(TEXT("CreateThread")); } // The service has started. SetTheServiceStatus(SERVICE_RUNNING, 0, 0, 0); OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_RUNNING/n")); // // Main loop for the service. // while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0) {/***************************************************************/ // Main loop for service./***************************************************************/ } // Wait for threads to exit. for (t=1;TRUE;t++) { if ((dwWaitRes = WaitForMultipleObjects(3,hThreads,TRUE,1000)) == WAIT_OBJECT_0) break; else if((dwWaitRes == WAIT_FAILED)||(dwWaitRes==WAIT_ABANDONED)) ErrorStopService(TEXT("WaitForMultipleObjects")); else SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000); } // Close the event handle and the thread handle. if (!CloseHandle(hStopEvent)) ErrorStopService(TEXT("CloseHandle")); if (!CloseHandle(hThreads[0])) ErrorStopService(TEXT("CloseHandle")); if (!CloseHandle(hThreads[1])) ErrorStopService(TEXT("CloseHandle")); if (!CloseHandle(hThreads[2])) ErrorStopService(TEXT("CloseHandle")); // Stop the service. OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_STOPPED/n")); SetTheServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);}// Handles control signals from the service control manager.void WINAPI Service_Ctrl(DWORD dwCtrlCode){ DWORD dwState = SERVICE_RUNNING; switch(dwCtrlCode) { case SERVICE_CONTROL_STOP: dwState = SERVICE_STOP_PENDING; break; case SERVICE_CONTROL_SHUTDOWN: dwState = SERVICE_STOP_PENDING; break; case SERVICE_CONTROL_INTERROGATE: break; default: break; } // Set the status of the service. SetTheServiceStatus(dwState, NO_ERROR, 0, 0); OutputDebugString( TEXT("SetTheServiceStatus, Service_Ctrl function/n")); // Tell service_main thread to stop. if ((dwCtrlCode == SERVICE_CONTROL_STOP) || (dwCtrlCode == SERVICE_CONTROL_SHUTDOWN)) { if (!SetEvent(hStopEvent)) ErrorStopService(TEXT("SetEvent")); else OutputDebugString(TEXT("Signal service_main thread/n")); }}// Thread procedure for all three worker threads.DWORD WINAPI ThreadProc(LPVOID lpParameter){ INT nThreadNum = (INT)lpParameter; TCHAR szOutput[25]; while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0) { // Just to have something to do, it will beep every second. Sleep(1000); wsprintf(szOutput,TEXT("/nThread %d says Beep/n"),nThreadNum); OutputDebugString(szOutput); //Send visual to debugger. } return 0;}// Wraps SetServiceStatus.void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint){ SERVICE_STATUS ss; // Current status of the service. // Disable control requests until the service is started. if (dwCurrentState == SERVICE_START_PENDING) ss.dwControlsAccepted = 0; else ss.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN; // Other flags include SERVICE_ACCEPT_PAUSE_CONTINUE // and SERVICE_ACCEPT_SHUTDOWN. // Initialize ss structure. ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwServiceSpecificExitCode = 0; ss.dwCurrentState = dwCurrentState; ss.dwWin32ExitCode = dwWin32ExitCode; ss.dwCheckPoint = dwCheckPoint; ss.dwWaitHint = dwWaitHint; // Send status of the service to the Service Controller. if (!SetServiceStatus(ssh, &ss)) ErrorStopService(TEXT("SetServiceStatus"));}// Handle API errors or other problems by ending the service and// displaying an error message to the debugger.void ErrorStopService(LPTSTR lpszAPI){ INT t; TCHAR buffer[256] = TEXT(""); TCHAR error[1024] = TEXT(""); LPVOID lpvMessageBuffer; DWORD dwWaitRes; wsprintf(buffer,TEXT("API = %s, "), lpszAPI); lstrcat(error, buffer); ZeroMemory(buffer, sizeof(buffer)); wsprintf(buffer,TEXT("error code = %d, "), GetLastError()); lstrcat(error, buffer); // Obtain the error string. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpvMessageBuffer, 0, NULL); ZeroMemory((LPVOID)buffer, (DWORD)sizeof(buffer)); wsprintf(buffer,TEXT("message = %s"), (TCHAR *)lpvMessageBuffer); lstrcat(error, buffer); // Free the buffer allocated by the system. LocalFree(lpvMessageBuffer); // Write the error string to the debugger. OutputDebugString(error); // If you have threads running, tell them to stop. Something went // wrong, and you need to stop them so you can inform the SCM. SetEvent(hStopEvent); // Wait for the threads to stop. for (t=1;TRUE;t++) { if ((dwWaitRes = WaitForMultipleObjects(3,hThreads,TRUE,1000)) == WAIT_OBJECT_0) break; else if ((dwWaitRes == WAIT_FAILED)|| (dwWaitRes == WAIT_ABANDONED)) break; // Our wait failed else { SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000); } } // Stop the service. SetTheServiceStatus(SERVICE_STOPPED, GetLastError(), 0, 0);}
- Creating a Multithreaded Service
- Creating a WCF Service
- Creating a .NET Web Service
- Lab 2: Creating a Service
- Android-Creating a Bound Service
- Creating a Simple Win32 Service in C++
- Creating a Web Service with JAX-RPC
- Creating a Simple Win32 Service in C++
- Creating a Windows Service using C#
- Running in a Background Service 之Creating a Background Service
- [From Network]Creating a Windows Service in C# (2)
- Walkthrough: Creating a Custom ASP.NET Web Service
- Android官网中关于Creating a Bound Service的介绍笔记
- Embedding Python inside a multithreaded C++ program
- 使用Restlet创建一个简单的web service(Creating a simple web service with Restlet)
- Creating a Scrollable DataGrid...
- Creating a Transparent Form
- Creating a Delete Button
- SERVICE_TABLE_ENTRY
- Writing a Service Program's main Function
- Writing a ServiceMain Function
- Writing a Control Handler Function
- 给中国学生的第四封信(李开复)--转载
- Creating a Multithreaded Service
- 乱码原理
- Handling Logoff Events
- 第八章configuring the database archiving mode
- C语言与Windows API编程!有无同路人?
- Opening an SCManager Database
- Installing a Service
- Deleting a Service
- Changing a Service Configuration