WinCE和PC數據交互之RAPI

    /// <summary>
    /// wince設備--pc有線通信類
    /// </summary>
    public class Rapi
    {
        private const int TimeOut = 2000;//異步連接設備超時時間2秒

        #region 初始化、卸載設備(私有)

        /// <summary>
        /// 異步初始化設備,打開後不關閉(默認打開後不關閉,因此定義爲私有)
        /// </summary>
        /// <param name="nTimeout">單位ms</param>
        /// <returns></returns>
        private 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>
        private void RapiUninit()
        {
            CeRapiUninit();
        }

        #endregion


        #region 公有方法(判斷文件是否存在、刪除、wince和pc傳輸文件)

        /// <summary>
        /// 判定文件是否存在
        /// -1:連接不到服務器 0:不存在 1:存在
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns>-1:連接不到服務器 0:不存在 1:存在</returns>
        public int IsExistFile(string fileName)
        {
            if (InitDevice(TimeOut))
            {
                CeFindData findData = new CeFindData();
                int jieg = CeFindFirstFile(fileName, ref findData);
                CeRapiUninit();
                if (jieg != -1) return 1;
                else return 0;
            }
            else
                return -1;

        }

        /// <summary>
        /// 刪除ce設備上的文件
        /// -1:連接不到服務器 0:刪除失敗 1:刪除成功
        /// </summary>
        /// <param name="fileName">要刪除的文件名</param>
        /// <returns>-1:連接不到服務器 0:刪除失敗 1:刪除成功</returns>
        public int DeleteFile(string fileName)
        {
            if (InitDevice(TimeOut))
            {
                CeFindData findData = new CeFindData();
                int jieg = CeFindFirstFile(fileName, ref findData);
                if (jieg != -1)
                {
                    bool isok = CeDeleteFile(fileName);
                    CeRapiUninit();
                    if (isok) return 1;
                    else return 0;
                }
                else return 1; //如果不存在要刪除的文件,等同於刪除成功。
            }
            else
                return -1;
        }

        /// <summary>
        /// PC-->Wince
        /// </summary>
        /// <param name="localFileName">pc文件</param>
        /// <param name="remoteFileName">wince文件</param>
        /// <returns></returns>
        public bool CopyFileToPDA(string localFileName, string remoteFileName)
        {
            #region 方法用變量

            const uint genericWrite = 0x40000000;
            // 設置讀寫權限
            const short createNew = 1;
            // 創建新文件 
            const short fileAttributeNormal = 0x80;
            // 設置文件屬性 
            const short invalidHandleValue = -1;
            // 錯誤句柄 
            byte[] buffer = new byte[0x1000];
            // 傳輸緩衝區定義爲4k 
            int byteswritten = 0;
            int filepos = 0;

            #endregion

            if (InitDevice(TimeOut))
            {
                //查找遠程文件
                CeFindData findData = new CeFindData();
                int jieg = CeFindFirstFile(remoteFileName, ref findData);
                if (jieg != -1)
                {
                    CeDeleteFile(remoteFileName);
                }
                // 創建遠程文件 
                IntPtr remoteFile = CeCreateFile(remoteFileName, genericWrite, 0, 0, createNew, fileAttributeNormal, 0);
                // 檢查文件是否創建成功 
                if ((int) remoteFile == invalidHandleValue)
                {
                    throw new Exception("創建文件失敗!");
                }
                else
                {
                    // 打開本地文件 
                    FileStream localFile = new FileStream(localFileName, FileMode.Open);
                    // 讀取4K字節 
                    int bytesread = localFile.Read(buffer, 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)
        {
            const short createOpen = 3;// 設置讀寫權限
            const uint genericRead = 0x80000000;
            const short fileAttributeNormal = 0x80; // 設置文件屬性
            const short invalidHandleValue = -1; // 錯誤句柄

            if (InitDevice(TimeOut))
            {
                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();
                        int jieg = CeFindFirstFile(remoteFileName, ref findData);
                        if (jieg != -1)
                        {
                            CeDeleteFile(remoteFileName);
                        }*/
                        CeRapiUninit();
                        return 1;
                    }
                    catch
                    {
                        return 0;
                    }
                }
            }
            else
            {
                return 0;
            }
        }

        #endregion


        #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


        #region 聲明要引用的API

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCloseHandle(IntPtr hObject);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeWriteFile(IntPtr hFile, byte[] lpBuffer,
                                              int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten,
                                              int lpOverlapped);

        
        [DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern IntPtr CeCreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode,
                                                  int lpSecurityAttributes, int dwCreationDisposition,
                                                  int dwFlagsAndAttributes, int hTemplateFile);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeRapiUninit();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern bool CeDeleteFile(string fileName);

        [DllImport("rapi.dll")]
        private static extern uint CeRapiInitEx(ref Rapiinit pRapiInit);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeFindFirstFile(string lpFileName, ref CeFindData lpFindFileData);

        [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);

        #endregion


        #region 未用到的api接口

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
                                                        uint dwShareMode, IntPtr lpSecurityAttributes,
                                                        uint dwCreationDisposition,
                                                        uint dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern Boolean WriteFile(SafeFileHandle lpFileName, byte[] lpBuffer,
                                                int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten,
                                                int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCopyFile(string lpExistingFileName, string lpNewFileName, Boolean bFailIfExists);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeReadFile(IntPtr hFile, byte[] lpBuffer,
                                             int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeRapiInit();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeRapiGetError();

        #endregion
    }

在做WinCE和PC之間進行文件傳輸要用到rapi.dll,但是在xp和win7上是不同的移動設備中心,該動態庫的版本也是不同的,因此在VS解決方案中一定不要添加該動態庫,如果添加了一定不要輸出到debug裏面,否則會因爲編譯好的程序在不同的操作系統上出現問題,因爲目標平臺一定會安裝移動設備中心,程序會根據不同版本的rapi.dll動態的調用。

以上是在開發中遇到的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章