2017-04-05 109 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管道类,但最终并没有什么区别。 –