基于数据共享进行通信的服务编程

6 篇文章 0 订阅

基于数据共享进行通信的服务编程

2009414日星期二

通常为了提高程序的运行权限,如在系统启动是进行启动运行,就需要用到服务,这里简单的给出基于Win32应用程序框架的服务(和控制台类似),详细不再介绍,见代码注释。

 

void Init();                             // 初始化函数

BOOL IsInstalled();                      // 判断服务是否已被装载

BOOL Install();                          // 装载服务

BOOL Uninstall();                        // 卸载服务

void LogEvent(LPCTSTR pszFormat,...);    // 打印日志

void WINAPI ServiceMain();               // 服务主函数

void WINAPI ServiceStrl(DWORD dwOpcode); // 处理服务事件函数

 

// Your function for your complement in the service.

BOOL Test(int i);

 

TCHAR szServiceName[] = _T("ServiceTest"); // 服务名

BOOL bInstall;                             // 服务是否被装载

SERVICE_STATUS_HANDLE hServiceStatus;      // 服务状态句柄

SERVICE_STATUS status;                     // 服务状态

DWORD dwThreadID;                          // 线程ID

 

// Win32应用程序入口函数

int APIENTRY WinMain(HINSTANCE hInstance,

                        HINSTANCE,

                        LPSTR lpCmdLine,

                        int nShowCmd)

{

     // 初始化

     Init();

 

     // 获取当前应用程序主线程ID

     dwThreadID = ::GetCurrentThreadId();

 

     SERVICE_TABLE_ENTRY st[] =

     {

         { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },

         { NULL, NULL }

     };

 

     // 比较判断命令行输入命令参数

     if (_stricmp(lpCmdLine,"/install") == 0)

     {

         Install();

     }

     else if (_stricmp(lpCmdLine, "/uninstall") == 0)

     {

         Uninstall();

     }

     else

     {

         // 将当前线程挂接到服务控制管理器

         if (!StartServiceCtrlDispatcher(st))

         {

              DWORD d = GetLastError();

              LogEvent(_T("Register Service Main Function Error!"));

         }

     }

 

     return 0;

}

 

// 初始化函数

void Init()

{

     // 初始化SERVICE_STATUS结构

     hServiceStatus = NULL;

     status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;

     status.dwCurrentState = SERVICE_STOPPED;

     status.dwControlsAccepted = SERVICE_ACCEPT_STOP;

     status.dwWin32ExitCode = 0;

     status.dwServiceSpecificExitCode = 0;

     status.dwCheckPoint = 0;

     status.dwWaitHint = 0;

}

 

// 服务主函数

void WINAPI ServiceMain()

{

     // 创建共享数据区

     CreateDataShare();

 

     // 设置参数为:启动等待

     status.dwCurrentState = SERVICE_START_PENDING;

     status.dwControlsAccepted = SERVICE_ACCEPT_STOP;

 

     // 注册服务处理函数

     hServiceStatus = RegisterServiceCtrlHandler(szServiceName,ServiceStrl);

     if (hServiceStatus == NULL)

     {

         LogEvent(_T("Handler not installed"));

         return;

     }

     // 将服务设置为参数指定的服务状态

     SetServiceStatus(hServiceStatus,&status);

 

     // 设置服务为运行状态

     status.dwWin32ExitCode = S_OK;

     status.dwCheckPoint = 0;

     status.dwWaitHint = 0;

     status.dwCurrentState = SERVICE_RUNNING;

     SetServiceStatus(hServiceStatus,&status);

 

     // 向前台窗口发服务启动消息

     WriteData(Service_Start);

 

     // Add your code here./

     int i = 0;

     while (1)

     {

         if (Test(i))

              break;

         else

              Sleep(1000);

         i++;

     }

    

 

     // 向前台窗口发服务停止消息

     WriteData(Service_End);

 

     // 将服务设置为停止状态

     status.dwCurrentState = SERVICE_STOPPED;

     SetServiceStatus(hServiceStatus,&status);

     LogEvent(_T("YS:Service stopped"));

 

     // 删除共享数据区

     DeleteDataShare();

}

 

// 服务处理函数

void WINAPI ServiceStrl(DWORD dwOpcode)

