最近经常遇到客户询问GPRS拨号连接的问题,之前另一同事封装过一个拨号的C++的API,但是客户调用之后还是反应不方便。这个GPRS拨号的问题,折腾了两周还没有完全搞定,闹心……
考虑到客户使用C#的较多,客户调用C++封装的API又有意见(这年头,客户真难伺候:( ),这周末有点时间,决定自己写过C#的GPRS拨号源码。本人使用C#的时间还不长,要自主完成此项工程还是很难滴,所以只好求组网络了。在CSDN中搜索了好久没有找见相关使用示例,历经艰辛,花了半天的时间终于调通程序,在此与大家分享一下成果。
查阅了同事的C++源码,要用到WINCE下的coredll.dll的三个函数:RasDial()、RasHangUp()、RasEnumConnections()。下面介绍一下三个函数的用途, 函数的原型在MSDN中有介绍,不过是C++版的,我在这里直接用C#版的写法:
一、拨号函数:RasDial(IntPtr dialExtensions, IntPtr phoneBookPath,IntPtr rasDialParam,uint NotifierType,IntPtr notifier,ref IntPtr pRasConn ) ,函数返回值类型为uint,成功返回0。
二、断开连接的函数:RasHangUp(IntPtr pRasConn),函数返回值类型为uint,成功返回0.
三、列举当前已经建立的活动的连接的函数:RasEnumConnections([In, Out] _RASCONN[] lprasconn, ref UInt32 lpcb, ref UInt32 lpcConnections),函数返回值类似为uint32,参数的结构体类型下文再说。
上面这三个函数的参数的定义这里就不啰嗦地进行解释了,因为MSDN有解释,而我的任务是把MSDN中的C++写法转换成我要用的C#源码。经过网络查找,最好在一个老外的网站找到函数的C#源码,嘿嘿,拿来主义!各位也可到此链接查阅原版http://www.tech-archive.net/Archive/WindowsCE/microsoft.public.windowsce.app.development/2006-02/msg00041.html。
在此,我们也将源码贴出来供大家分享一下:
#region 引用coredll
[DllImport("coredll.dll")]
private static extern uint RasDial
(
IntPtr dialExtensions,
IntPtr phoneBookPath,
IntPtr rasDialParam,
uint NotifierType,
IntPtr notifier,
ref IntPtr pRasConn
);
[DllImport("coredll.dll")]
private static extern uint RasHangUp(IntPtr pRasConn);
[DllImport("coredll.dll", CharSet = CharSet.Unicode)]
internal static extern UInt32 RasEnumConnections([In, Out] _RASCONN[] lprasconn, ref UInt32 lpcb, ref UInt32 lpcConnections);
const int RAS_MaxEntryName = 20;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct _RASCONN
{
private UInt32 m_size;
private IntPtr m_hrasconn;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = RAS_MaxEntryName + 1)]
public char[] m_entryName;
public IntPtr ConnectionHandle { get { return m_hrasconn; } }
public string EntryName { get { return new string(m_entryName).TrimEnd(new char[] { '/0' }); } }
public static _RASCONN CreateStruct()
{
_RASCONN obj = new _RASCONN();
obj.m_size = System.Convert.ToUInt32(Marshal.SizeOf(typeof(_RASCONN)));
obj.m_hrasconn = IntPtr.Zero;
obj.m_entryName = new char[RAS_MaxEntryName + 1];
return obj;
}
}
#endregion
#region
#endregion
/// <summary>
/// 列举已建立的活动连接
/// </summary>
/// <returns></returns>
private static _RASCONN[] EnumerateConnections()
{
_RASCONN[] rasconn;
UInt32 size = 0, noelements = 0;
size = System.Convert.ToUInt32(Marshal.SizeOf((rasconn = new _RASCONN[1])[0] = _RASCONN.CreateStruct()));
if (RasEnumConnections(rasconn, ref size, ref noelements) != 0x00)
{
size = System.Convert.ToUInt32(Marshal.SizeOf((rasconn = new _RASCONN[size / Marshal.SizeOf(typeof(_RASCONN))])[0] = _RASCONN.CreateStruct()) * rasconn.Length);
if (RasEnumConnections(rasconn, ref size, ref noelements) != 0x00) { rasconn = null; }
}
return rasconn;
}
/// <summary>
/// GPRS拨号连接
/// </summary>
/// <param name="EntryName">拨号连接的名称</param>
/// <param name="UserName">用户名</param>
/// <param name="Password">密码</param>
/// <param name="RasConn">返回的句柄</param>
/// <returns></returns>
unsafe private static uint myRasDial(string EntryName, string UserName, string Password, out IntPtr RasConn)
{
/*
EntryName ,UserName,Password - same as in RASDIALPARAMS structure (see
MSDN)
*/
uint r = 0;
RasConn = IntPtr.Zero;
byte[] bRASDIALPARAMS = new byte[1464];
fixed (byte* pAddr = bRASDIALPARAMS)
{
byte* pCurrent = pAddr;
Marshal.WriteInt32((IntPtr)pCurrent, bRASDIALPARAMS.Length);
pCurrent += 4;
foreach (byte b in Encoding.Unicode.GetBytes(EntryName))
{
Marshal.WriteByte((IntPtr)pCurrent, b);
pCurrent++;
}
pCurrent = pAddr + 0x192;//0x192 - offset for RASDIALPARAMS.UserName
foreach (byte b in Encoding.Unicode.GetBytes(UserName))
{
Marshal.WriteByte((IntPtr)pCurrent, b);
pCurrent++;
}
pCurrent = pAddr + 0x394;//0x394 - offset for RASDIALPARAMS.Password
foreach (byte b in Encoding.Unicode.GetBytes(Password))
{
Marshal.WriteByte((IntPtr)pCurrent, b);
pCurrent++;
}
r = RasDial(IntPtr.Zero, IntPtr.Zero, (IntPtr)pAddr, 0, IntPtr.Zero, ref RasConn);
}
return r;
}
/// <summary>
/// 断开所有活动的连接
/// </summary>
public static void DicConnectAll()
{
_RASCONN[] ran = EnumerateConnections();
for (int i = 0; i < ran.Length; i++)
{
RasHangUp(ran[i].ConnectionHandle);
}
}
/// <summary>
/// 断开已建立的连接
/// </summary>
/// <param name="mEntryName">已建立的活动连接的名称</param>
/// <returns></returns>
public static bool disConnect(string mEntryName)
{
_RASCONN[] ran = EnumerateConnections();
for (int i = 0; i < ran.Length; i++)
{
if (ran[i].EntryName == mEntryName)
{
if (RasHangUp(ran[i].ConnectionHandle) == 0)
return true;
else
return false;
}
}
return false; //表示没有此连接
}
/// <summary>
/// 判断是否已经建立连接
/// </summary>
/// <param name="mEntryName">要查询状态的拨号连接的名称</param>
/// <returns></returns>
public static bool GPRSIsCon(string mEntryName)
{
_RASCONN[] ran = EnumerateConnections();
for (int i = 0; i < ran.Length; i++)
{
if (ran[i].EntryName == mEntryName)
return true;
}
return false; //表示没有此连接
}
public static bool GPRSConnectNet(string mEntryName)
{
IntPtr hRaon;
uint res = myRasDial(mEntryName, "", "", out hRaon);
if (res == 0)
return true;
else
return false;
}
-------------------------------------------------------------------
在WINCE 6.0的设备上已经测试过,可行!不过目前还有一点存在问题,就是GPRS模块的上下电没有实现C#来完成,还需要调用同事封装C++的API。等这一难关再攻下来,我再把源码整个上传了。