【轉載】[翻譯整理]使用RAPI庫操作行動裝置——C#語言描述

來源:互聯網
上載者:User

說明,本文原創,所有代碼均摘自自己編寫的程式,保證可以編譯。PS, 微軟的FRONTPAGE 2003還是很討厭,自動無謂的垃圾代碼,害得我光排版就花了2小時。

本頁內容
● 引言
● SMARTPHONE SDK API 庫
● 管理裝置中的目錄檔案
● 取系統資訊
● 遠程操作電話和簡訊功能

    Windows Mobile日益成熟,開發人員隊伍也越來越壯大。作為一個10年的電腦熱愛者和程式員,我也經受不住新技術的誘惑,倒騰起Mobile這個玩具。Mobile和Windows的血緣關係決定了它在Windows程式員中的受歡迎程度,在網路上隨便搜尋一下,關於Mobile應用、開發的文章數不勝數。可是對於計劃開發一款全能的Desktop<=>Device同步管理程式的我來說,卻發現資源少得可憐——僅僅在MSDN和兩個國外的Developer網站上發現了一點資料。現在我仍然在搜尋學習中,在這裡把我迄今掌握的一點心得寫出來,希望能起到拋磚引玉的功效。另請各位高手指正。

    Mobile的開發資源很繁雜,很多人常常弄不清究竟要安裝哪些工具才能搭建出合適的開發環境。但是我相信Microsoft SMARTPHONE 2003 SDK和Microsoft POCKETPC 2003 SDK是所有的人都知道的,它們分別為SmartPhone和PocketPC提供了必不可少的支援。兄弟我至今沒有做出什麼成績,囊中羞澀,好容易攢了台SmartPhone,今天就已Microsoft SMARTPHONE 2003 SDK為例吧。

    SMARTPHONE SDK包含了大量的API,列表如下(選自SDK文檔,本人翻譯):

Smartphone API Description
ActiveSync 建立行動裝置 App程式安裝和配置,同步服務模組,過濾器和協助訪問ActiveSync服務的應用。
Bluetooth API 建立支援藍牙裝置的Mobile應用程式,比如耳機,印表機和其他行動裝置。
CE Messaging (CEMAPI) 建立messaging applications
Configuration Service Providers 建立可配置各種CSPs(Configuration Service Providers)的應用
Connection Manager 建立可自動管理行動裝置網路連接的應用
Control API 在你的行動裝置 App程式中使用Smartphone控制項
Device Management API 建立可遠端存取行動裝置組態管理的應用程式
Game API (GAPI) 建立高效能的即時遊戲
Home Screen API 建立使用者介面外掛程式
HTML Control 建立可顯示HTML文本和內嵌圖片,解析XML和綁定URL到別名的應用程式
MIDI 建立可播放MIDI檔案的應用程式
Object Exchange (OBEX) 建立對象交換應用,允許行動裝置自由的通過無線交換資料
Pocket Outlook Object Model (POOM) API 建立可操作收件匣組件(連絡人,日曆和任務)的行動裝置 App程式
Projects Control 建立可以和Projects Control互動的應用
Remote API (RAPI) 建立可以同步或控制行動裝置的傳統型應用程式
Speech Recognizer 為應用程式增加語音辨識功能(比如語音撥號)
Telephony 建立支援電話和簡訊的應用程式
User Interface 管理輸入面板,增加使用者介面元素到你的行動裝置 App程式
Vibrate API 為你的行動裝置 App程式增加震動特性
Voice Recorder Control 建立移動數字錄音程式
Windows User Interface Controls 建立將移動擴充合并到標準Microsoft Windows CE使用者介面控制項的應用

    要建立Desktop<=>Device的案頭同步管理程式,主要就依靠SDK API中的Remote API(RAPI)。RAPI 庫由一組函數組成,這些函數可用於通過傳統型應用程式管理裝置,包括裝置的目錄檔案、裝置的註冊表和系統資訊。廢話不多說,我們先來看看如何管理裝置中的目錄檔案。

    RAPI提供了一組檔案管理的方法(不完全列表,詳見SDK文檔。選自SDK文檔,本人翻譯):

