Receive SMS messages in managed applications)

Source: Internet
Author: User

Http://www.microsoft.com/china/msdn/library/langtool/vsdotnet/ReceivSMSMessages.mspx? MFR = true

Receive SMS messages in managed applications released on: 11/30/2004 | updated on: 11/30/2004

Maarten struys
PTS Software

Applicable:
Microsoft. NET Compact Framework 1.0
Microsoft Visual Studio. NET 2003

Download and receive an SMS example.

Abstract:In
In this article, we illustrate a method to receive SMS messages in a hosted application, while SMS messages do not appear in the inbox and
No pop-up notification is displayed when the message arrives. The sample code runs on the Pocket PC 2003 phone edition device. Only a slight modification is required (mainly in MMI
And it can also run in the smartphone 2003.

Content on this page
Introduction
Example of using and scaling existing mapi rules
Register mailruleclient object with inbox
Cancel mailruleclient object
Communication between client applications and mapi rule clients
Client processing to capture SMS messages
Build sample code
Test sample code
Disadvantages
Summary
About the author

Introduction

Although. NET Compact Framework 1.0 provides very powerful functions, it does not support telephone functions. With P/invoke, you can easily access the phone API and sim api, such as the article "accessing phone APIs from the Microsoft. NET Compact framework"
As described in. For Windows Mobile 2003 software, if the SMS message does not appear in the inbox, there is no direct API
It can be used to immediately process SMS messages received in a hosted application. The SDK Documentation references the imailruleclient interface to process incoming messages in the application. Mapi
The rule client (mapi rule client) is a COM that can implement the imailruleclient interface.
Object. During registration, the inbox application loads the mapi rule client. After registration, the incoming SMS messages are passed to the mapi
The rule client determines how to process the incoming message.

Figure 1-Relationship between inbox and imailruleclient

Smartphone
The 2003 SDK and the Pocket PC 2003 SDK have many sample codes. One example implements a Simple Mail rule client. It is located in the pocket
In the "\ Pocket PC 2003 \ samples \ Win32 \ mapirule" subdirectory of the PC 2003 SDK. After registering a device, this example
The mapi rule client receives all SMS messages and sends them to the inbox (except for messages containing the string "Zzz ). These messages are sent by mapi
The rule client processes the message to display the message and the sender's phone number in MessageBox, and then delete the SMS message.

Back to Top

Example of using and scaling existing mapi rules

Yes
Create your own mapi rule client. The mapirule example is a great entry point. If you can
You can create an interface between the example and the Managed Application to easily access SMS messages from the Managed Application. Because the mapirule example contains receiving SMS
The complete function of deleting a message after processing the message, so the only thing we need to do is to remove the SMS message from mapirule
The example is passed to the managed application. To this end, you can use a few simple local functions to expand the mapirule client example, so that the SMS
The message is sent to the calling client. For this purpose, the downloadable source code included in this article contains a modified version of the mapirule example. In mapirule
In the sample code, you need to modify the method cmailruleclient: processmessage. This method is the core of the mapi rule client, which receives SMS
Messages are processed or transmitted to the inbox. The following code snippet shows the original processmessage method in mapirule. cpp.

HRESULT CMailRuleClient::ProcessMessage(IMsgStore *pMsgStore,
ULONG cbMsg,
LPENTRYID lpMsg,
ULONG cbDestFolder,
LPENTRYID lpDestFolder,
ULONG *pulEventType,
MRCHANDLED *pHandled)
{
HRESULT hr = S_OK;
SizedSPropTagArray(1, sptaSubject) = { 1, PR_SUBJECT};
SizedSPropTagArray(1, sptaEmail) = { 1, PR_SENDER_EMAIL_ADDRESS};
ULONG cValues = 0;
SPropValue *pspvSubject = NULL;
SPropValue *pspvEmail = NULL;
IMessage *pMsg = NULL;
HRESULT hrRet = S_OK;
// Get the message from the entry ID
hr = pMsgStore->OpenEntry(cbMsg,
lpMsg,
NULL,
0,
NULL,
(LPUNKNOWN *) &pMsg);
if (FAILED(hr)) {
RETAILMSG(TRUE, (TEXT("Unable to get the message!\r\n")));
goto Exit;
}

// For SMS, the subject is also the message body
hr = pMsg->GetProps((SPropTagArray *) &sptaSubject,
MAPI_UNICODE,
&cValues,
&pspvSubject);
if (FAILED(hr)) {
RETAILMSG(TRUE, (TEXT("Unable to get the message body!\r\n")));
goto Exit;
}
// get the sender's address or phone number
hr = pMsg->GetProps((SPropTagArray *) &sptaEmail,
MAPI_UNICODE,
&cValues,
&pspvEmail);
if (FAILED(hr)) {
RETAILMSG(TRUE, (TEXT("Couldn't get the sender's address!\r\n")));
goto Exit;
}
//
// ***** START REPLACE WITH CODE FROM LISTING 2 *****
//
// Here we filter the message on some predetermined string.
// For sample purposes here we use "zzz". What happens when the
// filter condition(s) are met is up to you. You can send
// WM_COPYDATA messages to other app windows for light IPC,
// send an SMS message in response, or whatever you need to do.
// Here, we just play a sound and show the message in a
// standard message box.
if (wcsstr(pspvSubject->Value.lpszW, L"zzz") != NULL)
{
MessageBeep(MB_ICONASTERISK);
MessageBox(NULL,
pspvSubject->Value.lpszW,
pspvEmail->Value.lpszW,
MB_OK);

// Delete the message and mark it as handled
// so it won't show up in Inbox
hr = DeleteMessage(pMsgStore,
pMsg,
cbMsg,
lpMsg,
cbDestFolder,
lpDestFolder, pulEventType, pHandled);
} else {
// a 'normal' message, pass it on
*pHandled = MRC_NOT_HANDLED;
}
//
// ***** END REPLACE CODE *****
//
// Clean up
Exit:
if (pspvEmail) {
MAPIFreeBuffer(pspvEmail);
}
if (pspvSubject) {
MAPIFreeBuffer(pspvSubject);
}
if (pMsg) {
pMsg->Release();
}

return hr;
}

Listing 1: Sample Code of the original cmailruleclient: processmessage.

Explanation per
Function calls and processmessage internal working principle is beyond the scope of this article, but the reader needs to understand the key point: as long as the SMS is received
Message, the inbox application calls processmessage using the message entry, which contains all the information of received SMS messages. In
All methods called in processmessage are attached to the Pocket PC 2003 SDK
The Help file is described in detail. Use the following code snippet to replace the highlighted lines of code and replace all received SMS messages containing the special prefix (zzz)
The message is sent to the client application. We can modify the example.

The code displayed in the following code snippet replaces the Code marked in Listing 1.

// Here we filter the message on some predetermined string. For sample 
// purposes here we use "zzz". What happens when the filter condition(s)
// are met is up to you. You can send WM_COPYDATA messages to other
// app windows for light IPC, send an SMS message in response,
// or whatever you need to do.
if (wcsstr(pspvSubject->Value.lpszW, L"zzz") != NULL)
{
if (g_hSmsAvailableEvent != NULL)
{
// We have received an SMS message that needs to be send to our client.
// Since we run in the process space of Inbox, we are using a memory
// mapped file to pass the message and phone number to our client,
// that typically runs in another process space (therefor we can not
// simply copy strings). We protect the memory mapped file with a Mutex
// to make sure that we are not writing new SMS data while the reading
// client is still processing a previous SMS message.
WaitForSingleObject(g_hMutex, INFINITE);
lstrcpy(g_pSmsBuffer->g_szPhoneNr, pspvEmail->Value.lpszW);
lstrcpy(g_pSmsBuffer->g_szMessageBody, pspvSubject->Value.lpszW);
ReleaseMutex(g_hMutex);
SetEvent(g_hSmsAvailableEvent);
}

// Delete the message and mark it as handled so it won't show up in Inbox
hr = DeleteMessage(pMsgStore,
pMsg,
cbMsg,
lpMsg,
cbDestFolder,
lpDestFolder, pulEventType, pHandled);
}
else
{
// a 'normal' message, pass it on
*pHandled = MRC_NOT_HANDLED;
}

Listing 2: The Replacement code for passing all the SMS messages to the client process.

Back to Top

Register mailruleclient object with inbox

In
Before we can use the mapi rule client, we need to register it as com
Object, and add its Class Identifier to the following registry key: hkey_classes_root \ CLSID \. To make the inbox aware of mapi
If the rule client exists, we must also write its Class Identifier to the following registry key:
HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ inbox \ SVC \ SMS \ rules.

To set the two
Registry Key to fully register our COM object so that it can be used. The mapirule example contains the Function
Dllregisterserver. You can use the mapi
Any client application of the rule client calls this function. Because this article will use the hosted client application, we use P/invoke in the hosted application to call the function.
Dllregisterserver. After this function is executed, all received SMS messages are routed through the mapi rule client.
. In the sample code provided in this article, we will pass all received SMS messages containing "Zzz" to the client process, but we can filter out specific
SMS messages (for example, filtering by phone number or specific message content, or simply passing all messages ).

Back to Top

Cancel mailruleclient object

In
After the client application completes the capture of the SMS message, log out of the mapi
The rule client (at least) is equally important as registering this object. If this step is ignored, the SMS message will not appear in the inbox after we have completed our own application. To log out of mapi
The rule client calls the dllunregisterserver function. This function will delete the call function dllregisterserver
The registry key. In a hosted client application, you can use P/invoke
Complete this task. Because the inbox does not dynamically receive notifications of changes in the Registry, the device must also be soft-reset. See the "disadvantages" section at the end of this article.

Back to Top

Communication between client applications and mapi rule clients

Create
Establish Client Applications and mapis
There are several communication methods between Rule clients (in the process space running in the inbox. In addition to the communication mechanism, implementing the inter-process communication that we are discussing here is also very important. This is immediately confirmed.
Because each Windows CE process has its own memory space, it is impossible to simply pass the memory pointer from one process to another. In order
The message content is transmitted to the client application. We need to use the memory ing file. Mapi
The rule client creates a memory ing file in the constructor and destroys it in the destructor. In addition, you must create an event to indicate that the SMS message can be used in client applications.

CMailRuleClient::CMailRuleClient()
{
m_cRef = 1;
// Setup a memory mapped file so we can pass SMS messages between this
// server and a listening client.
g_hMMObj = CreateFileMapping((HANDLE)-1,
NULL,
PAGE_READWRITE,
0,
MMBUFSIZE,
TEXT("SmsBuffer"));
assert(g_hMMObj != NULL);
g_pSmsBuffer = (PSMS_BUFFER)MapViewOfFile(g_hMMObj,
FILE_MAP_WRITE, 0, 0, 0);
if (g_pSmsBuffer == NULL) {
CloseHandle(g_hMMObj);
}
assert(g_pSmsBuffer != NULL);
// Create an event to inform the client about a pending SMS message
g_hSmsAvailableEvent = CreateEvent(NULL,
FALSE,
FALSE,
_T("SMSAvailableEvent"));
assert(g_hSmsAvailableEvent != NULL);
}

Listing 3: create a resource to communicate with the client.

It is also important to understand that all handles are local handles for individual processes. Example
For example, the smsavailableevent handle cannot be shared between the mapi rule client and the client application, even if some parts of the client application are in the host
The same is true in the DLL of the mapi rule client function.

Back to Top

Client processing to capture SMS messages

To capture all sent SMS messages in a hosted application, we need to create a secondary thread in the Managed Application (only one native function of P/invokes waiting for the event to be set. The mechanism for asynchronous callback to managed code is titled"Asynchronous callbacks from Native WIN32 codeThis msdn article has a detailed description.

When
Cmailruleclient: processmessage receives an SMS
When a message is sent, it copies the message content to the memory ing file and sets an event to wait for the thread to change to an active thread. We use a memory ing file to transmit data between two independent processes. Once
Once this event is set, the message content is replicated to the managed data type again. Then, the managed application can process received messages. After the managed auxiliary thread completes processing, it will call back the local function to wait for another
An SMS message becomes available. Because we can only process one SMS message at a time, this example is simplified immediately. To ensure that both received SMS messages are correctly processed
Message, we must implement a certain type of queuing mechanism. To make the example simple and easy to understand, we decided to ignore
Message Queue content. However, the example provided is an excellent starting point for capturing SMS messages, and you can simply modify it to process the SMS messages received at the same time.

The following functions are included in the mapi rule client DLL. This function is blocked before another SMS message is available. Then, this function passes the SMS message content to the managed application that can further process these messages.

//////////////////////////////////////////////////////////////////////////////
// SMSMessageAvailable is used to pass data to the caller, whenever the
// worker thread has data available.
//
// SMSMessageAvailable can be called from unmanaged code or via P/Invoke
// from managed code.
//////////////////////////////////////////////////////////////////////////////
EXTERN_C BOOL SMSMessageAvailable (wchar_t *lpDestination, wchar_t *lpPhoneNr)
{
WaitForSingleObject(g_hClientEvent, INFINITE);
if (g_pClientSmsBuffer != NULL) {
WaitForSingleObject(g_hClientMutex, INFINITE);
lstrcpy(lpPhoneNr, g_pClientSmsBuffer->g_szPhoneNr);
lstrcpy(lpDestination, g_pClientSmsBuffer->g_szMessageBody);
ReleaseMutex(g_hClientMutex);
} else {
*lpPhoneNr = '\0';
*lpDestination = '\0';
}
return *lpPhoneNr != '\0';
}

Listing 4: client applications waiting for SMS messages in the mapi rule client DLL.

Managed Client application
Create an auxiliary thread in sequence, which can be registered as a simple method to receive SMS messages and input a while loop. In the while loop
The smsmessageavailable function exists in the Local Code and is included in the mapi rule client DLL. In this simple example, the received SMS
The message is displayed in the list box of the host form. The following code snippet is displayed.CapturesmsThe hosting auxiliary thread in the client application.

/// <summary>
/// This is the worker thread of the SMSListener class. After construction
/// of the object this class runs continuously, until SMSListener is disposed.
/// The worker thread P/Invokes into unmanaged code to SMSMessageAvailable.
/// Inside this function, execution is blocked until new (asynchronous) data
/// (an SMS message) is available. If data is it is simply passed to a
/// listbox, using Control.Invoke.
/// </summary>
private void CheckForData()
{
StringBuilder sbSms = new StringBuilder(255);
StringBuilder sbPhoneNr = new StringBuilder(255);
UnmanagedAPI.SMSMessageAvailable();
while (! bDone)
{
// P/Invoke into a native function that actually blocks until an
// SMS message is available
if (UnmanagedAPI.GetSMSData(sbSms, sbPhoneNr)
{
MessageBox.Show(sbSms.ToString(), sbPhoneNr.ToString());
if (sbSms.Length != 0)
{
parentForm.ReceivedSMSMessage = sbPhoneNr.ToString() +
" - " + sbSms.ToString();
parentForm.Invoke(new EventHandler(parentForm.UpdateListBox));
}
}
}
}

Listing 5: managed auxiliary threads that receive SMS messages.

There is a special thing to note in this auxiliary thread. When
When an SMS message is sent, the auxiliary thread must
The message is displayed in the list box. An unexpected problem may occur when the control is updated inside the thread with a specific control. Therefore, the auxiliary thread should never directly update the user interface control. Instead, it
Use the form invoke method to pass a delegate so that the thread with the form represents the auxiliary thread to update the UI control.

Back to Top

Build sample code

The provided sample code consists of two independent projects.MapiruleThe project contains all the local code, including the mapi rule client plug-in for the inbox that captures SMS messages. This project must be built using Embedded Visual C ++ 4.0 (which can be downloaded for free. Because the local code is specific to the processor, make sure that the correct platform is compiled.Mapirule.CapturesmsThe project contains only managed code. To be able to buildCapturesmsYou must use Visual Studio. NET 2003. Because the managed code is irrelevant to the processor, you do not need to specify a specific processor type when building the msclient. However, to ensure that the mapirule client DLL andCapturesmsFor deployment together, we use solution Resource Manager in Visual Studio. NET 2003 to add mapirule. DLLCapturesms. Because we now add processor-related code to a solution unrelated to the processor, you must specify the target processor on which the sample code will run.

Back to Top

Test sample code

After successfully buildingMapiruleAndCapturesms
There are two different ways to test the application. First, deploy the application to the actual Smartphone 2003 device or pocketpc.
On the 2003 phone edition device, use another mobile phone
The message is sent to the target device. This test should be executed before the application is released. In the initial stage of development, there is a simple and low-cost method to test the code. Just select a virtual
The simulator supported by the radio can be used as the target system. To send SMS messages to the simulator target, you can useCall eventsIndependent applications. The sample code of this application can be in the title of"Creating call events in an emulation EnvironmentIn this article. StartCall eventsApplication, you can use this application to send SMS messages from the desktop to a Windows Mobile simulator. Make sure that you use a simulator with a virtual radio as the target of the smsclient client application. StartCapturesmsAfter the application, you can useCall eventsSend an SMS message to it. Figure 2 shows the managed applications andCall eventsApplication.

Figure 2-send an SMS message to the pocketpc 2003 phone edition Simulator

Back to Top

Disadvantages

Mapirule
The document in the example shows how to uninstall mapirule. dll.
The device must be soft-reset. This may be related to the fact that a specific registry entry has a read-only attribute during device initialization. Install mapirule. dll
The problem also exists. As long as no SMS is received before mapirule. dll is installed
Message, the sample application described in this article will run well. However, if you have received the SMS
Message, before the device is soft reset, The mapirule ClientNoCapture SMS messages.

Back to Top

Summary

Enable
With the provided code example, you can easily capture and process SMS messages in client applications (even if client applications are written in managed code ). When. net
When Compact Framework Version 2 is released, it may be easier to process SMS messages in applications. However, with this example, you do not have to wait until v2
You can use SMS to publish messages. Use SMS in enterprise applications
Messages are quite interesting. For example, the following method can be used to maintain the inventory list: define a specific message protocol so that applications on mobile devices can
Message. This solution is beyond the scope of this article, but the sample code provided is to host the SMS in the application on the smart device
A good starting point for combining messaging and phone functions.

Back to Top

About the author

Maarten
Struys is public at PTS software and is responsible for real-time and embedded capability center work. Maarten is an experienced windows (CE)
The developer has been working on Windows CE since its appearance. Maarten has been in. Net since 2000.
Use managed code in the environment. He is also a freelance writer from two authoritative journals in the field of embedded system development in the Netherlands. He recently opened a web site to provide
. Net Information, website: www.dotnetfordevices.com. Maarten
Combining managed code and unmanaged code with Windows CE. Net 4.1, professionally evaluated. NET Compact framework
. The white paper on this topic won the winhec 2003 whitepaper award issued by Microsoft earlier this year.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.