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服务程序与一般的桌面应用程序运行在不同的安全上下文中。
于是修改服务程序,加入调试代码:
MemoryMappedFileSecurity mc = mmf.GetAccessControl();
foreach (AccessRule<MemoryMappedFileRights> ar in
{
_logger.Info("user:"+ ar.IdentityReference);
_logger.Info("right:"+ ar.Rights);
_logger.Info("type:"+ ar.AccessControlType);
}
重新运行服务程序,查看日志输出信息:
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完全控制的权限,以下是代码:
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,
{
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,问题解决~