本文介绍了托管.NET等效给CreateFile&安培; WriteFile的从胜基(KERNEL32.DLL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在遗留的文件格式工作。

I am working with a legacy file format.

该文件是使用非托管C ++,它利用WINBASE.H的CreateFile()及创建的; 。WriteFile的()函数(在kernel32.dll中找到)

The file is created using unmanaged C++ that utilizes the WinBase.h CreateFile() & WriteFile() functions (found in the kernel32.dll).

我一直使用的P / Invoke的互操作来访问,像这样这些本机的功能:

I have been using P/Invoke interop to access these native functions like so:

    [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的(),该文件总是被程序调用覆盖

The issue with this is when I call WriteFile(), the file is always overwritten by the proceeding call.

较好的我想用兼容.NET等价,让我产生输出的完全一样的格式。

Preferable I would like to use a compatible .NET equivalent that would allow me to produce the exact same format of output.

C ++代码看起来像这样:(工作)

The C++ code looks like so: (WORKING)

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#如下:(覆盖以前写IE浏览器将输出文件将只包含T)

The C# is as follows: (OVERWRITES PREVIOUS WRITE i.e. will output file will contain only '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#代码写出来测试:

UPDATE: The following C# code will write out "Test":

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);



感谢。

Thanks.

推荐答案

WriteFileEx只能异步运行,则必须为每个待处理呼叫OVERLAPPED提供一个单独的实例,你必须设置重叠的成员,如文件偏移量。然后,你不能调用CloseHandle的,直到所有操作完成。并使用重叠的局部变量,让它走出去的范围?您的数据被覆盖掉的是的至少的,可以去你错了显示代码的事情。

WriteFileEx only runs asynchronously, you must provide a SEPARATE instance of OVERLAPPED for each pending call, and you must setup the OVERLAPPED members, such as the file offset. Then you can't call CloseHandle until all the operations finish. And using a local variable for OVERLAPPED and letting it go out of scope? Your data getting overwritten is the least of the things that can go wrong with the code you show.

所以这就是为什么你的代码不工作。我不知道为什么你WriteFile的在第一时间切换到WriteFileEx。此外,调用从C#的Win32 API是相当不便,虽然偶尔必要的。但首先看是否.NET文件API做你的需要。

So that's why your code doesn't work. I don't know why you switched from WriteFile to WriteFileEx in the first place. In addition, calling the Win32 API from C# is quite inconvenient, although occasionally necessary. But first see if the .NET File APIs do what you need.

由于.NET文件API倾向于要么字符串的工作(在文本模式,注意换行转换和这样的)或字节数组,你需要把你的其他变量为字节[]。该这里是你的朋友。

Since .NET File APIs tend to work with either strings (in textmode, watch for newline conversions and such) or arrays of bytes, you need to turn your other variables into byte[]. The BitConverter class is your friend here.

这篇关于托管.NET等效给CreateFile&安培; WriteFile的从胜基(KERNEL32.DLL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 11:28