【发布时间】:2014-06-30 14:19:34
【问题描述】:
我的目标是 64 位 Windows 8 上的 .Net Framework 3.5(遗憾的是,4.0+ 不是这个项目的选项)。我最初认为问题是 ProcessA 生成的内存映射文件无法被 ProcessB 找到,但即使是 ProcessA 也找不到它刚刚创建的文件,即使句柄很好并且可以用来写入和读取文件。在代码示例中,我在调用 CreateFileMapping 后立即调用 OpenFileMapping,但即使在将数据写入文件后它也会失败。我已经在 CreateFileMapping 中使用了文件映射属性,使其变长并传入 0,使其成为 SECURITY_ATTRIBUTES 结构并为 lpSecurityDescriptor 传入 IntPtr.Zero,所有这些都没有任何乐趣。我也毫无乐趣地尝试了 FileMapAccess ReadWrite 和 AllAccess。我也试过让 memoryfilename 不恒定。我看不到为什么找不到映射文件,即使是创建它的进程也是如此。以下是所涉及代码的基本内容:
private IntPtr hHandle;
private IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
public const Int64 FILESIZE = 1024 * 1024;
private const string memoryfilename = "myfilename";
//CreateFileMapping
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr CreateFileMapping(
IntPtr hFile,
IntPtr lpFileMappingAttributes,
FileMapProtection flProtect,
uint dwMaximumSizeHigh,
uint dwMaximumSizeLow,
[MarshalAs(UnmanagedType.LPStr)] string lpName);
//OpenFileMapping
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenFileMapping(
FileMapAccess dwDesiredAccess,
Int32 bInheritHandle,
[MarshalAs(UnmanagedType.LPStr)] string lpName);
[Flags]
public enum FileMapAccess : uint
{
FileMapCopy = 0x0001,
FileMapWrite = 0x0002,
FileMapRead = 0x0004,
FileMapReadWrite = 0x0006,
FileMapAllAccess = 0x001f,
FileMapExecute = 0x0020,
}
[Flags]
enum FileMapProtection : uint
{
PageReadonly = 0x02,
PageReadWrite = 0x04,
PageWriteCopy = 0x08,
PageExecuteRead = 0x20,
PageExecuteReadWrite = 0x40,
SectionCommit = 0x8000000,
SectionImage = 0x1000000,
SectionNoCache = 0x10000000,
SectionReserve = 0x4000000,
}
//hHandle becomes non-zero
hHandle= CreateFileMapping(
INVALID_HANDLE_VALUE, IntPtr.Zero, FileMapProtection.PageReadWrite,
(uint)0, (uint)FILESIZE, memoryfilename);
//hHandle2 stays zero
IntPtr hHandle2 = OpenFileMapping(FileMapAccess.FileMapWrite, 0, memoryfilename);
//myerror is 2 ERROR_FILE_NOT_FOUND
uint myerror = GetLastError();
//this works and I can read/write the file through UnmanagedMemoryStream
pBuffer = MapViewOfFile(hHandle, FileMapAccess.FileMapWrite, 0, 0, (uint)FILESIZE);
【问题讨论】:
-
您的 pinvoke 声明非常糟糕。最严重的错误是在您的 CreateFileMapping() 声明中,它创建了一个带有中文名称的 MMF。删除 [MarshalAs]。使用 pinvoke.net 网站取得成功。
-
@HansPassant 这是一个使用 pinvoke.net 落后的案例,通常是这样。 Q 中的 p/invoke 来自那里!我刚刚修好了。 pinvoke.net 真的很可怕。也许我们应该找一些专家来制定一个正确的替代方案。想和我一起写一本权威指南吗?!! ;-)
-
你是对的,汉斯!不幸的是,我打破了 CreateFileMapping 和 OpenFileMapping 的 pinvoke 示例(我使用的),无偿地将字符串编组为 LPStr。谢谢!