Function Description
CeCopyFile 複製檔案
CeCreateDirectory 建立目錄
CeCreateFile 建立,開啟檔案、管道、通訊資源、磁碟裝置或者控制台。返回一個控制代碼用來訪問對象。
CeDeleteFile 刪除檔案
CeFindAllFiles 從指定的Windows CE目錄中擷取所有檔案和目錄的資訊,並且複製到一個包含CE_FIND_DATA結構的數組中
CeFindFirstFile 在目錄中尋找匹配給定檔案名稱的一個檔案
CeFindClose 關閉指定的尋找控制代碼,CeFindFirstFile和CeFindNextFile 函數用這個控制代碼尋找檔案
CeFindNextFile 從上一次訪問的CeFindFirstFile繼續尋找檔案
CeGetFileAttributes 返回指定檔案或目錄的屬性
CeGetFileSize 擷取指定檔案的位元組大小
CeGetFileTime 擷取檔案建立日期時間,最後訪問日期時間和最後修改日期時間
CeMoveFile 移動(重新命名)一個檔案或者目錄
CeReadFile 從檔案指標處讀取檔案資料
CeWriteFile 從檔案指標處寫入檔案資料

    首先要說明的是,任何RAPI操作都需要首先初始化與裝置的串連:

Function Description
CeRapiInit (RAPI) 建立Windows CE remote application-programming interface (RAPI).
[C#.NET] using System;
using System.Runtime.InteropServices;public class RAPI
{
 public void RapiInit()
 {
  int ret = CeRapiInit();

  if( ret != 0)
  {
   // 串連失敗,擷取失敗代碼
   int e = CeRapiGetError();

   // 拋出異常
   Marshal.ThrowExceptionForHR(ret);
  }

  // 串連成功
  // To Do

 }

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

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

    串連建立後,就可以進行檔案操作了。看一個將檔案複製到裝置的例子:

[C#.NET]using System;
using System.Runtime.InteropServices;
using System.IO;public class RAPI
{
 private const uint GENERIC_WRITE = 0x40000000;  // 設定讀寫權限
 private const short CREATE_NEW = 1;    // 建立新檔案
 private const short FILE_ATTRIBUTE_NORMAL = 0x80;  // 設定檔案屬性
 private const short INVALID_HANDLE_VALUE = -1;  // 錯誤控制代碼

 IntPtr remoteFile = IntPtr.Zero;
 String LocalFileName = @"c:\test.txt";   // 本機電腦檔案名稱
 String RemoteFileName = @"\My Documents\test.txt";  // 遠程裝置檔案名稱
 byte[] buffer = new byte[0x1000];    // 傳輸緩衝區定義為4k
 FileStream localFile;

 int bytesread = 0;
 int byteswritten = 0;
 int filepos = 0;

 public RapiFile()
 {
  // 建立遠程檔案
  remoteFile = CeCreateFile(RemoteFileName, GENERIC_WRITE, 0, 0, CREATE_NEW,
    FILE_ATTRIBUTE_NORMAL, 0);

  // 檢查檔案是否建立成功
  if ((int)remoteFile == INVALID_HANDLE_VALUE)
  {
   throw new Exception("Could not create remote file");
  }

  // 開啟本地檔案
  localFile = new FileStream(LocalFileName, FileMode.Open);

  // 讀取4K位元組
  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("Could not write to remote file");
   }
   try
   {
    // 重新填充本地緩衝區
    bytesread = localFile.Read(buffer, 0, buffer.Length);
   }
   catch(Exception)
   {
    bytesread = 0;
   }
  }

  // 關閉本地檔案
  localFile.Close();

  // 關閉遠程檔案
  CeCloseHandle(remoteFile);
 }
 // 聲明要引用的API
 [DllImport("rapi.dll", CharSet=CharSet.Unicode)]
 internal static extern int CeCloseHandle(IntPtr hObject);

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

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

    操作完畢後在合適的時候需要斷開RAPI串連,使用如下函數(選自SDK文檔,本人翻譯):

Function Description
CeRapiUninit (RAPI) 銷毀Windows CE remote application-programming interface (RAPI).
[C#.NET]
using System;
using System.Runtime.InteropServices;

public class RAPIUninit{
 public RAPIUninit()
 {
  CeRapiUninit();
 }
 
 // 聲明要引用的API
 [DllImport("rapi.dll", CharSet=CharSet.Unicode)]
 internal static extern int CeRapiUninit();
}
 

    檔案操作的函數有很多,基本思路都是一樣的,在這裡就不一一舉例了。請注意檔案控制代碼使用以後一定要釋放。

    我們再看一個取系統資訊的例子,RAPI提供了一些取系統資訊的函數(選自SDK文檔,本人翻譯):

Function Description
CeGetSystemInfo 返回當前系統資訊
CeGetSystemMetrics 擷取Windows元素的尺寸和系統設定
CeGetVersionEx 擷取當前啟動並執行作業系統版本的擴充資訊
CeGetSystemPowerStatusEx 擷取電池狀態
CeGlobalMemoryStatus 擷取系統實體記憶體和虛擬記憶體資訊
CeGetStoreInformation 擷取儲存空間資訊並填入STORE_INFORMATION結構
[C#.net]public class RAPI
{
 SYSTEM_INFO si;   // 系統資訊
 OSVERSIONINFO versionInfo;  // 版本資訊
 SYSTEM_POWER_STATUS_EX PowerStatus; // 電源資訊
 MEMORYSTATUS ms;   // 記憶體資訊
 String info;

 public void systemInfo()
 {
  // 檢索系統資訊
  try
  {
   CeGetSystemInfo(out si);
  }
  catch(Exception)
  {
   throw new Exception("Error retrieving system info.");
  }

  // 檢索裝置作業系統版本號碼。
  bool b;
  versionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFO)); // 設定為結構大小
  
  b = CeGetVersionEx(out versionInfo);
  if(!b)
  {
   throw new Exception("Error retrieving version information.");
  }

  // 檢索裝置電源狀態
  try
  {
   CeGetSystemPowerStatusEx(out PowerStatus, true); // true 表示讀取最新的電源資訊,否則將從緩衝中獲得
  }
  catch(Exception)
  {
   throw new Exception("Error retrieving system power status.");
  }

  // 檢索裝置記憶體狀態
  CeGlobalMemoryStatus( out ms );

  // 設定檢索資訊的格式。
  info = "The connected device has an ";
  switch (si.wProcessorArchitecture)
  {
   case ProcessorArchitecture.Intel:
    info += "Intel processor.\n";
    break;
   case ProcessorArchitecture.MIPS:
    info += "MIPS processor.\n";
    break;
   case ProcessorArchitecture.ARM:
    info += "ARM processor.\n";
    break;
   default:
    info = "unknown processor type.\n";
    break;
  }

  info += "OS version: " + versionInfo.dwMajorVersion + "." + versionInfo.dwMinorVersion + "." +
   versionInfo.dwBuildNumber + "\n";
  if (PowerStatus.ACLineStatus == 1)
  {
   info += "On AC power:YES\n";
  }
  else
  {
   info += "On AC power:NO \n";
  }
  info += "Battery level: " + PowerStatus.BatteryLifePercent + "%\n";
  info += "Total memory: " + String.Format("{0:###,###,###}",  ms.dwTotalPhys) +
   "\n";

  // 顯示結果。
  Console.WriteLine(info);
 }

 #region 聲明API,詳見SDK文檔
 [DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]
 internal static extern int CeGetSystemInfo(out SYSTEM_INFO pSI);

 [DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]
 internal static extern bool CeGetVersionEx(out OSVERSIONINFO lpVersionInformation);

 [DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]
 internal static extern bool CeGetSystemPowerStatusEx(out SYSTEM_POWER_STATUS_EX pStatus, bool fUpdate);

 [DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]
 internal static extern void CeGlobalMemoryStatus(out MEMORYSTATUS msce);
 #endregion

 #region 聲明結構
 ///  
 /// 處理器架構 (CeGetSystemInfo)
 ///
 public enum ProcessorArchitecture : short
 {
  ///
  /// Intel
  ///
  Intel  = 0,

  ///
  /// MIPS
  ///   
  MIPS  = 1,

  ///
  /// Alpha
  ///
  Alpha  = 2,

  ///  
  /// PowerPC
  ///
  PPC  = 3,

  ///
  /// Hitachi SHx
  ///
  SHX  = 4,

  ///
  /// ARM
  ///
  ARM  = 5,

  ///
  /// IA64
  ///
  IA64  = 6,

  ///
  /// Alpha 64
  ///
  Alpha64  = 7,

  ///
  /// Unknown
  ///
  Unknown   = -1
 }

 ///
 /// 行動裝置記憶體資訊
 ///
 [StructLayout(LayoutKind.Sequential)]
 public struct MEMORYSTATUS
 {
  internal uint dwLength;
  ///
  /// 當前記憶體佔用 (%)
  ///
  public int dwMemoryLoad;
  ///
  /// 實體記憶體總量
  ///
  public int dwTotalPhys;
  ///
  /// 可用實體記憶體
  ///
  public int dwAvailPhys;
  ///
  /// 分頁數
  ///
  public int dwTotalPageFile;
  ///
  /// 未分頁
  ///
  public int dwAvailPageFile;
  ///
  /// 虛擬記憶體總量
  ///
  public int dwTotalVirtual;
  ///
  /// 可用虛擬記憶體
  ///
  public int dwAvailVirtual;
 }

 ///
 /// 行動裝置電源資訊
 ///
 public struct SYSTEM_POWER_STATUS_EX
 {
  ///
  /// 交流電狀態
  ///
  public byte ACLineStatus;
  ///
  /// 電池充電狀態。1 High,2 Low,4 Critical,8 Charging,128 No system battery,255 Unknown status
  ///
  public byte BatteryFlag;
  ///
  /// 電池電量剩餘百分比
  ///
  public byte BatteryLifePercent;
  ///
  /// 保留欄位,設定為0
  ///
  internal byte Reserved1;
  ///   
  /// 電池電量剩餘時間(秒)
  ///
  public int BatteryLifeTime;
  ///
  /// 電池充滿電的總可用時間(秒)
  ///
  public int BatteryFullLifeTime;
  ///
  /// 保留欄位,設定為0
  ///
  internal byte Reserved2;
  ///
  /// 後備電池狀態
  ///
  public byte BackupBatteryFlag;
  ///
  /// 後備電池電量百分比
  ///
  public byte BackupBatteryLifePercent;
  ///
  /// 保留欄位,設定為0
  ///
  internal byte Reserved3;
  ///  
  /// 後備電池電量剩餘時間(秒)
  ///
  public int BackupBatteryLifeTime;
  ///
  /// 後備電池充滿電的總可用時間(秒)
  ///
  public int BackupBatteryFullLifeTime;
 }

 ///
 /// OSVERSIONINFO platform type
 ///
 public enum PlatformType : int
 {
  ///
  /// Win32 on Windows CE.
  ///
  VER_PLATFORM_WIN32_CE = 3
 }

 ///
 /// 作業系統版本資訊
 ///
 public struct OSVERSIONINFO
 {
  internal int dwOSVersionInfoSize;
  ///
  /// 主要版本資訊
  ///
  public int dwMajorVersion;
  ///
  /// 副版本資訊
  ///
  public int dwMinorVersion;
  ///
  /// 編譯資訊
  ///
  public int dwBuildNumber;
  ///
  /// 作業系統類型
  ///
  public PlatformType dwPlatformId;
 }

 ///
 /// 處理器類型 (CeGetSystemInfo)
 ///
  public enum ProcessorType : int
 {
  ///
  /// 386
  ///
  PROCESSOR_INTEL_386 = 386,
  ///
  /// 486
  ///
  PROCESSOR_INTEL_486 = 486,
  ///
  /// Pentium
  ///
  PROCESSOR_INTEL_PENTIUM = 586,
  ///
  /// P2
  ///
  PROCESSOR_INTEL_PENTIUMII = 686,
  ///
  /// IA 64
  ///
  PROCESSOR_INTEL_IA64 = 2200,
  ///
  /// MIPS 4000 series
  ///
  PROCESSOR_MIPS_R4000         = 4000,
  ///
  /// Alpha 21064
  ///
  PROCESSOR_ALPHA_21064        = 21064,
  ///
  /// PowerPC 403
  ///
  PROCESSOR_PPC_403            = 403,
  ///
  /// PowerPC 601
  ///
  PROCESSOR_PPC_601            = 601,
  ///
  /// PowerPC 603
  ///
  PROCESSOR_PPC_603            = 603,
  ///
  /// PowerPC 604
  ///
  PROCESSOR_PPC_604            = 604,
  ///
  /// PowerPC 620
  ///
  PROCESSOR_PPC_620            = 620,
  ///
  /// Hitachi SH3
  ///
  PROCESSOR_HITACHI_SH3        = 10003,
  ///
  /// Hitachi SH3E
  ///
  PROCESSOR_HITACHI_SH3E       = 10004,
  ///
  /// Hitachi SH4
  ///
  PROCESSOR_HITACHI_SH4        = 10005,
  ///
  /// Motorola 821
  ///
  PROCESSOR_MOTOROLA_821      = 821,
  ///
  /// Hitachi SH3
  ///
  PROCESSOR_SHx_SH3            = 103,
  ///
  /// Hitachi SH4
  ///
  PROCESSOR_SHx_SH4            = 104,
  ///
  /// Intel StrongARM
  ///
  PROCESSOR_STRONGARM          = 2577,
  ///
  /// ARM720
  ///
  PROCESSOR_ARM720             = 1824,
  ///
  /// ARM820
  ///
  PROCESSOR_ARM820             = 2080,
  ///
  /// ARM920
  ///
  PROCESSOR_ARM920             = 2336,
  ///
  /// ARM 7
  ///
  PROCESSOR_ARM_7TDMI          = 70001
 }

 ///
 /// CeGetSystemInfo的資料結構
 ///
 public struct SYSTEM_INFO
 {
  ///
  /// 處理器架構
  ///
  public ProcessorArchitecture wProcessorArchitecture;
  ///
  /// 保留
  ///
  internal ushort wReserved;
  ///
  /// Specifies the page size and the granularity of page protection and commitment.
  ///
  public int dwPageSize;
  ///
  /// 應用程式可訪問記憶體位址的最小值
  ///(Pointer to the lowest memory address accessible to applications
  /// and dynamic-link libraries (DLLs). )
  ///   
  public int lpMinimumApplicationAddress;
  ///
  /// 應用程式可訪問記憶體位址的最大值(Pointer to the highest memory address
  /// accessible to applications and DLLs.)
  ///   
  public int lpMaximumApplicationAddress;
  ///
  /// Specifies a mask representing the set of processors configured into
  /// the system. Bit 0 is processor 0; bit 31 is processor 31.
  ///
  public int dwActiveProcessorMask;
  ///
  /// 處理器數量(Specifies the number of processors in the system.)
  ///
  public int dwNumberOfProcessors;
  ///
  /// 處理器類型(Specifies the type of processor in the system.)
  ///
  public ProcessorType dwProcessorType;
  ///
  /// Specifies the granularity with which virtual memory is allocated.
  ///
  public int dwAllocationGranularity;
  ///
  /// Specifies the system architecture-dependent processor level.
  ///
  public short wProcessorLevel;
  ///
  /// Specifies an architecture-dependent processor revision.
  ///
  public short wProcessorRevision;
 }
 #endregion
} 

    RAPI可以做的事情還有很多,比如取註冊表資訊,提供對 Microsoft ActiveSync 底層功能的訪問,運行遠程應用程式,檔案清單等等。只要仔細閱讀SDK文檔,相信都不是難事。

    作為Mobile裝置的案頭管理程式,備份通話記錄,聯機傳送簡訊等功能是必不可少的。在我剛發現RAPI的時候,以為和前面的例子一樣,有現成的函數可以使用。仔細研究以後才發現要複雜的多。相信這是很多朋友的希望實現的功能,所以班門弄斧,簡述如下。

    RAPI並沒有提供通話,SIM卡和簡訊方面的函數,它們分別包含在SmartPhone SDK的Phone API,SIM Manager和Short Message Service中。然而包含這些API的phone.dll,cellcore.dll和sms.dll都是儲存在裝置上的,在Windows上啟動並執行程式是無法調用儲存在遠程裝置上的動態串連庫的。

    我們仍然需要RAPI。雖然它沒有提供直接存取通話記錄和簡訊方面的操作,但是它提供了一個特殊的函數:

Function Description
CeRapiInvoke 使用一種通用的機制執行遠程程式

    CeRapiInvoke的原型如下:

STDAPI_( HRESULT ) CeRapiInvoke(
    LPCWSTR pDllPath,                      // 包含API的Dll檔案完整路徑
    LPCWSTR pFunctionName,         // 要調用的函數名
    DWORD cbInput,                           // 函數輸入緩衝區大小
    BYTE * pInput,                               // 函數輸入緩衝區指標
    DWORD * pcbOutput,                  // 函數輸出緩衝區大小
    BYTE ** ppOutput,                       // 函數輸出緩衝區指標
    IRAPIStream ** ppIRAPIStream,  // 指定使用阻塞模式或流模式
    DWORD dwReserved);                // 保留

    CeRapiInvoke將允許我們調用遠程裝置中的任何API函數!不過不是直接調用,仍然需要對遠程API進行一些“封裝”。由於時間關係,我將在不久的將來為大家獻上關於CeRapiInvoke的詳細說明。

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/jarvisj/archive/2005/06/05/387902.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.