2015-08-26 73 views
0

我需要從我的Web API中的一條路由訪問內存映射文件。使用正常的IIS工作者設置我沒有運氣,我的服務總是返回「文件未找到」。我試圖添加前綴「全球/」,但仍然沒有運氣。提升IIS工作者身份以訪問內存映射文件

在網上閱讀了很多小時後,我瞭解到我需要更改IIS工作者的身份。所以,僅僅爲了測試的目的,我將工作者身份更改爲管理員帳戶。我上傳了圖片瀏覽:

http://imgur.com/MrA3byz

但仍沒有運氣。有沒有人知道如何正確配置IIS?

這裏是我如何訪問使用C#映射文件的存儲:

string Message = ""; 

try 
{ 
    string MMF_In_Name = "Global\\MMF_Name"; 
    MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name); 

    Messages.Add("Connected to MMF"); 
} 
catch (Exception ex) 
{ 
    Messages.Add(ex.Message); 
} 

我有雙重檢查內存映射文件的名稱,它是正確的。以管理員身份運行的命令行工具按預期工作。

我使用的是IIS 8.5的Windows Server 2012的

+0

就Windows而言,IIS工作進程與任何其他進程完全相同,並且具有所運行的用戶帳戶的所有訪問權限。你確定代碼是正確的嗎?如果f.e.你能成功打開文件嗎?你在標準過程中運行相同的代碼? – Massimo

+0

是的,我可以成功使用內存映射文件。在另一個線程上,有人告訴我需要使用前綴「Global /」創建文件。我也會嘗試。 – chhenning

+0

這個* COULD *是另一個UAC問題(儘管它應該像IIS進程一樣影響標準進程)。你可以嘗試關閉UAC嗎? – Massimo

回答

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工作人員應該能夠通過內存映射文件訪問應用程序。無需改變工作人員的身份。實際上,我使用默認設置運行它。