FindFile Sample
This sample demonstrates how to pass a structure that contains a second, embedded structure to an unmanaged function. It also demonstrates how to use the MarshalAsAttribute attribute to declare a fixed-length array within the structure. In this sample, the embedded structure elements are added to the parent structure. For a sample of an embedded structure that is not flattened, see Structs Sample. The Microsoft .NET Framework SDK includes the complete Visual Basic .NET and C# versions of this sample in Samples\Technologies\Interop\Platform-Invoke.
The FindFile sample uses the following unmanaged function, shown with its original function declaration:
FindFirstFile exported from Kernel32.dll.
HANDLE FindFirstFile(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);
The original structure passed to the function contains the following elements:
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;
In this sample, the FindData
class contains a corresponding data member for each element of the original structure and the embedded structure. In place of two original character buffers, the class substitutes strings. MarshalAsAttribute sets the UnmanagedType enumeration to ByValTStr, which is used to identify the inline, fixed-length character arrays that appear within the unmanaged structures.
The LibWrap
class contains a managed prototype of the FindFirstFile
method, which passes the FindData
class as a parameter. The parameter must be declared with the InAttribute and OutAttribute attributes because classes, which are reference types, are passed as In parameters by default.
Declaring Prototypes
' 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 := 256 )> _
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 'LibWrap
[C#]
// Declares a class member for 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=256 )]
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 );
}
Calling Functions
Public Class App
Public Shared Sub Main()
Dim fd As New FindData()
LibWrap.FindFirstFile( "C:\*", fd )
Console.WriteLine( "The first file: {0}", fd.fileName )
End Sub 'Main
End Class 'App
[C#]
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 );
}
}
See Also
Marshaling Classes, Structures, and Unions | Platform Invoke Data Types | Creating Prototypes in Managed Code