通过内核对象在服务程序和桌面程序之间通信的小问题
2012-12-05 11:47
399 查看
转自: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);
关于在通过 事件对象 在服务程序和普通桌面应用程序相互之间通信的问题,分类情况进行讨论:
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);
相关文章推荐
- 通过内核对象在服务程序和桌面程序之间通信的小问题 good
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 通过内核对象在服务程序和桌面程序之间通信的小问题
- 通过内核对象在服务程序和桌面程序之间通信
- Android Service与Activity之间通信:通过Binder对象、Broadcast广播
- 一个跟操作系统linux和windows差异有关的问题:通过soap的无wsdl实现php程序通信的程序(经典的吐血)
- Android手机通过Wifi与PC机之间进行通信问题 (有代码)
- 通过windows内核对象保证程序的单开
- Android Service与Activity之间通信的几种方式(1)-----通过Binder对象
- 操作系统与应用程序的关系 操作系统主要可以分为两大部分:内核和内核之外的一些程序。内核就是直接控制最底层的硬件,而我们日常所用到的软件,大都是通过内核之外一些程序与内核之间的接口完成的,例如WINDO
- 问题:无法通过Windows installer服务安装此安装程序包。您必须安装带有更新版本windows Installer服务的Windows。
- VS2010 ATL服务程序编写全攻略(二) - 内核对象访问
- android手机通过串口蓝牙透传模块与AVR单片机通信实例。。。蓝牙服务程序案例
- Windows内核对象 - 通过异步程序调用(APC)实现的定时功能
- 如何解决vista和win7在windows服务中无法与桌面程序交互的问题?
- Linux下进程之间通过消息队列通信小程序示例
- Delphi编写系统服务五:在系统服务和桌面程序之间共享内存
- Delphi编写系统服务五:在系统服务和桌面程序之间共享内存
- Android手机通过Wifi与PC机之间进行通信问题 (有代码)
- Android Service与Activity之间通信:通过Binder对象、Broadcast广播