.NET CF 開發 3G 應用有兩條路:
| API | 用途 |
|---|---|
RasGetEntryDialParams | 取得預設連線項參數 (含儲存的密碼) |
RasDial | 撥號建立連線,支援非同步事件通知 |
RasHangUp | 掛斷連線 |
RasGetConnectStatus | 查詢目前連線狀態 |
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern int RasGetEntryDialParams(string phoneBook, byte[] dialParams, out uint passwordFlag);
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern int RasDial(IntPtr extensions, string phoneBook, byte[] dialParams, uint notifierType, IntPtr hwnd, ref int rasConn);
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern int RasHangUp(int rasConn);
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern uint RasGetConnectStatus(int rasConn, byte[] connStatus);
RasDial 的 notifierType = 0xFFFFFFFF 時,hwnd 可接收 Windows 訊息通知連線狀態變更。繼承 MessageWindow 並覆寫 WndProc 將訊息轉為 C# 事件,實現 Observer 模式。
using System;
using System.Runtime.InteropServices;
using Microsoft.WindowsCE.Forms; // MessageWindow
public class RasManager : MessageWindow
{
// 單例
private static readonly RasManager _instance = new RasManager();
public static RasManager Instance => _instance;
// 事件定義
public delegate void NotifyEvent();
public event NotifyEvent OnConnectedEvent;
public event NotifyEvent OnDisconnectedEvent;
// RAS 狀態枚舉 (節錄關鍵值)
private enum RASCONNSTATE
{
RASCS_Connected = 0x2000,
RASCS_Disconnected = 0x2001
// 完整枚舉請參考 RAS Reference
}
private const int WM_RASDIALEVENT = 0xCCCD; // RAS 專用訊息
// WndProc 轉發 Windows 訊息為 C# 事件
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_RASDIALEVENT)
{
var state = (RASCONNSTATE)msg.WParam.ToInt32();
switch (state)
{
case RASCONNSTATE.RASCS_Connected:
OnConnectedEvent?.Invoke();
break;
case RASCONNSTATE.RASCS_Disconnected:
OnDisconnectedEvent?.Invoke();
break;
// 其他狀態可視需求處理 (認證中、重試等)
}
}
base.WndProc(ref msg);
}
// 對外 API
public void DialUp(string entryName, string user, string password)
{
// 1. 取得預設參數 (含密碼)
// 2. 填入使用者輸入的 user/password (若提供)
// 3. 呼叫 RasDial,傳入 this.Handle 作為 hwnd 接收事件
}
public void HangUp() => RasHangUp(_currentConn);
public RASCONNSTATE GetStatus()
{
// 呼叫 RasGetConnectStatus 解析狀態
return RASCONNSTATE.RASCS_Disconnected;
}
private int _currentConn = 0;
}
public class Form1 : Form
{
public Form1()
{
// 訂閱連線事件
RasManager.Instance.OnConnectedEvent += OnConnected;
RasManager.Instance.OnDisconnectedEvent += OnDisconnected;
}
private void OnConnected()
{
this.Invoke(() => lblStatus.Text = "已連線 - 3G");
}
private void OnDisconnected()
{
this.Invoke(() => lblStatus.Text = "未連線");
}
private void btnDial_Click(object sender, EventArgs e)
{
RasManager.Instance.DialUp("3G Connection", null, null);
}
private void btnHangUp_Click(object sender, EventArgs e)
{
RasManager.Instance.HangUp();
}
private void btnQueryStatus_Click(object sender, EventArgs e)
{
var state = RasManager.Instance.GetStatus();
MessageBox.Show($"當前狀態: {state}");
}
}
RASCS_OpenPort → RASCS_PortOpened → RASCS_ConnectDevice → RASCS_DeviceConnected
→ RASCS_AllDevicesConnected → RASCS_Authenticate → RASCS_AuthNotify → RASCS_AuthRetry
→ RASCS_AuthCallback → RASCS_AuthChangePassword → RASCS_AuthProject → RASCS_AuthLinkSpeed
→ RASCS_AuthAck → RASCS_ReAuthenticate → RASCS_Authenticated
→ RASCS_PrepareForCallback → RASCS_WaitForModemReset → RASCS_WaitForCallback
→ RASCS_Projected → RASCS_Interactive → RASCS_RetryAuthentication
→ RASCS_CallbackSetByCaller → RASCS_PasswordExpired
→ RASCS_Connected (成功)
→ RASCS_Disconnected (斷線)
HKLM\Comm\RAS\Entries 程式化建立。RasGetEntryDialParams 可取得儲存密碼;若使用者輸入新密碼,需更新 RASDIALPARAMS 結構體中對應欄位。RasDial 為非同步,事件在 MessageWindow 執行緒觸發,**更新 UI 必須用 Invoke**。ERROR_INVALID_ENTRY (連線項不存在)、ERROR_NO_CARRIER (無訊號)、ERROR_AUTHENTICATION_FAILURE (認證失敗)。HangUp 再 DialUp 新項目。同樣的 RAS 封裝可直接支援:
.NET CF 3G 開發**首選 RAS API**,避開 AT Commands 的協議地獄。核心在於:正確 P/Invoke 簽名、MessageWindow 將 Windows 訊息轉為 C# 事件、Invoke 確保 UI 執行緒安全。掌握此架構,即可快速構建穩健的行動網路應用。