How to enumerate files on a Windows CE based device from the Desktop
In this article I’d like to demonstrate how to enumerate files on a Windows CE based device from the desktop.
Listing the contents of a directly on a Windows CE from the desktop is something I found to be useful every now and then. It involves using the Remote API and ActiveSync / Windows Mobile Device Center
As usual this will involve a few P/Invokes:
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
static extern int CeRapiInit();
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
static extern int CeRapiUninit();
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CeFindFirstFile(string lpFileName, ref CE_FIND_DATA lpFindFileData);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
static extern bool CeFindNextFile(IntPtr hFindFile, ref CE_FIND_DATA lpFindFileData);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
static extern bool CeFindClose(IntPtr hFindFile);
We also need the CE_FIND_DATA structure
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct CE_FIND_DATA
{
public int dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwOID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
};
[StructLayout(LayoutKind.Sequential)]
struct FILETIME
{
public int dwLowDateTime;
public int dwHighDateTime;
}
The CeRapiInit method has be always called before performing Remote API operations. Once done, the CeRapiUninit must be called. For listing the files in a directory, I use CeFindFirstFile, CeFindNextFile, and CeFindClose. How this works: If the file(s) exists CeFindFirstFile will return a valid handle that can be used for calling CeFindNextFile. After going through all the files CeFindNextFile will return false and a call to CeFindClose needs to be called.
public static string[] GetFiles(string remoteDirectory)
{
try
{
CeRapiInit();
var list = new List<string>();
var findData = new CE_FIND_DATA();
var hFindFile = CeFindFirstFile(remoteDirectory + "\\*", ref findData);
if (hFindFile != new IntPtr(-1))
{
try
{
do
{
if (findData.dwFileAttributes != (int)FileAttributes.Directory)
list.Add(findData.cFileName);
} while (CeFindNextFile(hFindFile, ref findData));
}
finally
{
CeFindClose(hFindFile);
}
}
return list.ToArray();
}
finally
{
CeRapiUninit();
}
}
I hope you found this useful.