通过内核对象在服务程序和桌面程序之间通信的小问题
来源:互联网 发布:经典翻拍知乎 编辑:程序博客网 时间:2024/06/05 01:51
转自:http://www.cppblog.com/lapcca/archive/2010/09/06/126024.html
关于在通过 事件对象 在服务程序和普通桌面应用程序相互之间通信的问题,分类情况进行讨论:
1、普通桌面应用程序中创建事件,服务程序中打开事件
XP的情况
普通桌面应用程序中创建:
- m_hEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT( "{67BDE5D7-C2FC-49f5-9096-C255AB791B75}" ));
服务程序中打开并置其为有信号:
- HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT( "{67BDE5D7-C2FC-49f5-9096-C255AB791B75}" ));
- DWORD dwErr = ::GetLastError();
- ::SetEvent(m_hEvent);
vista下情况
vista下有点问题是,如果像上面那样写的话,服务程序在打开该事件对象时报错“系统找不到指定的文件。”,原因是XP下服务程序和应用程序创建的内核对象的命名空间默认是全局的,而vista下则不是,服务创建的内核对象默认在session0下,而用户创建的内核对象默认在各自的session下(session1,session2……),解决此问题的方法很简单,就是在创建命名时间对象时指定名字是全局的,也就是将CreateEvent和OpenEvent的最后一个参数设置为TEXT("Global\\{67BDE5D7-C2FC-49f5-9096-C255AB791B75}")。
2、服务程序中创建事件,普通桌面应用程序中打开事件
下面就不分系统说明,只说说根本的问题。
服务程序中创建:
- m_hEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT( "{67BDE5D7-C2FC-49f5-9096-C255AB791B75}" ));
普通桌面应用程序中打开:
- HANDLE hEvent = ::OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT( "{67BDE5D7-C2FC-49f5-9096-C255AB791B75}" ));
- ::SetEvent(hEvent);
上面的代码不能正常工作,在普通桌面应用程序中打开事件对象时,报错“拒绝访问。”,并且获得的事件句柄是NULL,原因是这样的,在服务程序中创建的内核对象,默认情况下桌面程序无法打开这个对象,每个内核对象都是有访问控制的,而服务中创建的内核对象权限比较高,当LPSECURITY_ATTRIBUTES这个参数传NULL的时候,将使用默认访问控制。普通桌面应用程序自然没有权限访问了,解决方法如下,在服务程序创建事件对象时,指定确定的安全描述符。
- // set SECURITY_DESCRIPTOR
- SECURITY_DESCRIPTOR secutityDese;
- ::InitializeSecurityDescriptor(&secutityDese, SECURITY_DESCRIPTOR_REVISION);
- ::SetSecurityDescriptorDacl(&secutityDese,TRUE,NULL,FALSE);
- SECURITY_ATTRIBUTES securityAttr;
- // set SECURITY_ATTRIBUTES
- securityAttr.nLength = sizeof SECURITY_ATTRIBUTES;
- securityAttr.bInheritHandle = FALSE;
- securityAttr.lpSecurityDescriptor = &secutityDese;
- m_hEvent = ::CreateEvent(&securityAttr, FALSE, FALSE, TEXT( "{67BDE5D7-C2FC-49f5-9096-C255AB791B75}" ));
这样普通桌面应用程序再去打开该事件对象就没有问题了。(注:vista下事件对象的名字仍然要指定全局空间)
另外再谈谈Windows编程中的session,最近遇到一些很郁闷的问题。一直在折腾Vista下的服务程序启动进程的问题,有了点小小的体会,记下来,希望能帮到跟我遇到一样问题的朋友。Windows xp、Vista中,服务程序都是运行在session0中,而后面的第1、2、...、N个用户则分别运行在session1、session2、...、sessionN中。不同的session有不同的namespace,但是由于目前主流的用户windows平台WinXP支持快速用户切换,所以我们感觉不到这些差异。
在XP中,用Sevice启动的进程跟我们用当前用户启动的进程在编程上似乎没什么区别,用起来都一样。 可是到了vista下,情况就不一样了。vista新的安全机制对不同的session之间的限制做了加强。一些命名内核对象,如Event的使用,为了进行进程通信,在进程1(处在session1中)中,我创建了一个命名的事件对象,然后在进程2(由我的服务启动,所以运行在session0中)中检测该Event,发现始终检查不到,而且错误信息是“系统找不到指定的文件。”另外专门写了个小程序去检测(直接运行,也是运行在session1中),却能检测到。
后来仔细读了MSDN中关于“ Kernel Object Name Spaces”的资料,才明白:一些命名的内核对象,比如: events, semaphores, mutexes, waitable timers, file-mapping objects, job objects,都只是在自己的namespace里唯一存在,不同的session因为namespace不同,所以会导致上面的现象。详细的信息可以参考MSDN中的CreateEvent资料中对参数lpName的说明。
按照上面的方法应该可以解决通信问题,下面是我写的代码,可以实现通信
HANDLE hThread;
unsigned dwThreadID;
SECURITY_DESCRIPTOR secutityDese;
::InitializeSecurityDescriptor(&secutityDese, SECURITY_DESCRIPTOR_REVISION);
::SetSecurityDescriptorDacl(&secutityDese,TRUE,NULL,FALSE);
SECURITY_ATTRIBUTES securityAttr;
// set SECURITY_ATTRIBUTES
securityAttr.nLength = sizeof SECURITY_ATTRIBUTES;
//参数为true 的时候,才可以和应用程序通信,false 则不行
securityAttr.bInheritHandle = TRUE;
securityAttr.lpSecurityDescriptor = &secutityDese;
g_hMutex = CreateMutex(&securityAttr,TRUE,TEXT("Global\\CSAPP"));
hThread = (HANDLE)_beginthreadex( NULL, 0, &Read, NULL, 0, &dwThreadID);
while(m_bIsRunning)
{
WaitForSingleObject(g_Semaphore,INFINITE);
ReleaseMutex(g_hMutex);
}
CloseHandle(hThread);
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 通过内核对象在服务程序和桌面程序之间通信
- Delphi编写系统服务五:在系统服务和桌面程序之间共享内存
- Delphi编写系统服务五:在系统服务和桌面程序之间共享内存
- 如何解决vista和win7在windows服务中无法与桌面程序交互的问题?
- 通过程序在桌面添加快捷方式
- Linux下进程之间通过消息队列通信小程序示例
- 通过windows内核对象保证程序的单开
- 请问在两个程序之间如何通信?
- c# 通过程序来设置允许服务与桌面交互
- 桌面下雪小程序
- 服务程序与桌面的交互
- Windows服务与普通进程间通信(通过内核对象)
- 单片机和PC之间的串行通信程序
- 修改程序在桌面和开始的快捷图标
- 开发android的桌面小程序AppWidget
- win8开发(11)——共享目标示例
- Struts2_ValueStack,OGNL详解
- PLSQL Developer 9.0注册码
- win8开发(12)——如何选择并打开文件
- 操作系统内存映射
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 维基百科 - 条件注释
- zend studio 配置phpunit 和设置断点调试
- Android程序配置信息控制
- 一个贪吃蛇小游戏(17行代码)
- Servlet 学习笔记
- Xcode 4.2的编译改动
- ubuntu 编译内核
- myeclipse中project名字前有红色感叹号的解决办法