win32 - service的创建

参考这篇教程:Simple Windows Service in C

安装service需要在管理员权限下运行cmd,并输入下面的命令行

C:\>sc create "My Sample Service" binPath= C:\SampleService.exe

My Sample Service是service name,可以随意更改。 后面的exe程序是我们需要执行的service,代码如下。

卸载service,输入,

C:\>sc delete "My Sample Service"

代码样例:

#include <Windows.h>#include <tchar.h>#include <wtsapi32.h>#pragma comment(lib,"Wtsapi32.lib")SERVICE_STATUS        g_ServiceStatus = { 0 };SERVICE_STATUS_HANDLE g_StatusHandle = NULL;HANDLE                g_ServiceStopEvent = INVALID_HANDLE_VALUE;HANDLE g_hChildStd_Rd = NULL;HANDLE g_hChildStd_Wr = NULL;VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);VOID WINAPI ServiceCtrlHandler(DWORD);DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);#define SERVICE_NAME  _T("My Sample Service")int _tmain(int argc, TCHAR* argv[]){    OutputDebugString(_T("My Sample Service: Main: Entry"));    SERVICE_TABLE_ENTRY ServiceTable[] =    {        {(LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},        {NULL, NULL}    };    if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)    {        OutputDebugString(_T("My Sample Service: Main: StartServiceCtrlDispatcher returned error"));        return GetLastError();    }    OutputDebugString(_T("My Sample Service: Main: Exit"));    return 0;}VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv){    HANDLE hThread;    DWORD Status = E_FAIL;    OutputDebugString(_T("My Sample Service: ServiceMain: Entry"));    g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);    if (g_StatusHandle == NULL)    {        OutputDebugString(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));        goto EXIT;    }    // Tell the service controller we are starting    ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;    g_ServiceStatus.dwControlsAccepted = 0;    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;    g_ServiceStatus.dwWin32ExitCode = 0;    g_ServiceStatus.dwServiceSpecificExitCode = 0;    g_ServiceStatus.dwCheckPoint = 0;    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)    {        OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));    }    /*     * Perform tasks neccesary to start the service here     */    OutputDebugString(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));    // Create stop event to wait on later.    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);    if (g_ServiceStopEvent == NULL)    {        OutputDebugString(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));        g_ServiceStatus.dwControlsAccepted = 0;        g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;        g_ServiceStatus.dwWin32ExitCode = GetLastError();        g_ServiceStatus.dwCheckPoint = 1;        if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)        {            OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));        }        goto EXIT;    }    // Tell the service controller we are started    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;    g_ServiceStatus.dwWin32ExitCode = 0;    g_ServiceStatus.dwCheckPoint = 0;    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)    {        OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));    }    // Start the thread that will perform the main task of the service    hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);    OutputDebugString(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));    // Wait until our worker thread exits effectively signaling that the service needs to stop    WaitForSingleObject(hThread, INFINITE);    OutputDebugString(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));    /*     * Perform any cleanup tasks     */    OutputDebugString(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));    CloseHandle(g_ServiceStopEvent);    g_ServiceStatus.dwControlsAccepted = 0;    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;    g_ServiceStatus.dwWin32ExitCode = 0;    g_ServiceStatus.dwCheckPoint = 3;    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)    {        OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));    }EXIT:    OutputDebugString(_T("My Sample Service: ServiceMain: Exit"));    return;}VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode){    OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Entry"));    switch (CtrlCode)    {    case SERVICE_CONTROL_STOP:        OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SERVICE_CONTROL_STOP Request"));        if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)            break;        /*         * Perform tasks neccesary to stop the service here         */        g_ServiceStatus.dwControlsAccepted = 0;        g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;        g_ServiceStatus.dwWin32ExitCode = 0;        g_ServiceStatus.dwCheckPoint = 4;        if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)        {            OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SetServiceStatus returned error"));        }        // This will signal the worker thread to start shutting down        SetEvent(g_ServiceStopEvent);        break;    default:        break;    }    OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Exit"));}DWORD WINAPI ServiceWorkerThread(LPVOID lpParam){    OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));    WCHAR station[] = L"Winsta0\\default";    SECURITY_ATTRIBUTES saAttr;    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);    saAttr.bInheritHandle = TRUE;    saAttr.lpSecurityDescriptor = NULL;    CreatePipe(&g_hChildStd_Rd, &g_hChildStd_Wr, &saAttr, 0);    STARTUPINFO si;    ZeroMemory(&si, sizeof(STARTUPINFO));    si.cb = sizeof(STARTUPINFO);    si.hStdOutput = g_hChildStd_Wr;    si.hStdError = g_hChildStd_Wr;    si.lpDesktop = station;    si.dwFlags = STARTF_USESTDHANDLES;    PROCESS_INFORMATION pi;    HANDLE hToken;    bool err = WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &hToken);    WCHAR path[] = L"D:\\child.exe";    if (CreateProcessAsUser(hToken, path, NULL, 0, 0, true, CREATE_NO_WINDOW, 0, 0, &si, &pi))    {        CloseHandle(g_hChildStd_Wr);        DWORD ret = WaitForSingleObject(pi.hProcess, 2000); //wait for the child process exit.        if (ret == 0)        {            WCHAR chBuf[100]= L"HELLO WORLD";            DWORD dwRead, dwWritten,            err = ReadFile(g_hChildStd_Rd, chBuf, 100, &dwRead, NULL);            HANDLE hFile = CreateFile(L"123.txt",                // name of the write                GENERIC_WRITE,          // open for writing                0,                      // do not share                NULL,                   // default security                CREATE_NEW,             // create new file only                FILE_ATTRIBUTE_NORMAL,  // normal file                NULL);                  // no attr. template            WriteFile(                hFile,           // open file handle                chBuf,      // start of data to write                100,  // number of bytes to write                &dwWritten, // number of bytes that were written                NULL);            // no overlapped structure        }    }    //  Periodically check if the service has been requested to stop    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)    {        /*         * Perform main service function here         */                //  Simulate some work by sleeping        Sleep(3000);    }    OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));    return ERROR_SUCCESS;}

在Winsta0\default中创建子进程,在service中使用CreateProcessAsUser调用子进程。

文档参考:Window Stations

如果需要service与子进程建立通信,可以使用匿名管道,代码中已经创建了管道,我没有使用它们。

(0)

相关推荐