{

     // 根据服务控制码,进行状态设置

     switch (dwOpcode)

     {

     case SERVICE_CONTROL_STOP:

         status.dwCurrentState = SERVICE_STOP_PENDING;

         SetServiceStatus(hServiceStatus,&status);

         PostThreadMessage(dwThreadID,WM_CLOSE,0,0);

         break;

 

     case SERVICE_CONTROL_PAUSE:

         break;

 

     case SERVICE_CONTROL_CONTINUE:

         break;

 

     case SERVICE_CONTROL_INTERROGATE:

         break;

 

     case SERVICE_CONTROL_SHUTDOWN:

         break;

 

     default:

         LogEvent(_T("Bad service request"));

     }

}

 

// 判断服务是否已被装载

BOOL IsInstalled()

{

     BOOL bResult = FALSE;

 

     // 打开服务控制管理器

     SC_HANDLE hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

     if (hSCM != NULL)

     {

         // 打开服务

         SC_HANDLE hService = OpenService(hSCM,szServiceName,SERVICE_QUERY_CONFIG);

         if (hService != NULL)

         {

              bResult = TRUE;

              // 关闭服务句柄

              CloseServiceHandle(hService);

         }

         // 关闭服务控制管理器句柄

         CloseServiceHandle(hSCM);

     }

 

     return bResult;

}

 

// 装载服务

BOOL Install()

{

     // 如果已安装,则返回

     if (IsInstalled()) return TRUE;

 

     // 打开服务控制管理器

     SC_HANDLE hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

     if (hSCM == NULL)

     {

         MessageBox(NULL,_T("Couldn't open service manager"), szServiceName, MB_OK);

         return FALSE;

     }

 

     // 获取当前执行的.exe的全路径

     TCHAR szFilePath[MAX_PATH];

     GetModuleFileName(NULL,szFilePath,MAX_PATH);

 

     // 创建服务

     SC_HANDLE hService = CreateService(hSCM,szServiceName,szServiceName,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,

         SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,szFilePath, NULL, NULL, _T(""), NULL, NULL);

 

     if (hService == NULL)

     {

         CloseServiceHandle(hSCM);

         MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);

         return FALSE;

     }

 

     CloseServiceHandle(hService);

     CloseServiceHandle(hSCM);

 

     return TRUE;

}

 

// 卸载服务

BOOL Uninstall()

{

     if (!IsInstalled()) return TRUE;

 

     // 打开服务控制管理器

     SC_HANDLE hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

     if (hSCM == NULL)

     {

         MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);

        return FALSE;

     }

 

     // 打开服务

     SC_HANDLE hService = OpenService(hSCM,szServiceName,SERVICE_STOP | DELETE);

     if (hService == NULL)

     {

         CloseServiceHandle(hService);

         MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);

        return FALSE;

     }

 

     // 将服务控制码发送给系统

     ControlService(hService,SERVICE_CONTROL_STOP,&status);

 

     // 删除服务

     BOOL bDelete = DeleteService(hService);

     CloseServiceHandle(hService);

     CloseServiceHandle(hSCM);

 

     if (bDelete) return TRUE;

 

     LogEvent(_T("Service could not be deleted"));

 

     return FALSE;

}

 

// 打印日志函数

void LogEvent(LPCTSTR pFormat,...)

{

     TCHAR chMsg[256];

     HANDLE hEventSource;

     LPTSTR lpszStrings[1];

     va_list pArg; // #include <stdarg.h>

 

     // 实现函数可变参数

     va_start(pArg, pFormat);

     _vstprintf_s(chMsg, 256, pFormat, pArg);

     va_end(pArg);

 

     lpszStrings[0] = chMsg;

     // 返回注册事件日志句柄

     hEventSource = RegisterEventSource(NULL,szServiceName);

 

     if (hEventSource != NULL)

     {

         // 打印事件日志

         ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);

         // 注销事件日志句柄

         DeregisterEventSource(hEventSource);

     }

}

服务通常是无操作界面的,因此需要和前台应用程序进行结合使用,那么就涉及到进程间通信的问题了。这里我使用共享内存的方法(即内存映射),但由于在服务里默认创建的内存映射权限较高,应用程序无法访问,因此需要手动指定服务里的内存映射的权限。下面给出详细代码:

