写在前面的话
最近在问答里回答了不少问题,这个只是其中一个。以前使用windowsAPI就会搜索现成的代码,这次是第一次去研究怎么将windowsAPI的内容转成C#,所以记录一下备忘。
相关参考
过程说明
将windowsAPI转换为可以使用的函数,主要过程包括:
1、定义好常量或者枚举,用于对各类需要输入的文件参量Flag进行处理;
2、使用DllImport导入相关的核心动态库,比如这个在kernel32里面
3、对于正确的函数名,声明对应的变量类型,需要具体去阅读API的文档,比如DWORD就相当于32位无符号整数,C的指针就相当于IntPtr或者用整数也应该可以代替等,这个具体需要阅读windows的文档。这里需要注意,一般可能需要包括释放指针等各种配套的函数,实际使用和转换过程中需要不止1个方法。实际使用时候看需要吧。
4、进行进一步的封装或者处理,因为声明的类型等原因可能并不能明确知道使用什么样的值,需要对函数进行重载重新封装,来进一步在C#环境下使其可读性更好。如:重载的CreateFileA和重新封装的OpenFile方法。
public static class DllImportHelper
{
[DllImport("kernel32.dll")]
static extern IntPtr CreateFileA(
string fileName,
uint desiredAccess,
uint shareMode,
IntPtr lpSecurityAttributes,
uint creationDisposition,
uint FlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32")]
static extern bool CloseHandle(
IntPtr hObject // handle to object
);
[Flags]
public enum Access_Mask : uint
{
DELETE=0x00010000,
READ_CONTROL=0x00020000,
WRITE_DAC=0x00040000,
WRITE_OWNER=0x00080000,
SYNCHRONIZE=0x00100000,
STANDART_RIGHTS_REQUIRED=0x000F0000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL= 0x0000FFFF,
GENERIC_ALL=0x10000000,
GENERIC_EXECUTE=0x20000000,
GENERIC_WRITE=0x40000000,
GENERIC_READ=0x80000000
}
[Flags]
public enum ShareModeMask : uint
{
None=0x00000000,
FILE_SHARE_DELETE=0x00000004,
FILE_SHARE_READ=0x00000001,
FILE_SHARE_WRITE=0x00000002
}
public enum CreationDisposition : uint
{
CREATE_ALWAYS=2,
CREATE_NEW=1,
OPEN_ALWAYS=4,
OPEN_EXISTING=3,
TRUNCATE_EXISTING=5
}
[Flags]
public enum FileAttributesAndFlags : uint
{
FILE_ATTRIBUTE_READONLY= 0x00000001,
FILE_ATTRIBUTE_HIDDEN= 0x00000002,
FILE_ATTRIBUTE_SYSTEM= 0x00000004,
FILE_ATTRIBUTE_ARCHIVE= 0x00000020,
FILE_ATTRIBUTE_NORMAL= 0x00000080,
FILE_ATTRIBUTE_TEMPORARY= 0x00000100,
FILE_ATTRIBUTE_OFFLINE= 0x00001000,
FILE_ATTRIBUTE_ENCRYPTED= 0x00004000,
FILE_FLAG_BACKUP_SEMANTICS= 0x02000000,
FILE_FLAG_DELETE_ON_CLOSE= 0x04000000,
FILE_FLAG_NO_BUFFERING = 0x20000000,
FILE_FLAG_OPEN_NO_RECALL= 0x00100000,
FILE_FLAG_OPEN_REPARSE_POINT= 0x00200000,
FILE_FLAG_OVERLAPPED= 0x40000000,
FILE_FLAG_POSIX_SEMANTICS= 0x01000000,
FILE_FLAG_RANDOM_ACCESS= 0x10000000,
FILE_FLAG_SESSION_AWARE= 0x00800000,
FILE_FLAG_SEQUENTIAL_SCAN= 0x08000000,
FILE_FLAG_WRITE_THROUGH= 0x80000000
}
public static IntPtr CreateFileA(
string fileName,
Access_Mask access,
ShareModeMask shareMode,
IntPtr lpSecurityAttributes,
CreationDisposition creationDisposition,
FileAttributesAndFlags FlagsAndAttributes,
IntPtr hTemplateFile)
=> CreateFileA(fileName, (uint)access, (uint)shareMode, lpSecurityAttributes, (uint)creationDisposition, (uint)FlagsAndAttributes, hTemplateFile);
public static IntPtr CreateFileA(
string fileName,
Access_Mask access,
ShareModeMask shareMode,
CreationDisposition creationDisposition,
FileAttributesAndFlags FlagsAndAttributes)
=> CreateFileA(fileName, (uint)access, (uint)shareMode, IntPtr.Zero, (uint)creationDisposition, (uint)FlagsAndAttributes, IntPtr.Zero);
public static IntPtr OpenFile(string fileName)
{
var handle = CreateFileA(
fileName,
Access_Mask.GENERIC_READ,
ShareModeMask.None,
CreationDisposition.OPEN_EXISTING,
FileAttributesAndFlags.FILE_ATTRIBUTE_NORMAL
);
return handle;
}
}