MemoryMappedFile使用小结

    对于Windows进程之间的数据交换,最简单的方式莫过于使用.NET4框架MemoryMappedFile,关于MemoryMappedFile,MSDN上面有很好的讲解和实例,参见:  http://msdn.microsoft.com/zh-cn/library/dd997372.aspx

    粗看了一下,似乎很简单,于是照猫画虎的搬进了自己的项目(包括一个服务程序(Widows Services)和一个服务监控程序(Winform),需要实现这两个进程间的数据交换),很快完成了编码,运行一下,服务程序运行OK,启动监控程序,异常发生:“Exception:无法访问的路径!”异常发生在监控程序MemoryMappedFile.CreateOrOpen(MEMORY_NAME, _memorySize, MemoryMappedFileAccess.ReadWrite)的时候;显然,系统认为监控程序无权打开由服务程序创建的内存映射文件,上网google,证实了我的猜测:Windows服务程序与一般的桌面应用程序运行在不同的安全上下文中。

    于是修改服务程序,加入调试代码:

MemoryMappedFile mmf = _shmManager.Mmf;
MemoryMappedFileSecurity mc
= mmf.GetAccessControl();
foreach (AccessRule<MemoryMappedFileRights> ar in
mc.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
_logger.Info(
"user:"+ ar.IdentityReference);
_logger.Info(
"right:"+ ar.Rights);
_logger.Info(
"type:"+ ar.AccessControlType);
}

    重新运行服务程序,查看日志输出信息: 

2011-03-1417:46:20,059 -- User: NT AUTHORITY\SYSTEM
2011-03-1417:46:20,059 -- Type: Allow
2011-03-1417:46:20,059 -- Rights: 983071
2011-03-1417:46:20,059 -- User: BUILTIN\Administrators
2011-03-1417:46:20,059 -- Type: Allow
2011-03-1417:46:20,059 -- Rights: CopyOnWrite, ReadExecute, ReadPermissions

    试验结果表明:默认情况下,由Windows服务进程创建的内存映射文件对NT AUTHORITY\SYSTEM账号赋予完全控制权限,而内置的管理员组有BUILTIN\Administrators有CopyOnWrite, ReadExecute, ReadPermissions的权限;而我的系统是用本地Administrator登录的,应该也属于BUILTIN\Administrators组,看来管理员组的这些权限还是不足以去CreateOrOpen(...)的,考虑到我的监控程序还需要写内存映射文件,需要更高的权限才行,于是修改服务程序,在创建内存映射文件时赋予Administrator完全控制的权限,以下是代码:

mmf = MemoryMappedFile.CreateOrOpen(MEMORY_NAME, _memorySize,
MemoryMappedFileAccess.ReadWrite);
bool exist= false;
string user = System.Net.Dns.GetHostName()+"\\Administrator";
AccessRule<MemoryMappedFileRights> rule = new AccessRule<MemoryMappedFileRights>(
user,
MemoryMappedFileRights.FullControl,
AccessControlType.Allow);

MemoryMappedFileSecurity msc = mmf.GetAccessControl();
foreach (AccessRule<MemoryMappedFileRights> ar in msc.GetAccessRules(true, true,
typeof(NTAccount)))
{
if(ar.IdentityReference == rule.IdentityReference &&
ar.AccessControlType == rule.AccessControlType &&
ar.Rights == rule.Rights)
{
exist= true;
break;
}
}
if(!exist)
{
msc.AddAccessRule(rule);
mmf.SetAccessControl(msc);
}

    再次编译,运行服务程序,正常,运行监控程序,正常, OK,问题解决~

posted @ 2011-05-14 01:16 北方的河 阅读(...) 评论(...) 编辑 收藏