• VC++使用服务做守护进程的示例(转载)


    转载:http://blog.csdn.net/zdy0_2004/article/details/40461571

    #define _WIN32_WINNT 0x502
    #define _CRT_SECURE_NO_WARNINGS
    #include <Windows.h>
    #include <Shlwapi.h>
    #include <WtsApi32.h>
    #include <UserEnv.h>
    #include <iostream>
    #include <fstream>
    #include <atlbase.h>
    
    static const char* const lpServiceName = "ProtectService";
    static SERVICE_STATUS_HANDLE hServiceStatus = NULL;
    static SERVICE_STATUS    ServiceStatus = {0};
    static char szCurDir[MAX_PATH+1] = {0};
    static bool bRun = false;
    static HANDLE hProcess = NULL;
    static FILE* fLog = NULL;
    static std::ofstream ofs_log;
    
    bool InstallService();
    VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);
    VOID WINAPI HandlerFunc(DWORD dwControl);
    HANDLE RunAsLoggedUser(const char* lpPath,char* lpCmdLine);
    void WorkFunc();
    
    int main(int argc, char **argv)
    {
        GetModuleFileName(NULL,szCurDir,MAX_PATH);
        *strrchr(szCurDir,'\') = '';
    
        char szLogPath[MAX_PATH+1];
        sprintf(szLogPath,"%s\Service.log",szCurDir);
        fLog = fopen(szLogPath,"a+");
        setvbuf(fLog,NULL,_IONBF,1024);
    
        ofs_log.open(szLogPath,std::ios::app);
    
        SERVICE_TABLE_ENTRY ServiceTable[2];
        char szBuffer[30];
        strcpy(szBuffer,lpServiceName);
        ServiceTable[0].lpServiceName = szBuffer;
        ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    
        ServiceTable[1].lpServiceName = NULL;
        ServiceTable[1].lpServiceProc = NULL;
    
        // 启动服务的控制分派机线程
        if (!StartServiceCtrlDispatcher(ServiceTable))
        {
            ofs_log<<"程序不是以服务方式启动"<<std::endl;
            std::cout<<"程序不是以服务方式启动,要创建服务并启动吗?y/n:";
            if (getchar() == 'y')
            {
                // 安装服务
                if (!InstallService())
                {
                    ofs_log<<"安装服务失败"<<std::endl;
                    std::cout<<"安装服务失败,具体原因请查看日志"<<std::endl;
                    return 1;
                }
                ofs_log<<"安装服务成功"<<std::endl;
            }
            
        }
        return 0;
    }
    
    bool InstallService()
    {
        SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if (!hSCManager)
        {
            ofs_log<<"OpenSCManager失败,错误码为:"<<GetLastError()<<std::endl;
            return false;
        }
    
        SC_HANDLE hService = OpenService(hSCManager,lpServiceName,SERVICE_QUERY_CONFIG);
        if (hService)
        {
            ofs_log<<"服务已经存在"<<std::endl;
            CloseServiceHandle(hSCManager);
            CloseServiceHandle(hService);
            return false;
        }
    
        char    szPath[MAX_PATH+1];
        GetModuleFileName(NULL,szPath,MAX_PATH);
        hService = CreateService(hSCManager,
            lpServiceName,
            lpServiceName,
            SERVICE_ALL_ACCESS,
            SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
            SERVICE_AUTO_START,
            SERVICE_ERROR_NORMAL,
            szPath,
            NULL,
            NULL,
            NULL,
            NULL,
            NULL);
        if (!hService)
        {
            ofs_log<<"CreateService失败,错误码为"<<GetLastError()<<std::endl;
            CloseServiceHandle(hSCManager);
            return false;
        }
    
        if (!StartService(hService,0,NULL))
        {
            ofs_log<<"服务安装成功,但是启动服务失败,错误码为:"<<GetLastError()<<std::endl;
            CloseServiceHandle(hService);
            CloseServiceHandle(hSCManager);
            return false;
        }
    
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCManager);
    
        return true;
    }
    
    VOID WINAPI ServiceMain( DWORD dwArgc,LPTSTR *lpszArgv )
    {
        ServiceStatus.dwServiceType = SERVICE_WIN32;
        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
        hServiceStatus = RegisterServiceCtrlHandler(lpServiceName,HandlerFunc);
        if (!hServiceStatus)
        {
            ofs_log<<"RegisterServiceCtrlHandler失败,错误码为:"<<GetLastError()<<std::endl;
            return;
        }
        if (!SetServiceStatus(hServiceStatus,&ServiceStatus))
        {
            ofs_log<<"SetServiceStatus失败,错误码为:"<<GetLastError()<<std::endl;
            return;
        }
    
        bRun = true;
        WorkFunc();
    }
    
    VOID WINAPI HandlerFunc( DWORD dwControl )
    {
        ofs_log<<"收到服务消息:"<<dwControl<<std::endl;
    
        if (dwControl == SERVICE_CONTROL_STOP || dwControl == SERVICE_CONTROL_SHUTDOWN)
        {
            // 停止服务
            ofs_log<<"服务停止"<<std::endl;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            bRun = false;
            if (hProcess)
            {
                TerminateProcess(hProcess,0);
            }
        }
    
        SetServiceStatus(hServiceStatus,&ServiceStatus);
    }
    
    HANDLE RunAsCreator(const char* lpPath, char* lpCmdLine)
    {
        if (!PathFileExists(lpPath))
        {
            ofs_log<<"指定的要启动的程序不存在"<<std::endl;
            return NULL;
        }
    
        char szSubProcCurDir[MAX_PATH];
        strcpy(szSubProcCurDir,lpPath);
        *strrchr(szSubProcCurDir,'\') = '';
    
        STARTUPINFO si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(si);
    
        if (!CreateProcess(lpPath,lpCmdLine,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,NULL,szSubProcCurDir,&si,&pi))
        {
            ofs_log<<"CreateProcess失败,错误码为:"<<GetLastError()<<std::endl;
            return NULL;
        }
    
        if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
        {
            CloseHandle(pi.hThread);
        }
    
        return pi.hProcess;
    }
    
    HANDLE RunAsLoggedUser( const char* lpPath,char* lpCmdLine )
    {
        if (!PathFileExists(lpPath))
        {
            ofs_log<<"指定的要启动的程序不存在"<<std::endl;
            return NULL;
        }
    
        DWORD dwSid = WTSGetActiveConsoleSessionId();
        ofs_log<<"当前登录用户ID为:"<<dwSid<<std::endl;
    
        HANDLE hExistingToken = NULL;
        if (!WTSQueryUserToken(dwSid,&hExistingToken))
        {
            ofs_log<<"WTSQueryUserToken失败,错误码为:"<<GetLastError()<<std::endl;
            return NULL;
        }
    
        HANDLE hNewToken = NULL;
        if (!DuplicateTokenEx(hExistingToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hNewToken))
        {
            ofs_log<<"DuplicateTokenEx失败,错误码为:"<<GetLastError()<<std::endl;
            CloseHandle(hExistingToken);
            return NULL;
        }
        CloseHandle(hExistingToken);
    
        LPVOID pEnv = NULL;
        DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
        if (CreateEnvironmentBlock(&pEnv,hNewToken,FALSE))
        {
            dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
        }
    
        STARTUPINFO si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(si);
        si.lpDesktop = "WinSta0\Default";
    
        char szSubProcCurDir[MAX_PATH+1];
        strcpy(szSubProcCurDir,lpPath);
        *strrchr(szSubProcCurDir,'\') = '';
    
        if (!CreateProcessAsUser(hNewToken,lpPath,lpCmdLine,NULL,NULL,FALSE,dwCreationFlags,pEnv,szSubProcCurDir,&si,&pi))
        {
            ofs_log<<"CreateProcessAsUser失败,错误码为:"<<GetLastError()<<std::endl;
            if (pEnv)
            {
                DestroyEnvironmentBlock(pEnv);
            }
            return NULL;
        }
    
        if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
        {
            CloseHandle(pi.hThread);
        }
    
        if (pEnv)
        {
            DestroyEnvironmentBlock(pEnv);
        }
    
        return pi.hProcess;
    }
    
    HANDLE RunAsSpecifiedUser(const char* lpUserName,const char* lpPassword,const char* lpPath,char* lpCmdLine)
    {
        if (!PathFileExists(lpPath))
        {
            ofs_log<<"指定的要启动的程序不存在"<<std::endl;
            return NULL;
        }
    
        HANDLE hExistingToken = NULL;
        if (!LogonUser(lpUserName,NULL,lpPassword,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hExistingToken))
        {
            ofs_log<<"LogonUser失败,错误码为:"<<GetLastError()<<std::endl;
            return NULL;
        }
    
        HANDLE hNewToken = NULL;
        if (!DuplicateTokenEx(hExistingToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hNewToken))
        {
            ofs_log<<"DuplicateTokenEx失败,错误码为:"<<GetLastError()<<std::endl;
            CloseHandle(hExistingToken);
            return NULL;
        }
        CloseHandle(hExistingToken);
    
        LPVOID pEnv = NULL;
        DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
        if (CreateEnvironmentBlock(&pEnv,hNewToken,FALSE))
        {
            dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
        }
    
        STARTUPINFO si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(si);
        //si.lpDesktop = "WinSta0\Default";
    
        char szSubProcCurDir[MAX_PATH+1];
        strcpy(szSubProcCurDir,lpPath);
        *strrchr(szSubProcCurDir,'\') = '';
    
        if (!CreateProcessAsUser(hNewToken,lpPath,lpCmdLine,NULL,NULL,FALSE,dwCreationFlags,pEnv,szSubProcCurDir,&si,&pi))
        {
            ofs_log<<"CreateProcessAsUser失败,错误码为:"<<GetLastError()<<std::endl;
            if (pEnv)
            {
                DestroyEnvironmentBlock(pEnv);
            }
            return NULL;
        }
    
        if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
        {
            CloseHandle(pi.hThread);
        }
    
        if (pEnv)
        {
            DestroyEnvironmentBlock(pEnv);
        }
    
        return pi.hProcess;
    }
    
    void WorkFunc()
    {
        char szIniPath[MAX_PATH+1];
        sprintf(szIniPath,"%s\config.ini",szCurDir);
        if (!PathFileExists(szCurDir))
        {
            ofs_log<<"配置文件不存在"<<std::endl;
        }
    
        char szProgPath[MAX_PATH+1];
        GetPrivateProfileString("PROGRAM","PATH","",szProgPath,MAX_PATH,szIniPath);
        char szCmdLine[200];
        GetPrivateProfileString("PROGRAM","CMD","",szCmdLine,200,szIniPath);
        int method = GetPrivateProfileInt("USERINFO","METHOD",1,szIniPath);
        char szUserName[100];
        char szPassword[100];
        GetPrivateProfileString("USERINFO","UID","",szUserName,99,szIniPath);
        GetPrivateProfileString("USERINFO","PWD","",szPassword,99,szIniPath);
    
        while (bRun)
        {
            switch (method)
            {
            case 1:
                hProcess = RunAsCreator(szProgPath,szCmdLine);
                break;
            case 2:
                hProcess = RunAsLoggedUser(szProgPath,szCmdLine);
                break;
            case 3:
                hProcess = RunAsSpecifiedUser(szUserName,szPassword,szProgPath,szCmdLine);
                break;
            default:
                ofs_log<<"未知的启动方式:"<<method<<std::endl;
                return;
            }
    
            if (!hProcess)
            {
                ofs_log<<"创建进程失败失败"<<std::endl;
            }
            WaitForSingleObject(hProcess,INFINITE);
            CloseHandle(hProcess);
            hProcess = NULL;
            ofs_log<<"被守护进程退出"<<std::endl;
            Sleep(2000);
        }
    }

     守护进程Demo

  • 相关阅读:
    跟我学Windows Azure 一 创建Windows Azure试用账号
    Dynamic编程
    多线程下的资源同步访问
    避免在同一机器上同时运行同一应用程序的多个实例
    依赖注入与Service Locator
    MVP演化论
    应用MVP模式对遗留代码进行重构
    对遗留代码的解依赖技术
    单元测试之测试方法
    单元测试之Mock
  • 原文地址:https://www.cnblogs.com/chechen/p/7325444.html
Copyright © 2020-2023  润新知