gpt4 book ai didi

c# - 将内存映射与服务一起使用

转载 作者:行者123 更新时间:2023-12-03 15:47:03 25 4
gpt4 key购买 nike

我构建了一个应用程序,它也可以作为服务运行(使用 -service )开关。当我从命令提示符运行服务时,这完全没有问题(我设置了一些东西,让我在不作为真正的服务运行时从控制台调试它)。但是,当我尝试将它作为真正的服务运行然后使用我的应用程序打开现有的内存映射时,出现错误...

Unable to find the specified file.



我如何将它作为服务或在控制台中运行:
[STAThread]
static void Main(string[] args)
{
//Convert all arguments to lower
args = Array.ConvertAll(args, e => e.ToLower());

//Create the container object for the settings to be stored
Settings.Bag = new SettingsBag();

//Check if we want to run this as a service
bool runAsService = args.Contains("-service");

//Check if debugging
bool debug = Environment.UserInteractive;

//Catch all unhandled exceptions as well
if (!debug || debug)
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}

if (runAsService)
{
//Create service array
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new CRSService()
};

//Run services in interactive mode if needed
if (debug)
RunInteractive(ServicesToRun);
else
ServiceBase.Run(ServicesToRun);
}
else
{
//Start the main gui
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainGUI());
}
}

在我的应用程序中,我有一个服务端和一个应用程序端。应用程序的目的只是为了控制服务。我使用内存映射文件进行所有控制,它似乎工作得很好并且适合我的需要。但是,当我将应用程序作为真正的服务运行时,我从调试日志中看到它正在创建具有正确名称和访问设置的内存映射文件。我还可以看到文件在它应该在的地方创建。服务中的一切似乎都与我通过控制台调试时完全相同。但是,我的应用程序(作为应用程序而不是服务运行时)告诉我它找不到内存映射文件。我也让它在错误中抛出文件名路径,所以我知道它在正确的位置。

我如何打开内存映射(抛出错误的地方):
m_mmf = MemoryMappedFile.OpenExisting(
m_sMapName,
MemoryMappedFileRights.ReadWrite
);

注意:该服务以与我在其中运行 Visual Studio 的帐户相同的帐户运行。作为示例,下图显示了我的任务管理器、services.msc gui 和我当前识别的帐户。

enter image description here

在服务创建内存映射文件后,如何让我的客户端应用程序看到它?为什么当我将它作为控制台服务运行而不是作为真正的服务运行时它可以工作?

最佳答案

Windows 服务在 session 中独立运行 0 ,当您的控制台应用程序在用户 session 中运行时,为了让它们相互通信,必须在 Global\ 中创建内存映射文件。命名空间,使其可被其他 session 访问。例如

var file = MemoryMappedFile.CreateOrOpen(@"Global\MyMemoryMappedFile", ...

您还应该为文件设置适当的权限,以确保所有用户都可以访问它。

我建议阅读这篇文章 Implementing Non-Persisted Memory Mapped Files Exposing IPC Style Communications with Windows Services ,它更详细地解释了上述内容,并提供了有关设置权限等的示例。

从上面链接的帖子中复制的源代码:

Mutex, Mutex Security & MMF Security Policy Creation


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");

Create & Write to the 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();
}

Reading from the 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);
}

关于c# - 将内存映射与服务一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59977590/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com