2017-04-05 161 views
0

從.Net MemoryMappedFile提供Win32句柄的屬性或方法(如果有的話)是什麼?從MemoryMappedFile獲取Win32句柄

我有非託管C++代碼讀取和寫入C風格的文件,如標準輸入和標準輸出。我想使用MemoryMappedFile :: CreateNew創建一個MemoryMappedFile,然後獲取可以轉換爲FILE *的Win32 HANDLE,以用於非託管C++。我看到MemoryMappedViewAccessor :: SafeMemoryMappedViewHandle和SafeHandle和其他可能性,但我沒有找到任何說明(或通過示例顯示)該句柄可以用作C/C++程序中的Win32句柄的任何內容。我只是不確定具體是什麼提供了Win32 HANDLE。還有其他的可能性,比如使用所有的Windows API和沒有.Net,但我問是否可以使用MemoryMappedFile來完成,我相信如果使用MemoryMappedFile無法完成的話,我可以使用所有Windows API來完成。

更新:以下是@MichaelGunter轉換爲C++的代碼。看到漢斯帕斯坦的評論,他說這不起作用,事實並非如此。從safeHandle-> DangerousGetHandle()返回的句柄似乎有效,但是當我調用_open_osfhandle來轉換句柄時,它會失敗。

MemoryMappedFile^ mmf = nullptr; 
try { mmf = MemoryMappedFile::CreateNew("testmap", 10000, MemoryMappedFileAccess::ReadWrite); } 
catch (Object^ ex) 
{ 
    // show error 
    return; 
} 
SafeMemoryMappedFileHandle^ safeHandle = mmf->SafeMemoryMappedFileHandle; 
bool success = false; 
safeHandle->DangerousAddRef(success); 
if (!success) 
{ 
    // show error 
    return; 
} 
IntPtr handle = safeHandle->DangerousGetHandle(); 
if (safeHandle->IsInvalid) 
{ 
    // show error 
    return; 
} 
pin_ptr<const wchar_t> wchstr = PtrToStringChars(Message); 
if (!Put((intptr_t)handle, const_cast<wchar_t*>(wchstr))) 
{ 
    // show error 
    return; 
} 
safeHandle->DangerousRelease(); 

這就是「Put」功能。

BOOL Put(intptr_t h, wchar_t* Message) { 
    int fd = _open_osfhandle(h, 0); 
    if (fd < 1) 
     return FALSE; 
    FILE * fp = _wfdopen(fd, L"w"); 
    fputws(Message, fp); 
    return TRUE; 
} 

MemoryMappedFile::SafeMemoryMappedFileHandle Property 文檔中說,我需要的安全權限,所以我用在一些地方以下。

[SecurityPermissionAttribute(SecurityAction::LinkDemand, UnmanagedCode = true)] 
+0

沒有直接的方法來做到這一點;但這可能會有所幫助:http://stackoverflow.com/questions/5193579/how-make-file-from-handle-in-winapi –

+0

@丹,是的,謝謝。我知道這一點。我應該在我的問題上說句柄。我很抱歉,感到困惑。我會嘗試更新我的問題來說句柄而不是FILE *。 – user34660

+0

您不能將這樣的句柄轉換爲FILE *。 XY問題。 –

回答

0

給出一個MemoryMappedFile:

MemoryMappedFile mmf = ...; 

得到一個 「安全」 的手柄。只要手柄處於使用狀態,請將此安全手柄存放。

SafeMemoryMappedFileHandle safeHandle = mmf.SafeMemoryMappedFileHandle; 

添加到手柄的引用,以便它不會被收回:

bool success = false; 
safeHandle.DangerousAddRef(ref success); 
if (!success) 
    throw new InvalidOperationException("Failed to addref handle."); 

獲取原始句柄:

IntPtr handle = safeHandle.DangerousGetHandle(); 

當你與原手柄完成,釋放安全手柄:

safeHandle.DangerousRelease(); 
+0

將代碼轉換爲C++的一個注意事項是添加'using using namespace Microsoft :: Win32 :: SafeHandles;' – user34660

+0

我更新了您的代碼轉換爲C++的問題。漢斯帕斯坦說,它不會工作,但如果我們能夠得到它的工作,那將是不可思議的。 – user34660

+0

這並不令我感到驚訝,它不適用於FILE *。 :) –

0

雖然您可以獲取內存映射文件對象的句柄(如Michael的回答中所述),但您將無法將此句柄傳遞給__open_osfhandle,因爲無法像使用內存映射文件對象一樣使用該文件對象。也就是說,你無法讀取或寫入句柄;它可以用只有用來映射文件映射對象的視圖到內存中。

直接使用Win32 API不會有任何區別。文件映射對象根本不提供您正在尋找的功能。

相反,您應該嘗試使用管道對象。如果您不嘗試移動文件指針,則可以將視爲文件。我相信微軟的C運行時可以接受一個管道句柄代替文件句柄,儘管這在文檔中沒有提到。

請參閱Pipe Operations in the .NET Framework開始。

+0

....或者,當然,你可以使用一個實際的文件。 –

+0

管道使用Win32 API。我熟悉[使用重定向輸入和輸出創建子進程](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v = vs.85).aspx)。幾年前,我試圖讓.Net的管道實現工作,我不能。我認爲在.Net中使用WCF更好。如果我使用管道,我更願意直接通過Windows API使用管道。 – user34660

+1

是的,由於您使用C++編寫,Win32 API可能也是我的首選,具體取決於上下文。我曾經假設,既然你使用的是.NET的MemoryMappedFile類而不是CreateFileMapping,你也應該使用.NET管道類,但最終並沒有什麼區別。 –