Я хочу, чтобы приложение не .NET получало доступ к файлу Memory Mapped, , но это приложение не знает о существовании файлов с памятью, поэтому мне нужен путь к файлу. Возможно?
Могу ли я получить путь для файла с отображением памяти? (.NET 4.0)
Ответ 1
У них есть несколько примеров здесь.
ИЗМЕНИТЬ
Я думаю, это даст ответ. В принципе, казалось бы, какой-то указатель памяти требуется для файлов с отображением памяти, а не для пути к файловой системе.
Ответ 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 NT. Если вам нужно преобразовать это в формат dos/win32, см. Этот вопрос: Как преобразовать собственный путь (NT) в имя пути Win32?
Для ошибки, когда нет связанного файла, сообщение об ошибке немного странно, но код ошибки означает ERROR_FILE_INVALID, что имеет смысл, поскольку нет файла.