Managed .NET equivalent of CreateFile & WriteFile from WinBase (kernel32.dll)

I am working with an obsolete file format.

The file is created using unmanaged C ++, which uses the CreateFile () and WriteFile () functions of WinBase.h (found in kernel32.dll).

I used P / Invoke to access these native functions as follows:

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

The problem with this is that when I call WriteFile (), the file is always overwritten by the outgoing call.

Preferably, I would like to use the compatible .NET equivalent, which would allow me to create the same output format.

C ++ code looks like this: (WORK)

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 # looks like this: (OVERWRITES PREVIOUS WRITE, that is, the output will only contain "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();
}

UPDATE: The following C # code will output "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);

Thank.

+3
4

WriteFileEx , SEPARATE OVERLAPPED , OVERLAPPED, . CloseHandle, . OVERLAPPED ? , , - , , .

, . , WriteFile WriteFileEx . , API Win32 # , . , .NET File API , .

API- .NET ( , ..) , []. BitConverter - .

+3

, , File.WriteAllText ?

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

File.WriteAllBytes:

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

There is nothing special about raw API calls. Just get System.IO.FileStream and call Write on it. (One way to get a FileStream is to first get System.IO.File first.

+1
source

Take a look at the classes System.IO.Fileand System.IO.FileInfothey both provide the methods you are looking for.

0
source

Source: https://habr.com/ru/post/1738060/


All Articles