从WinBase(kernel32.dll)管理.NET等效于CreateFile和WriteFile

我正在使用遗留文件格式。

该文件是使用非托管C ++创建的,该C ++使用WinBase.h CreateFile()和WriteFile()函数(在kernel32.dll中找到)。

我一直在使用P / Invoke互操作来访问这些本机函数,如下所示:

[DllImport("kernel32.dll")] public static extern bool WriteFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, [In] ref NativeOverlapped lpOverlapped); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool WriteFileEx( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, [In] ref NativeOverlapped lpOverlapped, WriteFileCompletionDelegate lpCompletionRoutine); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr hObject); public delegate void WriteFileCompletionDelegate( UInt32 dwErrorCode, UInt32 dwNumberOfBytesTransfered, ref NativeOverlapped lpOverlapped); 

这个问题是当我调用WriteFile()时,文件总是被正在进行的调用覆盖。

我希望使用兼容的.NET等价物来生成完全相同的输出格式。

C ++代码如下所示:(工作)

 HANDLE hFile = CreateFile(sFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(hFile, &someVar1, sizeof(bool), &dwWritten, NULL); WriteFile(hFile, &someVar1, sizeof(long), &dwWritten, NULL); WriteFile(hFile, &someVar2, sizeof(bool), &dwWritten, NULL); WriteFile(hFile, sStr.GetBuffer(0), dwStrLen*sizeof(TCHAR), &dwWritten, NULL); CloseHandle(hFile); 

C#如下:( OVERWRITES PREVIOUS WRITE即输出文件只包含’T’)

 { var hFile = COMFileOps2.CreateFile(FILE_NAME, (uint) COMFileOps2.FILE_GENERIC_WRITE, COMFileOps2.FILE_SHARE_WRITE, IntPtr.Zero, COMFileOps2.CREATE_ALWAYS, COMFileOps2.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); var natOverlap = new NativeOverlapped(); COMFileOps2.WriteFileEx(hFile, new byte[] {(byte) 't'}, 1, ref natOverlap, Callback); COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'e' }, 1, ref natOverlap, Callback); COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'s' }, 1, ref natOverlap, Callback); COMFileOps2.WriteFileEx(hFile, new byte[] { (byte)'T' }, 1, ref natOverlap, Callback); COMFileOps2.CloseHandle(hFile); } private static void Callback(uint dwerrorcode, uint dwnumberofbytestransfered, ref NativeOverlapped lpoverlapped) { throw new NotImplementedException(); } 

更新:以下C#代码将写出“测试”:

 uint written; uint position = 0; var natOverlap0 = new NativeOverlapped(); COMFileOps.WriteFile(hFile, new byte[] {(byte) 'T'}, 1, out written, ref natOverlap0); position += written; var natOverlap1 = new NativeOverlapped {OffsetLow = (int) position}; COMFileOps.WriteFile(hFile, new byte[] { (byte)'e' }, 1, out written, ref natOverlap1); position += written; var natOverlap2 = new NativeOverlapped { OffsetLow = (int)position }; COMFileOps.WriteFile(hFile, new byte[] { (byte)'s' }, 1, out written, ref natOverlap2); position += written; var natOverlap3 = new NativeOverlapped { OffsetLow = (int)position }; COMFileOps.WriteFile(hFile, new byte[] { (byte)'t' }, 1, out written, ref natOverlap3); COMFileOps.CloseHandle(hFile); 

谢谢。

WriteFileEx只是异步运行,您必须为每个挂起的调用提供OVERLAPPED的SEPARATE实例,并且必须设置OVERLAPPED成员,例如文件偏移量。 然后,在完成所有操作之前,您无法调用CloseHandle。 并使用局部变量OVERLAPPED并让它超出范围? 被覆盖的数据是您显示的代码可能出错的最少数据。

这就是你的代码不起作用的原因。 我不知道为什么你首先从WriteFile切换到WriteFileEx。 此外,尽管偶尔需要,但从C#调用Win32 API非常不方便。 但首先看看.NET File API是否能满足您的需求。

由于.NET File API倾向于使用字符串(在textmode中,监视换行符等)或字节数组,因此需要将其他变量转换为byte []。 BitConverter类是你的朋友。

您没有解释您尝试处理的格式,但File.WriteAllText不足够吗?

 File.WriteAllText("someFile.txt", "some format"); 

对于二进制文件,您可以使用File.WriteAllBytes :

 File.WriteAllBytes("someFile.bin", new byte[] { 0x1, 0x2, 0x3 }); 

原始API调用没有什么特别之处。 只需获取一个System.IO.FileStream并在其上调用Write。 (获取FileStream的一种方法是首先获取System.IO.File。

查看System.IO.FileSystem.IO.FileInfo类,它们都提供了您正在寻找的方法。