// 设置安全访问控制

void init_sec_attr(SECURITY_ATTRIBUTES &sa)

{

     DWORD dwRes;

     PSID pEveryoneSID = NULL, pAdminSID = NULL;

     PACL pACL = NULL;

     PSECURITY_DESCRIPTOR pSD = NULL;

     EXPLICIT_ACCESS ea[2];

     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;

     SID_IDENTIFIER_AUTHORITY SIDAuthNT    = SECURITY_NT_AUTHORITY;       

 

     // Create a well-known SID for the Everyone group.

     if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,

         SECURITY_WORLD_RID,

         0, 0, 0, 0, 0, 0, 0,

         &pEveryoneSID))

     {

         printf("AllocateAndInitializeSid Error %u/n", GetLastError());

 

     }

 

     // Initialize an EXPLICIT_ACCESS structure for an ACE.

     // The ACE will allow Everyone read access to the key.

     ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));

     ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL;

     ea[0].grfAccessMode = SET_ACCESS;

     ea[0].grfInheritance= NO_INHERITANCE;

     ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;

     ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;

     ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;

 

     // Create a SID for the BUILTIN/Administrators group.

     if(! AllocateAndInitializeSid(&SIDAuthNT, 2,

         SECURITY_BUILTIN_DOMAIN_RID,

         DOMAIN_ALIAS_RID_ADMINS,

         0, 0, 0, 0, 0, 0,

         &pAdminSID))

     {

         printf("AllocateAndInitializeSid Error %u/n", GetLastError());

 

     }

 

     // Initialize an EXPLICIT_ACCESS structure for an ACE.

     // The ACE will allow the Administrators group full access to

     // the key.

     ea[1].grfAccessPermissions = KEY_ALL_ACCESS;

     ea[1].grfAccessMode = SET_ACCESS;

     ea[1].grfInheritance= NO_INHERITANCE;

     ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;

     ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;

     ea[1].Trustee.ptstrName  = (LPTSTR) pAdminSID;

 

     // Create a new ACL that contains the new ACEs.

     dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);

     if (ERROR_SUCCESS != dwRes)

     {

         printf("SetEntriesInAcl Error %u/n", GetLastError());

 

     }

 

     // Initialize a security descriptor. 

     pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,

         SECURITY_DESCRIPTOR_MIN_LENGTH);

     if (NULL == pSD)

     {

         printf("LocalAlloc Error %u/n", GetLastError());

 

     }

 

     if (!InitializeSecurityDescriptor(pSD,

         SECURITY_DESCRIPTOR_REVISION))

     { 

         printf("InitializeSecurityDescriptor Error %u/n",

              GetLastError());

 

     }

 

     // Add the ACL to the security descriptor.

     if (!SetSecurityDescriptorDacl(pSD,

         TRUE,     // bDaclPresent flag  

         NULL,                  //pACL,

         FALSE))   // not a default DACL

     { 

         printf("SetSecurityDescriptorDacl Error %u/n",

              GetLastError());

     }

 

     sa.nLength = sizeof (SECURITY_ATTRIBUTES);

     sa.lpSecurityDescriptor = pSD;

     sa.bInheritHandle = FALSE;

}

 

// 创建共享数据区

BOOL CreateDataShare()

{

     // 打开文件映射

     hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,Data_Share);

     if (!hMap)

     {

         SECURITY_ATTRIBUTES sa;

         // 设置安全访问控制

         init_sec_attr(sa);

         // 创建文件映射

         hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0,MAX_PATH,Data_Share);

         if (!hMap) return FALSE;

     }

 

     // 映射对象的一个视图,得到指向共享内存的指针

     pBuffer = ::MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);

     if (!pBuffer) return FALSE;

 

     return TRUE;

}

 

// 删除共享数据区

void DeleteDataShare()

{

     // 解除文件映射

     ::UnmapViewOfFile(pBuffer);

 

     // 关闭内存映射文件对象句柄

     ::CloseHandle(hMap);

}

 

// 在共享数据区写入要发送的消息

void WriteData(LPCSTR lpszMessage)

{

     memset(pBuffer,0,MAX_PATH);

     memcpy(pBuffer,lpszMessage,strlen(lpszMessage));

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值