Connection Manager is a fundamental part of Windows Mobile but it currently exposes only a native API. The good news is that most of these APIs are simple and can be easily accessed from the .NET Compact Framework. There are a few enumerations and structures that you will also need to define but for the most part, the process is relatively simple.
When you use the Connection Manager to establish a connection, you must specify the characteristics of the desired connection. In native code you specify these characteristics using a native structure, CONNMGR_CONNECTIONINFO, and several groups of #define macros. To make the structure more consistent with other features of .NET, you might implement the native structure as a managed class and name the managed class something like ConnMgrConnectionInfo. Rather than representing the macros as constants in .NET, you can create more explicit groupings of the macros by defining each group of related macros as a set of enumeration values.
Note: |
|---|
|
If you would like to check out the various Connection Manager native code declarations, take a look at the connmgr.h C++ header file located in %Program Files%\Windows Mobile 6 SDK\PocketPC\Include\Armv4i.
|
Several of the structure members rely on the macros, so the first thing to do is define the enumerations that correspond to the macros.
The first enumeration corresponds to the CONNMGR_PARAM_* family of macros. These values identify which of the criteria fields in the structure are valid. The criteria-related fields in the structure specify the desired characteristics of the requested connection. A connection request can specify multiple criteria therefore the enumeration declaration includes the Flags attribute as shown in the following code. By marking the enumeration with the Flags attribute, you can bitwise-or the members together.
[Flags]
enum ConnMgrParam : int
{
GuidDestNet = 0x1,
MaxCost = 0x2,
MinRcvBw = 0x4,
MaxConnLatency = 0x8
}
Each of the enumeration members have the same name as the structure field to which they correspond. The upcoming discussion of the structure definition will address the meanings of each of the fields.
The next enumeration corresponds to the CONNMGR_FLAG_PROXY_* macros. These values specify the types of proxy servers that Connection Manager can use to establish the connection. Like the ConnMgrParam enumeration, this declaration includes the Flags attribute as shown in the following code.
[Flags]
enum ConnMgrProxy : int
{
NoProxy = 0x0,
Http = 0x1,
Wap = 0x2,
Socks4 = 0x4,
Socks5 = 0x8
}
The next thing to consider when requesting a connection is the priority of the request. The Connection Manager is responsible for all connections on the device and tries to service as many of the requests for those connections as possible. To assist the Connection Manager in determining the order and importance of each request, each request must specify its priority. The Connection Manager supports several different priority levels; however, applications commonly use only a few of these values. The following code shows the enumeration declaration with the commonly used priority values.
enum ConnMgrPriority
{
UserInteractive = 0x8000,
HighPriorityBackground = 0x0200,
LowPriorityBackground = 0x0008
}
Table 2 provides a description of each of these priorities.
Table 2. Common Connection priorities
|
Priority
|
Description
|
|---|
|
UserInteractive
|
A user-initiated action has requested the connection and the user interface is waiting for the connection. This priority supersedes most other priorities.
|
|
HighPriorityBackground
|
The connection request is of high priority, but the application is in the background and therefore not affecting the user interface.
|
|
LowPriorityBackground
|
The connection request only connects if another higher priority application is already using the requested path. Using this priority, an application may share an existing connection but will not establish a new one.
|
Connection Manager supports a number of priority values beyond those in the enumeration declaration. The CONNMGR_PRIORITY_* macros in the connmgr.h header file provide the complete list. For a description of the priority values not listed in Table 2, check out Connection Manager Priority Constants.
The last enumeration is for the connection status values. For the most part, the names of each status value are self-explanatory. For a description of each status value, see Connection Manager Status Constants or look at the CONNMGR_STATUS_* macros in the connmgr.h header file. The following code shows the status value enumeration.
enum ConnMgrStatus
{
Unknown = 0x00,
Connected = 0x10,
Suspended = 0x11,
Disconnected = 0x20,
ConnectionFailed = 0x21,
ConnectionCanceled = 0x22,
ConnectionDisabled = 0x23,
NoPathToDestination = 0x24,
WaitingForPath = 0x25,
WaitingForPhone = 0x26,
PhoneOff = 0x27,
ExclusiveConflict = 0x28,
NoResources = 0x29,
ConnectionLinkFailed = 0x2a,
AuthenticationFailed = 0x2b,
NoPathWithProperty = 0x2c,
WaitingConnection = 0x40,
WaitingForResource = 0x41,
WaitingForNetwork = 0x42,
WaitingDisconnection = 0x80,
WaitingConnectionAbort = 0x81
}
With all of the enumerations defined, the next thing to do is understand the connection request structure. As you are likely aware, you can represent a native structure as either a managed structure or a managed class. In general, classes are a little more flexible than structures because classes allow you to provide a default constructor and use member initializers. As mentioned earlier in this article, the ConnMgrConnectionInfo managed class represents to the CONNMGR_CONNECTIONINFO native structure. The following code shows the ConnMgrConnectionInfo class definition.
[StructLayout(LayoutKind.Sequential)]
class ConnMgrConnectionInfo
{
Int32 cbSize; // DWORD
public ConnMgrParam dwParams = 0; // DWORD
public ConnMgrProxy dwFlags = 0; // DWORD
public ConnMgrPriority dwPriority = 0; // DWORD
public Int32 bExclusive = 0; // BOOL
public Int32 bDisabled = 0; // BOOL
public Guid guidDestNet = Guid.Empty; // GUID
public IntPtr hWnd = IntPtr.Zero; // HWND
public UInt32 uMsg = 0; // UINT
public Int32 lParam = 0; // LPARAM
public UInt32 ulMaxCost = 0; // ULONG
public UInt32 ulMinRcvBw = 0; // ULONG
public UInt32 ulMaxConnLatency = 0; // ULONG
} ;
The description of each of the structure fields is in Table 3.
Table 3. ConnMgrConnectionInfo class members
|
Field
|
Description
|
|---|
|
cbSize
|
The size of the class in bytes.
|
|
dwParams
|
The list of class criteria fields to consider when selecting the connection. To specify multiple criteria fields, use a bitwise-or to combine multiple ConnMgrParam enumeration values.
|
|
dwFlags
|
The connection request's proxy requirements.
|
|
dwPriority
|
The connection request's priority.
|
|
bExclusive
|
The connection request's exclusivity; a non-zero value indicates that connection cannot be shared with other applications.
|
|
bDisabled
|
The connection request's indicator whether the Connection Manager should establish the connection; a non-zero value indicates that the Connection Manager should determine if the connection is possible but not actually perform the connection. When the Connection Manager reaches the point where it would normally establish the connection, the Connection Manager sets the connections status to ConnMgrStatus.ConnectionDisabled.
|
|
guidDestNet
|
The connection request's destination expressed as a GUID; if this field is valid the dwParams field must contain ConnMgrParam.GuidDestNet.
|
|
hWnd
|
The handle of the window to send status change messages; this will normally be the handle of a MessageWindow-derived class.
|
|
uMsg
|
The message to send to the window identified by the hWnd field when sending status change messages; this field is only valid if the hWnd field is set to a valid window handle.
|
|
lParam
|
A value to include in the status change message sent to the window identified by the hWnd field; this field is only valid if the hWnd field is set to a valid window handle. Use this field to include application-specific data in the status change message.
|
|
ulMaxCost
|
The maximum acceptable cost of the connection; if this field is valid the dwParams field must contain ConnMgrParam.MaxCost (most applications can ignore this field).
|
|
ulMinRcvBw
|
The minimum acceptable reception bandwidth of the connection; if this field is valid the dwParams field must contain ConnMgrParam.MinRcvBw (most applications can ignore this field).
|
|
ulMaxConnLatency
|
The maximum acceptable connection latency expressed in milliseconds; if this field is valid the dwParams field must contain ConnMgrParam.MaxConnLatency (most applications can ignore this field).
|
To simplify working with the ConnMgrConnectionInfo class, the class definition includes a couple of constructors that take care of some common situations. First is the default constructor, which is shown in the following code example.
public ConnMgrConnectionInfo()
{
cbSize = Marshal.SizeOf(typeof(ConnMgrConnectionInfo))
}
Before passing the ConnMgrConnectionInfo class to any of the Connection Manager functions, the size of the class must be stored in the cbSize member so this constructor automatically stores the class size in cbSize as part of the class construction.
Although the ConnMgrConnectionInfo class has several members, applications often need to set only the destination, the priority, and if needed, the proxy; to include the destination in the connection request criteria the dwParams member is set to ConnMgrParam.GuidDestNet. The constructor shown in the following code handles this situation.
public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority, ConnMgrProxy proxy)
: this()
{
guidDestNet = destination;
dwParams = ConnMgrParam.GuidDestNet;
dwPriority = priority;
dwFlags = proxy;
}
For convenience, the class contains two other constructors that represent common situations. The first accepts the destination and priority, and sets the connection criteria to indicate that no proxy is necessary. The second accepts the destination and sets the connection request priority to ConnMgrPriority.UserInteractive, which is the priority of a connection for which the application user interface is waiting.
public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority)
: this(destination, priority, ConnMgrProxy.NoProxy) { }
public ConnMgrConnectionInfo(Guid destination)
: this(destination, ConnMgrPriority.UserInteractive) { }