• win32


    参考这篇教程: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;
    }

    在Winsta0default中创建子进程,在service中使用CreateProcessAsUser调用子进程。

    文档参考:Window Stations

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

    如果对匿名管道的数据传输有兴趣的,可以参考我的另外一篇文章: win32 - 匿名管道的使用

  • 相关阅读:
    [NOIP2013] 提高组 洛谷P1979 华容道
    Vijos P1404 遭遇战
    CodeVS 1506 传话
    P1546 最短网络 Agri-Net
    HDU 4747 Mex
    POJ1020 Anniversary Cake
    【数据结构】平衡二叉树
    【数据结构】二叉排序树
    【数据结构】二叉树
    概念源于生活
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14276287.html
Copyright © 2020-2023  润新知