這工作在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工作人員應該能夠通過內存映射文件訪問應用程序。無需改變工作人員的身份。實際上,我使用默認設置運行它。
就Windows而言,IIS工作進程與任何其他進程完全相同,並且具有所運行的用戶帳戶的所有訪問權限。你確定代碼是正確的嗎?如果f.e.你能成功打開文件嗎?你在標準過程中運行相同的代碼? – Massimo
是的,我可以成功使用內存映射文件。在另一個線程上,有人告訴我需要使用前綴「Global /」創建文件。我也會嘗試。 – chhenning
這個* COULD *是另一個UAC問題(儘管它應該像IIS進程一樣影響標準進程)。你可以嘗試關閉UAC嗎? – Massimo