Calling WriteFileEx() from C# (including supporting structures, constants, etc...)
Today I had the unfortunate and tedious task of calling the WriteFileEx API from a managed application. For you consuming pleasure I have posted the source code for a console app that creates a file called history.txt in the local directory and writes the word “test” into it.
I updated the API information on Pinvoke.net so you can grab it from there as well.
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication8
{
struct OVERLAPPED
{
public IntPtr Internal;
public IntPtr InternalHigh;
public UInt32 Offset;
public UInt32 OffsetHigh;
public IntPtr hEvent;
};
class Class1
{
public const int FILE_READ_DATA = 0x0001; // file & pipe
public const int FILE_LIST_DIRECTORY = 0x0001; // directory
public const int FILE_WRITE_DATA = 0x0002; // file & pipe
public const int FILE_ADD_FILE = 0x0002; // directory
public const int FILE_APPEND_DATA = 0x0004; // file
public const int FILE_ADD_SUBDIRECTORY = 0x0004; // directory
public const int FILE_CREATE_PIPE_INSTANCE = 0x0004; // named pipe
public const int FILE_READ_EA = 0x0008; // file & directory
public const int FILE_WRITE_EA = 0x0010; // file & directory
public const int FILE_EXECUTE = 0x0020; // file
public const int FILE_TRAVERSE = 0x0020; // directory
public const int FILE_DELETE_CHILD = 0x0040; // directory
public const int FILE_READ_ATTRIBUTES = 0x0080; // all
public const int FILE_WRITE_ATTRIBUTES = 0x0100; // all
public const long STANDARD_RIGHTS_REQUIRED = 0x000F0000L;
public const long READ_CONTROL = 0x00020000L;
public const long SYNCHRONIZE = 0x00100000L;
public const long STANDARD_RIGHTS_READ = READ_CONTROL;
public const long STANDARD_RIGHTS_WRITE = READ_CONTROL;
public const long STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
public const long STANDARD_RIGHTS_ALL = 0x001F0000L;
public const long SPECIFIC_RIGHTS_ALL = 0x0000FFFFL;
public const long FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF;
public const long FILE_GENERIC_READ = STANDARD_RIGHTS_READ |
FILE_READ_DATA |
FILE_READ_ATTRIBUTES |
FILE_READ_EA |
SYNCHRONIZE;
public const long FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
FILE_WRITE_DATA |
FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA |
FILE_APPEND_DATA |
SYNCHRONIZE;
public const long FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE |
FILE_READ_ATTRIBUTES |
FILE_EXECUTE |
SYNCHRONIZE;
public const int FILE_SHARE_READ = 0x00000001;
public const int FILE_SHARE_WRITE = 0x00000002;
public const int FILE_SHARE_DELETE = 0x00000004;
public const int FILE_ATTRIBUTE_READONLY = 0x00000001;
public const int FILE_ATTRIBUTE_HIDDEN = 0x00000002;
public const int FILE_ATTRIBUTE_SYSTEM = 0x00000004;
public const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const int FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
public const int FILE_ATTRIBUTE_DEVICE = 0x00000040;
public const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
public const int FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
public const int FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
public const int FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
public const int FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
public const int FILE_ATTRIBUTE_OFFLINE = 0x00001000;
public const int FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
public const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
public const int FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001;
public const int FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002;
public const int FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004;
public const int FILE_NOTIFY_CHANGE_SIZE = 0x00000008;
public const int FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010;
public const int FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020;
public const int FILE_NOTIFY_CHANGE_CREATION = 0x00000040;
public const int FILE_NOTIFY_CHANGE_SECURITY = 0x00000100;
public const int FILE_ACTION_ADDED = 0x00000001;
public const int FILE_ACTION_REMOVED = 0x00000002;
public const int FILE_ACTION_MODIFIED = 0x00000003;
public const int FILE_ACTION_RENAMED_OLD_NAME = 0x00000004;
public const int FILE_ACTION_RENAMED_NEW_NAME = 0x00000005;
public const int MAILSLOT_NO_MESSAGE = -1;
public const int MAILSLOT_WAIT_FOREVER = -1;
public const int FILE_CASE_SENSITIVE_SEARCH = 0x00000001;
public const int FILE_CASE_PRESERVED_NAMES = 0x00000002;
public const int FILE_UNICODE_ON_DISK = 0x00000004;
public const int FILE_PERSISTENT_ACLS = 0x00000008;
public const int FILE_FILE_COMPRESSION = 0x00000010;
public const int FILE_VOLUME_QUOTAS = 0x00000020;
public const int FILE_SUPPORTS_SPARSE_FILES = 0x00000040;
public const int FILE_SUPPORTS_REPARSE_POINTS = 0x00000080;
public const int FILE_SUPPORTS_REMOTE_STORAGE = 0x00000100;
public const int FILE_VOLUME_IS_COMPRESSED = 0x00008000;
public const int FILE_SUPPORTS_OBJECT_IDS = 0x00010000;
public const int FILE_SUPPORTS_ENCRYPTION = 0x00020000;
public const int FILE_NAMED_STREAMS = 0x00040000;
public const int FILE_READ_ONLY_VOLUME = 0x00080000;
public const int CREATE_ALWAYS = 2;
public delegate void WriteFileCompletionDelegate(UInt32 dwErrorCode,
UInt32 dwNumberOfBytesTransfered, ref OVERLAPPED lpOverlapped);
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool WriteFileEx(IntPtr hFile, byte [] lpBuffer,
uint nNumberOfBytesToWrite, [In] ref OVERLAPPED lpOverlapped,
WriteFileCompletionDelegate lpCompletionRoutine);
[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool CloseHandle(IntPtr hObject);
[STAThread]
static void Main(string[] args)
{
IntPtr hfile;
hfile = CreateFile(@"history.txt", (UInt32)FILE_ALL_ACCESS, FILE_SHARE_WRITE, IntPtr.Zero, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
OVERLAPPED ol = new OVERLAPPED();
WriteFileEx(hfile, new byte[] { (byte)'t', (byte)'e', (byte)'s', (byte)'t' }, 4, ref ol, new WriteFileCompletionDelegate(Class1.callback));
CloseHandle(hfile);
}
private static void callback(UInt32 dwErrorCode, UInt32 dwNumberOfBytesTransfered, ref OVERLAPPED lpOverlapped)
{
Console.Write("In the callback");
Console.Read();
}
}
}
Comments
- Anonymous
July 07, 2004
Woudln't it make more sense to put those flags into enums? You can call them Enum1, Enum2 and so on… - Anonymous
July 07, 2004
It certainly would make more sense but I was just wanting to get a working sample, nothing that was real-world ready. - Anonymous
July 09, 2004
Glad to see you are back to bloggn' Roberto. ;)