FindFile 示例
该示例演示如何将包含另一个嵌入结构的结构传递给非托管函数。 它还演示如何使用 MarshalAsAttribute 特性在结构内部声明固定长度的数组。 在该示例中,嵌入的结构元素被添加到父结构中。 有关未经单一化的嵌入结构的示例,请参见结构示例。
FindFile 示例使用以下非托管函数(这里同时显示其原始函数声明):
从 Kernel32.dll 导出的 FindFirstFile。
HANDLE FindFirstFile(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);
传递到该函数的初始结构包含以下元素:
typedef struct _WIN32_FIND_DATA
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;
在该示例中,FindData 类包含原始结构和嵌入结构中的每个元素的相应数据成员。 该类用字符串替换两个原始字符缓冲区。 MarshalAsAttribute 将 UnmanagedType 枚举设置为 ByValTStr,后者用于标识在非托管结构中出现的内联的、固定长度的字符数组。
LibWrap 类包含 FindFirstFile 方法的托管原型,它将 FindData 类作为参数进行传递。 必须用 InAttribute 和 OutAttribute 特性声明该参数,因为作为引用类型的类在默认情况下将作为 In 参数进行传递。
声明原型
' Declares a class member for each structure element.
< StructLayout(LayoutKind.Sequential, CharSet := CharSet.Auto)> _
Public Class FindData
Public fileAttributes As Integer = 0
' creationTime was a by-value FILETIME structure.
Public creationTime_lowDateTime As Integer = 0
Public creationTime_highDateTime As Integer = 0
' lastAccessTime was a by-value FILETIME structure.
Public lastAccessTime_lowDateTime As Integer = 0
Public lastAccessTime_highDateTime As Integer = 0
' lastWriteTime was a by-value FILETIME structure.
Public lastWriteTime_lowDateTime As Integer = 0
Public lastWriteTime_highDateTime As Integer = 0
Public nFileSizeHigh As Integer = 0
Public nFileSizeLow As Integer = 0
Public dwReserved0 As Integer = 0
Public dwReserved1 As Integer = 0
< MarshalAs(UnmanagedType.ByValTStr, SizeConst := 260)> _
Public fileName As String = Nothing
< MarshalAs(UnmanagedType.ByValTStr, SizeConst := 14)> _
Public alternateFileName As String = Nothing
End Class 'FindData
Public Class LibWrap
' Declares a managed prototype for the unmanaged function.
Declare Auto Function FindFirstFile Lib "Kernel32.dll" _
(ByVal fileName As String, <[In], Out> ByVal findFileData As _
FindData) As IntPtr
End Class
// Declares a class member for each structure element.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public class FindData
{
public int fileAttributes = 0;
// creationTime was an embedded FILETIME structure.
public int creationTime_lowDateTime = 0 ;
public int creationTime_highDateTime = 0;
// lastAccessTime was an embedded FILETIME structure.
public int lastAccessTime_lowDateTime = 0;
public int lastAccessTime_highDateTime = 0;
// lastWriteTime was an embedded FILETIME structure.
public int lastWriteTime_lowDateTime = 0;
public int lastWriteTime_highDateTime = 0;
public int nFileSizeHigh = 0;
public int nFileSizeLow = 0;
public int dwReserved0 = 0;
public int dwReserved1 = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
public String fileName = null;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=14)]
public String alternateFileName = null;
}
public class LibWrap
{
// Declares a managed prototype for the unmanaged function.
[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr FindFirstFile(string fileName, [In, Out]
FindData findFileData);
}
// Declares a class member for each structure element.
[StructLayout(LayoutKind::Sequential, CharSet=CharSet::Auto)]
public ref class FindData
{
public:
int fileAttributes;
// creationTime was an embedded FILETIME structure.
int creationTime_lowDateTime;
int creationTime_highDateTime;
// lastAccessTime was an embedded FILETIME structure.
int lastAccessTime_lowDateTime;
int lastAccessTime_highDateTime;
// lastWriteTime was an embedded FILETIME structure.
int lastWriteTime_lowDateTime;
int lastWriteTime_highDateTime;
int nFileSizeHigh;
int nFileSizeLow;
int dwReserved0;
int dwReserved1;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst=260)]
String^ fileName;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst=14)]
String^ alternateFileName;
};
public ref class LibWrap
{
public:
// Declares a managed prototype for the unmanaged function.
[DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
static IntPtr FindFirstFile(String^ fileName, [In, Out]
FindData^ findFileData);
};
调用函数
Public Class App
Public Shared Sub Main()
Dim fd As New FindData()
Dim handle As IntPtr = LibWrap.FindFirstFile("C:\*.*", fd)
Console.WriteLine("The first file: {0}", fd.fileName)
End Sub
End Class
public class App
{
public static void Main()
{
FindData fd = new FindData();
IntPtr handle = LibWrap.FindFirstFile("C:\\*.*", fd);
Console.WriteLine("The first file: {0}", fd.fileName);
}
}
public ref class App
{
public:
static void Main()
{
FindData^ fd = gcnew FindData();
IntPtr handle = LibWrap::FindFirstFile("C:\\*.*", fd);
Console::WriteLine("The first file: {0}", fd->fileName);
}
};