Windows 服务在会话中独立运行0
,而您的控制台应用程序在用户会话中运行,因此为了使它们能够相互通信,必须在Global\
命名空间,以使其可供其他会话访问。例如
var file = MemoryMappedFile.CreateOrOpen(@"Global\MyMemoryMappedFile", ...
您还应该为该文件设置适当的权限,以确保所有用户都可以访问它。
我建议阅读这篇文章实现非持久内存映射文件,公开与 Windows 服务的 IPC 样式通信 http://web.archive.org/web/20180221131343/http://blogs.networkingfutures.co.uk/post/2015/12/28/Windows-Services-Implementing-Non-Persisted-Memory-Mapped-Files-Exposing-IPC-Style-Communications.aspx,它更详细地解释了上述内容,并提供了有关设置权限等的示例。
从上面链接的帖子复制的源代码:
互斥体、互斥体安全和 MMF 安全策略创建
bool mutexCreated;
Mutex mutex;
MutexSecurity mutexSecurity = new MutexSecurity();
MemoryMappedFileSecurity mmfSecurity = new MemoryMappedFileSecurity();
mutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
mmfSecurity.AddAccessRule(new AccessRule<MemoryMappedFileRights>("everyone", MemoryMappedFileRights.FullControl,
AccessControlType.Allow));
mutex = new Mutex(false, @"Global\MyMutex", out mutexCreated, mutexSecurity);
if (mutexCreated == false) log.DebugFormat("There has been an error creating the mutex");
else log.DebugFormat("mutex created successfully");
创建并写入 MMF
MemoryMappedFile file = MemoryMappedFile.CreateOrOpen(@"Global\MyMemoryMappedFile", 4096,
MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, mmfSecurity,
HandleInheritability.Inheritable);
using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor()) {
string xmlData = SerializeToXml(CurrentJobQueue) + "\0"; // \0 terminates the XML to stop badly formed
issues when the next string written is shorter than the current
byte[] buffer = ConvertStringToByteArray(xmlData);
mutex.WaitOne();
accessor.WriteArray<byte>(0, buffer, 0, buffer.Length);
mutex.ReleaseMutex();
}
从 MMF 读取
using (MemoryMappedFile file = MemoryMappedFile.OpenExisting(
@"Global\MyMemoryMappedFile", MemoryMappedFileRights.Read)) {
using (MemoryMappedViewAccessor accessor =
file.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read)) {
byte[] buffer = new byte[accessor.Capacity];
Mutex mutex = Mutex.OpenExisting(@"Global\MyMutex");
mutex.WaitOne();
accessor.ReadArray<byte>(0, buffer, 0, buffer.Length);
mutex.ReleaseMutex();
string xmlData = ConvertByteArrayToString(buffer);
data = DeserializeFromXML(xmlData);
}