如何从 Web API 与内存映射文件通信?
How to commuicate with a Memory Mapped File from a Web API?
我有 Web API 和一个需要通过内存映射文件与本地工具通信的控制器。当我尝试使用 OpenExisting 打开此类文件时,出现 "file not found" 错误。
string MMF_In_Name = "MemoryMappedFilename";
MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name);
我尝试在名称中添加前缀 "Global/" 但没有成功。
接下来我尝试从我的控制器启动一个命令行工具。该工具启动,但它得到相同的 "file not found error"。当我 运行 工具本身一切正常时。这意味着文件名是正确的。
如何说服 IIS worker 让我打开并使用内存映射文件?
我正在使用 Windows Server 2012 和 ISS 8.5。
这适用于 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 worker 这样的客户端尝试访问文件时,它需要确保使用正确的名称,也就是使用 "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 worker 应该能够通过内存映射文件访问应用程序。无需更改工作人员的身份。事实上,我运行它的默认设置。
我有 Web API 和一个需要通过内存映射文件与本地工具通信的控制器。当我尝试使用 OpenExisting 打开此类文件时,出现 "file not found" 错误。
string MMF_In_Name = "MemoryMappedFilename";
MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name);
我尝试在名称中添加前缀 "Global/" 但没有成功。
接下来我尝试从我的控制器启动一个命令行工具。该工具启动,但它得到相同的 "file not found error"。当我 运行 工具本身一切正常时。这意味着文件名是正确的。
如何说服 IIS worker 让我打开并使用内存映射文件?
我正在使用 Windows Server 2012 和 ISS 8.5。
这适用于 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 worker 这样的客户端尝试访问文件时,它需要确保使用正确的名称,也就是使用 "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 worker 应该能够通过内存映射文件访问应用程序。无需更改工作人员的身份。事实上,我运行它的默认设置。