I’m adding Windows Mobile Connection Manager support to my .NET Compact Framework 3.5 application.
I need to hide connection errors from the user, I’ve read the MSDN documentation and followed it to letter (as far a I can tell), but they still keep popping up if the GPRS fails to connect.
Here’s my C# code:
This is the managed wrapper for the ConnMgrConnectionInfo structure:
[StructLayout(LayoutKind.Sequential)]
public sealed 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
// Constructors
public ConnMgrConnectionInfo()
{
cbSize = Marshal.SizeOf(typeof(ConnMgrConnectionInfo));
}
public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority, ConnMgrProxy proxy)
: this()
{
guidDestNet = destination;
dwParams = ConnMgrParam.GuidDestNet;
dwPriority = priority;
dwFlags = proxy;
}
public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority)
: this(destination, priority, ConnMgrProxy.NoProxy) { }
public ConnMgrConnectionInfo(Guid destination)
: this(destination, ConnMgrPriority.UserInteractive) { }
}
Together with this are the enums that define the C flags from connmgr.h
[Flags]
public enum ConnMgrParam : int
{
GuidDestNet = 0x1,
MaxCost = 0x2,
MinRcvBw = 0x4,
MaxConnLatency = 0x8
}
[Flags]
public enum ConnMgrProxy : int
{
NoProxy = 0x0,
Http = 0x1,
Wap = 0x2,
Socks4 = 0x4,
Socks5 = 0x8,
SuspendAware = 0x10,
Registered_Home = 0x20,
No_Error_Msgs = 0x40,
WakeOnIncoming = 0x80,
}
public enum ConnMgrPriority
{
UserInteractive = 0x8000,
HighPriorityBackground = 0x0200,
LowPriorityBackground = 0x0008
}
Here is the relevant PInvoke to “Dial” a connection in the connection manager:
[DllImport("CellCore.dll", EntryPoint = "ConnMgrEstablishConnectionSync", SetLastError = true)]
public static extern int ConnMgrEstablishConnectionSync(ConnMgrConnectionInfo connectionInfo, ref IntPtr connectionHandle,
uint dwTimeout, ref ConnMgrStatus dwStatus);
And finally, here is the code that instantiates a ConnMgrConnectionInfo with the correct settings then requests a connection from the connection manager:
const string scDefaultDestinationNetwork = "My ISP";
const uint dwTimeout = 60000;
ConnMgrStatus status = ConnMgrStatus.Unknown;
IntPtr pointerOut = IntPtr.Zero;
int retVal;
if (ConnectionEntry.DestinationNetwork == null)
{
ConnectionEntry.DestinationNetwork = scDefaultDestinationNetwork;
}
Guid destinationNetworkGuid = LookupGUIDforNetwork(ConnectionEntry.DestinationNetwork);
ConnMgrConnectionInfo info = new ConnMgrConnectionInfo(destinationNetworkGuid, ConnMgrPriority.HighPriorityBackground, ConnMgrProxy.No_Error_Msgs);
retVal = Win32PInvokes.ConnMgrEstablishConnectionSync(info, ref pointerOut, dwTimeout, ref status);
if (retVal == 0)
{
ConnectionEntry.Handle = pointerOut;
ConnectionFailures = 0;
}
else
{
ConnectionFailures++;
}
Also, the following registry settings are set to 0 to hide connection success and disconnect messages:
HKEY_CURRENT_USER\ControlPanel\Notifications\{8ddf46e7-56ed-4750-9e58-afc6ce486d03}\Options (0)
HKEY_CURRENT_USER\ControlPanel\Notifications\{8ddf46e8-56ed-4750-9e58-afc6ce486d03}\Options (0)
Now when that code fires, connection errors still pop up over our kiosk style application, allowing the users to hit Settings and get to the underlying OS and it’s settings.
Can anybody see what I’m doing wrong?
Here’s my solution:
Repoint the following registry setting you your own custom exe:
HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\Rai\:MSREMNET\1It defaults to a program called RemNet.exe in \Windows.
If passed the parameter -RASERROR it pops up a balloon.
I wrote my own exe that selectively ignores calls with -RASERROR and passes the rest on to the original RemNet:
I use the DEBUG switch to either build an EXE that tells me whats going on (DEBUG) or just masks ras errors (RELEASE)