我需要从我的Web API中的一个路由访问内存映射文件。使用正常的IIS工作器设置我没有运气,我的服务总是返回"文件未找到"。我试着添加前缀" Global /"但仍然没有运气。
在网上阅读了好几个小时后,我了解到我需要更改IIS工作者的身份。因此,仅出于测试目的,我将工作者身份更改为管理员帐户。我在这里上传了一张照片:
但仍然没有运气。有没有人知道如何正确配置IIS?
以下是使用c#:
访问内存映射文件的方法{{1}}
我仔细检查了内存映射文件的名称,这是正确的。以管理员身份运行的命令行工具按预期工作。
我在Windows Server 2012上使用IIS 8.5。
答案 0 :(得分:0)
这适用于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工作者应该能够通过内存映射文件访问应用程序。无需更改工人的身份。实际上,我在默认设置下运行它。