1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using Microsoft.Win32.SafeHandles;
namespace WindowsFormsApplication1
{
public class RAPI
{
public void RapiInit()
{
rapiinitresult = CeRapiInit();
//if (ret != 0)
//{
// // throw new Exception("未连接到PDA设备!");
// // 连接失败,获取失败代码
// int e = CeRapiGetError();
// // 抛出异常
// Marshal.ThrowExceptionForHR(ret);
//}
// 连接成功
}
private int rapiinitresult = 0;
public bool Connect(int TimeoutSeconds)
{
//由于CeRapiInit会阻塞主线程,因此使用线程运行CeRapiInit,超过5秒后终止
rapiinitresult = 123456789;
System.Threading.Thread rth = new System.Threading.Thread(new System.Threading.ThreadStart(RapiInit));
rth.Name = "CeRapiInit";
rth.Start();
DateTime d = DateTime.Now.AddMilliseconds(TimeoutSeconds);
while (rapiinitresult == 123456789)
{
if (d.CompareTo(DateTime.Now) <= 0)
{
rth.Interrupt();
// rth.Abort();
CeRapiUninit();
return false;
}
}
int ret = rapiinitresult;
if (ret != 0)
{
// 连接失败,获取失败代码
int e = CeRapiGetError();
// 抛出异常
Marshal.ThrowExceptionForHR(ret);
return false;
}
return true;
}
private const int TimeOut = 2000;//异步连接设备超时时间2秒
#region 初始化、卸载设备(私有)
/// <summary>
/// 异步初始化设备,打开后不关闭(默认打开后不关闭)
/// </summary>
/// <param name="nTimeout">单位ms</param>
/// <returns></returns>
public bool InitDevice(int nTimeout)
{
Rapiinit ri = new Rapiinit();
ri.cbsize = Marshal.SizeOf(ri);
uint hRes = CeRapiInitEx(ref ri);
ManualResetEvent me = new ManualResetEvent(false);
me.SafeWaitHandle = new SafeWaitHandle(ri.heRapiInit, false);
if (!me.WaitOne(nTimeout, true)) //阻塞等待结果
{
CeRapiUninit();
return false;
}
else
{
return true;
}
}
/// <summary>
/// CE设备卸载,一般情况下不适用,各个方法末尾已经卸载设备。
/// </summary>
public void RapiUnInit()
{
CeRapiUninit();
}
#endregion
// 测试PCA是否能连接
public bool testPcaConnect()
{
return InitDevice(TimeOut);
}
#region 该类要用到的结构体
public struct CeFindData
{
public int DwFileAttributes;
public FILETIME FtCreationTime;
public int FtCreationTime2;
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.Explicit)]
private struct Rapiinit
{
[FieldOffset(0)]
public int cbsize;
[FieldOffset(4)]
public readonly IntPtr heRapiInit;
[FieldOffset(8)]
private readonly IntPtr hrRapiInit;
}
#endregion
//public void RapiFile(String LocalFileName, String RemoteFileName)
//{
// // 传输缓冲区定义为4k
// FileStream localFile;
// int bytesread = 0;
// int byteswritten = 0;
// int filepos = 0;
// // 创建远程文件
// try
// {
// remoteFile = CeCreateFile(RemoteFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
// // 检查文件是否创建成功
// if ((int)remoteFile == INVALID_HANDLE_VALUE)
// {
// CeCloseHandle(remoteFile);
// throw new Exception("无法创建文件!");
// }
// }
// catch (Exception ex)
// {
// throw (ex);
// }
// // 打开本地文件
// localFile = new FileStream(LocalFileName, FileMode.Open);
// byte[] buffer = new byte[localFile.Length];
// // 读取4K字节
// bytesread = localFile.Read(buffer, filepos, buffer.Length);
// while (bytesread > 0)
// {
// try
// {
// // 移动文件指针到已读取的位置
// filepos += bytesread;
// // 写缓冲区数据到远程设备文件
// byteswritten = 0;
// if (!Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread, ref byteswritten, 0)))
// { // 检查是否成功,不成功关闭文件句柄,抛出异常
// CeCloseHandle(remoteFile);
// throw new Exception("文件写入失败!");
// }
// 重新填充本地缓冲区
// bytesread = localFile.Read(buffer, 0, buffer.Length);
// }
// catch (Exception)
// {
// localFile.Close(); // 关闭本地文件
// CeCloseHandle(remoteFile);// 关闭远程文件
// bytesread = 0;
// byteswritten = 0;
// filepos = 0;
// }
// finally
// {
// // 关闭本地文件
// localFile.Close();
// CeCloseHandle(remoteFile);// 关闭远程文件
// bytesread = 0;
// byteswritten = 0;
// filepos = 0;
// }
// }
//}
public int CreateProcess(string path)
{
int ret = 255;
// @"/ResidentFlash2/QdPca/QdPca.exe"
// "\\ResidentFlash2\\QdPca\\AppUpdate.exe"
bool result = CeCreateProcess(
path,
null,
null,
null,
false,
0,
null,
null,
null,
null
);
if (result == false)
{
int errnum = CeRapiGetError();
ret = errnum;
}
else
ret = 0;
return ret;
}
[DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool CeCreateProcess(
string lpApplicationName,
string lpCommandLine,
string lpProcessAttributes,
string lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
string lpEnvironment,
string lpCurrentDirectory,
string lpStartupInfo,
string lpProcessInformation
);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
internal static extern int CeDeleteFile(string lpFileName);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
internal static extern int CeRapiGetError();
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
internal static extern int CeRapiInit();
[DllImport("rapi.dll")]
private static extern uint CeRapiInitEx(ref Rapiinit pRapiInit);
//[DllImport("rapi.dll")]
//public static extern int CeRapiUnInit();
// 声明要引用的API
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
internal static extern int CeRapiUninit();
private const uint GENERIC_WRITE = 0x40000000;
// 设置读写权限
private const short CREATE_NEW = 1; // 创建新文件
private const short CREATE_ALWAYS = 2; // 创建新文件
private const short FILE_ATTRIBUTE_NORMAL = 0x80; // 设置文件属性
private const short INVALID_HANDLE_VALUE = -1; // 错误句柄
UIntPtr remoteFile = UIntPtr.Zero;
private const uint GENERIC_READ = 0x80000000;
private const short OPEN_EXISTING = 3;
//String LocalFileName = @"d:/test.txt"; // 本地计算机文件名
//String RemoteFileName = @"/ResidentFlash2/QdPca/param/text.txt"; // 远程设备文件名
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern int CeCloseHandle(IntPtr hObject);
[DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr CeCreateFile(string lpFileName, long dwDesiredAccess, long dwShareMode,
long lpSecurityAttributes, long dwCreationDisposition,
long dwFlagsAndAttributes, long hTemplateFile);
String info;
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CeFindFirstFile(string lpFileName, ref CeFindData lpFindFileData);
[DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr CeFindNextFile(IntPtr hFindFile, ref CeFindData lpFindFileData);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CeFindFirstFile(string lpFileName, ref CE_FIND_DATA lpFindFileData);
[DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr CeFindNextFile(IntPtr hFindFile, ref CE_FIND_DATA lpFindFileData);
[DllImport("rapi.dll ", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool CeFindAllFiles(string szPath, long dwFlags, ref long lpdwFoundCount, ref CE_FIND_DATA[] AllFilesInfo);
//internal static extern bool CeFindAllFiles(string szPath, long dwFlags, ref long lpdwFoundCount, IntPtr AllFilesInfo);
[DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int CeFindClose(IntPtr hFindFile);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CE_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 dwOID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
};
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern int CeGetFileSize(int hFile, int lpOverlapped);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern int CeReadFile(int hFile, byte[] lpBuffer, int lpOverlapped, out int laji, int gouride);
[DllImport("rapi.dll", CharSet = CharSet.Unicode)]
private static extern long CeWriteFile(IntPtr hFile, byte[] lpBuffer,
long nNumberOfbytesToWrite, ref long lpNumberOfbytesWritten,
long lpOverlapped);
public const long FAF_ATTRIBUTES = 0x01;
public const long FAF_NAME = 0x80;
public const long FAF_FOLDERS_ONLY = 0x4000;
public const long FAF_NO_HIDDEN_SYS_ROMMODULES = 0x8000;
public const long FAF_ATTRIB_CHILDREN = 0x1000;
public const long FAF_ATTRIB_NO_HIDDEN = 0x2000;
public const long FAF_OID = 0x0040;
/// <summary>
/// Delete a file on the connected device
/// </summary>
/// <param name="FileName">File to delete</param>
public void DeleteDeviceFile(string FileName)
{
if (!Convert.ToBoolean(CeDeleteFile(FileName)))
{
throw new Exception("Could not delete file");
}
}
/// <summary>
/// 获取PCA文件路径下的文件
/// </summary>
/// <param name="path">PCA路径</param>
/// <returns></returns>
public List<string> GetFileName(string path)
{
List<string> list = new List<string>();
if (InitDevice(TimeOut))
{
CE_FIND_DATA fd = new CE_FIND_DATA();
IntPtr hFile = CeFindFirstFile(path, ref fd);
if (hFile != (IntPtr)INVALID_HANDLE_VALUE)
{
list.Add(fd.cFileName);
hFile = CeFindNextFile(hFile, ref fd);
while (hFile != IntPtr.Zero)
{
list.Add(fd.cFileName);
hFile = CeFindNextFile(hFile, ref fd);
}
CeFindClose(hFile);
}
CeRapiUninit();
}
return list;
}
/// <summary>
/// Copy a device file to the connected PC
/// </summary>
/// <param name="LocalFileName">Name of destination file on PC</param>
/// <param name="RemoteFileName">Name of source file on device</param>
//public bool CopyFileFromDevice(string LocalFileName, string RemoteFileName)
//{
// return CopyFileFromDevice(LocalFileName, RemoteFileName, true);
//}
/// <summary>
/// Copy a device file to the connected PC
/// </summary>
/// <param name="LocalFileName">Name of destination file on PC</param>
/// <param name="RemoteFileName">Name of source file on device</param>
/// <param name="Overwrite">Overwrites existing file on the device if <b>true</b>, fails if <b>false</b></param>
//public bool CopyFileFromDevice(string LocalFileName, string RemoteFileName, bool Overwrite)
//{
// bool Result = false;
// try
// {
// FileStream localFile;
// UIntPtr remoteFile = UIntPtr.Zero;
// int bytesread = 0;
// int create = Overwrite ? CREATE_ALWAYS : CREATE_NEW;
// byte[] buffer = new byte[0x1000]; // 4k transfer buffer
// // open the remote (device) file
// remoteFile = CeCreateFile(RemoteFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// // check for success
// if ((int)remoteFile == INVALID_HANDLE_VALUE)
// {
// CeCloseHandle(remoteFile);
// throw new Exception("无法创建远程文件文件!");
// }
// // create the local file
// localFile = new FileStream(LocalFileName, Overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.Write);
// // read data from remote file into buffer
// CeReadFile(remoteFile, buffer, 0x1000, ref bytesread, 0);
// while (bytesread > 0)
// {
// // write it into local file
// localFile.Write(buffer, 0, bytesread);
// // get more data
// if (!Convert.ToBoolean(CeReadFile(remoteFile, buffer, 0x1000, ref bytesread, 0)))
// {
// CeCloseHandle(remoteFile);
// localFile.Close();
// throw new Exception("Failed to read device data");
// }
// }
// CeCloseHandle(remoteFile);
// localFile.Flush();
// localFile.Close();
// Result = true;
// }
// catch (Exception ex)
// {
// throw ex;
// }
// return Result;
//}
/// <summary>
/// PC-->Wince
/// </summary>
/// <param name="localFileName">pc文件</param>
/// <param name="remoteFileName">wince文件</param>
/// <returns></returns>
public bool CopyFileToPCA(string localFileName, string remoteFileName)
{
//if (InitDevice(TimeOut))
//if (Connect(2000))
{
#region 方法用变量
const long genericWrite = 0x40000000;
// 设置读写权限
//const short createNew = 1;
const long createAlways = 2;
// 创建新文件
const long fileAttributeNormal = 0x80;
// 设置文件属性
const long invalidHandleValue = -1;
// 错误句柄
byte[] buffer = new byte[1024*100];
// 传输缓冲区定义为4k
long byteswritten = 0;
long filepos = 0;
#endregion
//查找远程文件
CeFindData findData = new CeFindData();
IntPtr jieg = CeFindFirstFile(remoteFileName, ref findData);
if (jieg != (IntPtr)(-1))
{
CeDeleteFile(remoteFileName);
}
// 创建远程文件
IntPtr remoteFile = CeCreateFile(remoteFileName, genericWrite, 0, 0, createAlways, fileAttributeNormal, 0);
// 检查文件是否创建成功
if ((long)remoteFile == invalidHandleValue)
{
throw new Exception("创建文件失败!");
}
else
{
// 打开本地文件
FileStream localFile = new FileStream(localFileName, FileMode.Open);
// 读取4K字节
long bytesread = localFile.Read(buffer, (int)filepos, buffer.Length);
while (bytesread > 0)
{
// 移动文件指针到已读取的位置
filepos += bytesread;
// 写缓冲区数据到远程设备文件
if (!Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread, ref byteswritten, 0)))
{
// 检查是否成功,不成功关闭文件句柄,抛出异常
CeCloseHandle(remoteFile);
throw new Exception("写远程文件失败!");
}
try
{
// 重新填充本地缓冲区
bytesread = localFile.Read(buffer, 0, buffer.Length);
}
catch (Exception)
{
bytesread = 0;
}
}
// 关闭本地文件
localFile.Close();
// 关闭远程文件
CeCloseHandle(remoteFile);
//CeRapiUninit();
return true;
}
}
//else
{
return false;
}
}
/// <summary>
/// Wince-->Pc
/// </summary>
/// <param name="remoteFileName">wince文件</param>
/// <param name="localFileName">pc文件</param>
/// <returns> 1 成功 0 失败 -1 没找到文件</returns>
public int CopyFileToPC(string remoteFileName, string localFileName)
{
if (InitDevice(TimeOut))
{
const short createOpen = 3;// 设置读写权限
const uint genericRead = 0x80000000;
const short fileAttributeNormal = 0x80; // 设置文件属性
const short invalidHandleValue = -1; // 错误句柄
IntPtr fileh = CeCreateFile(remoteFileName, genericRead, 0, 0, createOpen, fileAttributeNormal, 0);
if ((int)fileh == invalidHandleValue)
{
return -1;
}
else
{
try
{
FileStream writer = new FileStream(localFileName, FileMode.Create);
int size = CeGetFileSize((int)fileh, 0);
byte[] buff = new byte[400096];
int readed = 400096;
while (readed == 400096)
{
CeReadFile((int)fileh, buff, 400096, out readed, 0);
writer.Write(buff, 0, readed);
}
CeCloseHandle(fileh);
writer.Close();
//上传成功后删除ce文件
CeFindData findData = new CeFindData();
IntPtr jieg = CeFindFirstFile(remoteFileName, ref findData);
if (jieg != (IntPtr)(-1))
{
CeDeleteFile(remoteFileName);
}
CeRapiUninit();
return 1;
}
catch
{
return 0;
}
}
}
else
{
return 0;
}
}
}
}
2
// 使用
if (rapi.Connect(2000))
{
rapi.CopyFileToPCA("本地文件名全称", "PCA端的文件名全称");
}
else
{
// PCA 连接失败
}