Hi all,
I'm trying to get the list of files in a directory using WINAPI functions FindFirstFile and FindNextFile.
The problem is that WIN32_FIND_DATA.cFileName returns only the first character of the file name.
This is a console application created in Microsoft Visual C# 2008 Express Edition.
Here is the code. Do you have any ideas what is wrong?
Thanks
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace DirectoryWINAPI
{
struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
class Program
{
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindClose(IntPtr hFindFile);
static void Main(string[] args)
{
StreamWriter sw = new StreamWriter("dir.txt", false);
string dir = Path.GetFullPath(System.IO.Directory.GetCurrentDirectory());
WIN32_FIND_DATA wfd = new WIN32_FIND_DATA();
IntPtr h = FindFirstFile((dir + @"\*.*"), out wfd);
while (FindNextFile(h, out wfd))
sw.WriteLine(wfd.cFileName);
FindClose(h);
sw.Flush();
sw.Close();
}
}
}
VulpesPosted Mar 25, 2011, 9:25 AM
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
I think this is because you're using the CharSet.Auto versions of the functions which default to ANSI. As there was no attribute, the strings would have been marshalled to unicode.
JorgePosted Mar 25, 2011, 9:37 AM
VulpesPosted Mar 25, 2011, 9:05 AM
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text; // added this
namespace DirectoryWINAPI
{
[StructLayout(LayoutKind.Sequential)] // added this
struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)] // change here
public byte[] cFileName; // ditto
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] // ditto
public byte[] cAlternateFileName; // ditto
}
class Program
{
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindClose(IntPtr hFindFile);
static void Main(string[] args)
{
StreamWriter sw = new StreamWriter("dir.txt", false);
string dir = Path.GetFullPath(System.IO.Directory.GetCurrentDirectory());
WIN32_FIND_DATA wfd = new WIN32_FIND_DATA();
IntPtr h = FindFirstFile((dir + @"\*.*"), out wfd);
while (FindNextFile(h, out wfd))
sw.WriteLine(Encoding.Unicode.GetString(wfd.cFileName)); // change here
FindClose(h);
sw.Flush();
sw.Close();
}
}
}