我想,一个non-.NET应用程序访问内存映射文件, 但这个应用程序不知道内存映射文件的存在 ,所以我需要的文件路径。 有可能的?
Answer 1:
他们有一些样品这里 。
编辑
我认为这将提供答案。 基本上,这似乎还需要一些内存指针的内存映射文件,而不是文件系统路径。
Answer 2:
您可以使用GetMappedFileName功能,当它被映射到得到一个内存映射文件的路径。 当然,这需要的是内存映射文件实际上是由一个物理文件的支持,但问题使得含糊什么情况到底是。 做了一些第三方库的手你MemoryMappedFile,MemoryMappedViewAccessor或MemoryMappedViewStream,但你不知道它是否是由一个物理文件的支持?
这里是在一个怎么会从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());
}
}
}
当我运行此我得到的输出:
\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
注意,路径在本地NT路径格式返回。 如果您需要将其转换成DOS / Win32的格式,看这个问题: 我如何转换本地(NT)路径为Win32的路径名?
对于当没有文件相关联的错误,该错误信息是有点怪,但错误代码的含义ERROR_FILE_INVALID ,这是有道理的,因为没有文件。
文章来源: Can I get a path for a Memory Mapped File? (.NET 4.0)