【问题标题】:How to commuicate with a Memory Mapped File from a Web API?如何从 Web API 与内存映射文件通信?
【发布时间】:2015-08-25 01:23:48
【问题描述】:

我有一个带有控制器的 Web API,该控制器需要通过内存映射文件与本地工具进行通信。当我尝试使用 OpenExisting 打开此类文件时,出现“找不到文件”错误。

string MMF_In_Name = "MemoryMappedFilename";
MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name);

我尝试在名称中添加前缀“Global/”但没有成功。

接下来我尝试从我的控制器启动命令行工具。该工具启动,但它得到相同的“找不到文件错误”。当我自己运行该工具时,一切正常。也就是说文件名是正确的。

如何说服 IIS 工作人员让我打开和使用内存映射文件?

我使用的是 Windows Server 2012 和 ISS 8.5。

【问题讨论】:

  • 正在运行的凭证工作进程可能是它没有权限。检查尝试输入系统凭据并查看它是否有效
  • 在 ApplicationPool 的高级设置中,我是否需要像用户一样将身份更改为不同的帐户?
  • 是的,或者我猜系统在我看来是凭据问题。

标签: c# asp.net iis asp.net-web-api2 memory-mapped-files


【解决方案1】:

这适用于 Windows Server 2012 和 IIS 8.5。

了解 IIS 工作程序在与普通应用程序不同的终端服务器会话中运行,这一点很重要。很像 Windows 服务。

因此,当应用程序公开内存映射文件时,它需要通过添加到名称中的“Global\”前缀来创建它。但它还需要添加安全描述符或身份。在 c# 中它看起来像这样:

string MMF_Name = @"Global\MyMemoryMappedFileName";

var security = new MemoryMappedFileSecurity();
security.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MemoryMappedFileRights.FullControl, AccessControlType.Allow));


var mmf = MemoryMappedFile.CreateOrOpen(MMF_Name
    , 1024 * 1024
    , MemoryMappedFileAccess.ReadWrite
    , MemoryMappedFileOptions.None
    , security
    , System.IO.HandleInheritability.Inheritable);

在 C++ 中它看起来像这样:

TCHAR szName[] = TEXT("Global\MyMemoryMappedFileName");

HANDLE hMapFile;
LPCTSTR pBuf;

SECURITY_DESCRIPTOR sd;

if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  printf("InitializeSecurityDescriptor failed %d\n", GetLastError());

if (!SetSecurityDescriptorDacl(&sd, true, 0, false))
  printf("SetSecurityDescriptorDacl failed %d\n", GetLastError());

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = false;



hMapFile = CreateFileMapping(
  INVALID_HANDLE_VALUE,    // use paging file
  &sa,                    // default security
  PAGE_READWRITE,          // read/write access
  0,                       // maximum object size (high-order DWORD)
  BUF_SIZE,                // maximum object size (low-order DWORD)
  szName);                 // name of mapping object

if (hMapFile == NULL)
{
  _tprintf(TEXT("Could not create file mapping object (%d).\n"),
       GetLastError());
  return 1;
}

创建此类对象的应用程序需要以管理员权限开始。

现在,当像 IIS 工作者这样的客户端尝试访问文件时,它需要确保使用正确的名称,也就是使用“Global\”前缀。在 C# 中它看起来像:

string MMF_Name = @"Global\MyMemoryMappedFileName";

var MMF = MemoryMappedFile.OpenExisting(MMF_Name
    , MemoryMappedFileRights.ReadWrite
    , HandleInheritability.Inheritable);

在 C++ 中:

TCHAR szName[] = TEXT("Global\\MyMemoryMappedFileName");

HANDLE hMapFile;
LPCTSTR pBuf;

hMapFile = OpenFileMapping(
  FILE_MAP_ALL_ACCESS,   // read/write access
  TRUE,                 // !!!!! do inherit the name
  szName);               // name of mapping object

if (hMapFile == NULL)
{
  _tprintf(TEXT("Could not open file mapping object (%d).\n"),
       GetLastError());
  return 1;
}

当这一切都完成时。 IIS 工作者应该能够通过内存映射文件访问应用程序。无需更改工人的身份。事实上,我在默认设置下运行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多