问题
I want that a non-.NET application access a Memory Mapped file, but this application is not aware of the existence of Memory Mapped files, so I need the file path. It is possible?
回答1:
They have some samples here.
EDIT
I think this would provide the answer. Basically, it would seem some sort of memory pointer is required for memory-mapped files, and not a file system path.
回答2:
You can use the GetMappedFileName function to get the path to a memory mapped file when it is mapped. This of course requires that the memory mapped file is actually backed by a physical file, but the question makes it vague what the situation exactly is. Did some third party library hand you a MemoryMappedFile, MemoryMappedViewAccessor or MemoryMappedViewStream, but you don't know whether it is backed by a physical file?
Here is a sample showing how one would get the filename from a MemoryMappedFile:
using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;
namespace MMFilePathTest
{
static class Program
{
private static MemoryMappedFile GetMappedPhysicalFile()
{
return MemoryMappedFile.CreateFromFile("test.bin", System.IO.FileMode.Create, null, 4096);
}
private static MemoryMappedFile GetMappedAnonymousMemory()
{
/* The documentation errounously claims that mapName must not be null. Actually anonymous
* mappings are quite a normal thing on Windows, and is actually both safer and more secure
* if you don't have a need for a name for them anyways.
* (Reported as https://github.com/dotnet/docs/issues/5404)
* Using a name here gives the exact same results (assuming the name isn't already in use). */
return MemoryMappedFile.CreateNew(null, 4096);
}
/* This can be changed to kernel32.dll / K32GetMappedFileNameW if compatibility with Windows Server 2008 and
* earlier is not needed, but it is not clear what the gain of doing so is, see the remarks about
* PSAPI_VERSION at https://msdn.microsoft.com/en-us/library/windows/desktop/ms683195(v=vs.85).aspx */
[DllImport("Psapi.dll", EntryPoint = "GetMappedFileNameW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern int GetMappedFileName(
SafeProcessHandle hProcess,
SafeMemoryMappedViewHandle lpv,
[Out] StringBuilder lpFilename,
int nSize
);
/* Note that the SafeMemoryMappedViewHandle property of SafeMemoryMappedViewAccess and SafeMemoryMappedViewStream
* is actually the address where the file is mapped */
private static string GetPathWithGetMappedFileName(SafeMemoryMappedViewHandle memoryMappedViewHandle)
{
// The maximum path length in the NT kernel is 32,767 - memory is cheap nowadays so its not a problem
// to just allocate the maximum size of 32KB right away.
StringBuilder filename = new StringBuilder(short.MaxValue);
int len;
len = GetMappedFileName(Process.GetCurrentProcess().SafeHandle, memoryMappedViewHandle, filename, short.MaxValue);
if (len == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
filename.Length = len;
return filename.ToString();
}
private static void PrintFileName(MemoryMappedFile memoryMappedFile)
{
try
{
using (memoryMappedFile)
using (MemoryMappedViewAccessor va = memoryMappedFile.CreateViewAccessor())
{
string filename = GetPathWithGetMappedFileName(va.SafeMemoryMappedViewHandle);
Console.WriteLine(filename);
}
}
catch (Win32Exception e)
{
Console.WriteLine("Error: 0x{0:X08}: {1}", e.NativeErrorCode, e.Message);
}
}
static void Main(string[] args)
{
PrintFileName(GetMappedPhysicalFile());
PrintFileName(GetMappedAnonymousMemory());
}
}
}
When I run this I get the output:
\Device\HarddiskVolume5\Users\poizan\Documents\Visual Studio 2017\Projects\MMFilePathTest\MMFilePathTest\bin\Debug\test.bin
Error: 0x000003EE: The volume for a file has been externally altered so that the opened file is no longer valid
Note that the path is returned in native NT path format. If you need to convert that into a dos/win32 format, see this question: How can I convert a native (NT) pathname into a Win32 path name?
For the error when there is not file associated, the error message is a bit weird, but the error code means ERROR_FILE_INVALID, which makes sense since there is no file.
来源:https://stackoverflow.com/questions/1114786/can-i-get-a-path-for-a-memory-mapped-file-net-4-0