我的目标是在64位Windows 8上使用.Net Framework 3.5(可惜该项目不是4.0+)。我最初认为问题是ProcessB无法找到ProcessA生成的内存映射文件,但甚至找不到即使句柄不错,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);
[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
);
该DllImport
属性使用CharSet.Auto
,意味着将使用该函数的宽字符版本。然后,您使用传递ANSI编码的字符串UnmanagedType.LPStr
。正如汉斯所说,这意味着当系统将您提供的ANSI编码文本解释为UTF-16编码时,您的名字将会被修饰。
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenFileMapping(
FileMapAccess dwDesiredAccess,
Int32 bInheritHandle,
[MarshalAs(UnmanagedType.LPStr)]
string lpName
);
这次您省略了CharSet.Auto
,因此这次默认为``CharSet.Ansi is used. And so the ANSI version of the function is used, which matches
UnmanagedType.LPStr` '' 。因此,将传递预期的名称。
所有这些都解释了系统为什么报告ERROR_FILE_NOT_FOUND
。
修复p / invoke声明,一切都会好起来。
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr CreateFileMapping(
IntPtr hFile,
IntPtr lpFileMappingAttributes,
FileMapProtection flProtect,
uint dwMaximumSizeHigh,
uint dwMaximumSizeLow,
string lpName
);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr OpenFileMapping(
FileMapAccess dwDesiredAccess,
bool bInheritHandle,
string lpName
);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句