السلام عليكم
كثيرا ما تفتح مواضيع متعلقة بالرسائل القصيرة. لذلك سأحاول تخصيص هذا الموضوع لتقديم أكبر حد ممكن من المعلومات المتعلقة بإرسال, قراءة والتصنت لإستقبال الرسائل القصيرة.
إرسال الرسائل القصيرة
SmsOpen ,SmsClose وSmsSendMessage وهي متوفرة في المكتبة sms.dll التي تحتوي العديد من الدوال الأخرى للتصرف في الرسائل القصيرة.
سأبدأ أولا بإستعراض الدوال الأصلية
[DllImport("sms.dll")]
private static extern IntPtr SmsOpen(String ptsMessageProtocol, IntPtr dwMessageModes, ref IntPtr psmshHandle, IntPtr phMessageAvailableEvent);
[DllImport("sms.dll")]
private static extern IntPtr SmsSendMessage(IntPtr smshHandle, IntPtr psmsaSMSCAddress, IntPtr psmsaDestinationAddress, IntPtr pstValidityPeriod, byte[] pbData, IntPtr dwDataSize, byte[] pbProviderSpecificData, IntPtr dwProviderSpecificDataSize, SMS_DATA_ENCODING smsdeDataEncoding, IntPtr dwOptions, IntPtr psmsmidMessageID);
[DllImport("sms.dll")]
private static extern IntPtr SmsClose(IntPtr smshHandle);هذه الدالة الرئيسية لإرسال الرسالة القصيرة وقد قمت بتقسيمها إلى ستة أجزاء:
unsafe public static void SendMessage(string sPhoneNumber, string sMessage) {
IntPtr hSms = IntPtr.Zero;
try {
//======== 1. Open SMS component
IntPtr res = SmsOpen(SMS_MSGTYPE_TEXT, (IntPtr)SMS_MODE_SEND, ref hSms, IntPtr.Zero);
if (res != IntPtr.Zero)
throw new Exception("Could not open SMS.");
//======== 2. Retreive destination phone Nbr
Byte[] bDest = new Byte[516];
fixed (byte* pAddr = bDest) {
byte *pCurrent = pAddr;
Marshal.WriteInt32((IntPtr)pCurrent, (int)AddressType.Unknown);
pCurrent +=4;
foreach (byte b in Encoding.Unicode.GetBytes(sPhoneNumber)) {
Marshal.WriteByte((IntPtr)pCurrent, b);
pCurrent++;
}
//===== 3. Encode Message to be sent
Byte[] ProvData = new Byte[12];
byte[] bMessage = Encoding.Unicode.GetBytes(sMessage);
int nMsgSize = bMessage.Length;
//===== 4. Send SMS
res = SmsSendMessage(hSms, IntPtr.Zero, (IntPtr)pAddr, IntPtr.Zero, bMessage, (IntPtr)nMsgSize, ProvData, (IntPtr)ProvData.Length, SMS_DATA_ENCODING.SMSDE_OPTIMAL, (IntPtr)SMS_OPTION_DELIVERY_NONE, IntPtr.Zero);
//===== 5. Manage exception
if (res != IntPtr.Zero)
throw new Exception("SMS send failed.");
}
}
//====== 6. Close SMS Component
finally {
if (hSms != IntPtr.Zero)
SmsClose(hSms);
}
}1. كخطوة أولى لإرسال الرسائل القصيرة ينبغي فتح الجزء المكلف بذلك في حاسوب الكف/الهاتف الذكي :component . يمكن أن تفشل هذه المرحلة عند عدم توفر البطاقة في الهاتف أو أن المزود للخدمة لا يوفر صلاحية إرسال الرسائل القصيرة
2. في الجزء الثاني يتم قراءة رقم هاتف المرسل إليه وتشفيره : Encoding وفي ذلك تم إستعمال تعليمة خاصة قد تولد مشاكل عند الترجمة
fixed (byte* pAddr = bDest)
لذلك ينبغي تفعيل الإختيارAllow unsafe code في خصائص المشروع كما هو مصور في الصورة التالية:
3. في هذا الجزء من الدالة الرئيسية تتم قراءة نص الرسالة التي نود إرسالها ويتم تحويلها الى بايت
وأخيرا إرسال الرسالة القصيرة وتتبع نجاح العملية دون حدوث إستثناآت. ويبقى لنا غلق الجزء المهتم بهذه الخدمة والذي فتحناه في بداية الدالة
نلاحظ في الصورة الأولى وفي الكود (سي شارب) أني إستعملت رقم الهاتف +14250010001 هذا الرقم يستعمل في المحاكي. أي أرسلت الرسالة من و الى المحاكي.
أو من هذا الرابط
قراءة الرسائل القصيرة
في نفس المكتبة sms.dllتوجد دالة لقراءة الرسائل القصيرة وهي smsReadMessage. هذه الدالة مستعملة بشكل نادر في المشاريع المطورة بالدوت نت وذلك يعود الى صعوبة إستعمالها. وهي مستعملة أكثر في البرمجة باللغة سي (MFC)
private static extern IntPtr SmsReadMessage(IntPtr smshHandle,
long psmsaSMSCAddress,
string psmsaSourceAddress,
long pstReceiveTime,
byte[] pbBuffer,
long dwBufferSize,
long pbProviderSpecificBuffer,
long dwProviderSpecificDataBuffer,
long pdwBytesRead);
[DllImport("sms.dll")]
private static extern IntPtr SmsGetMessageSize(ref IntPtr hSms, ref uint dwMessageSize);
[DllImport("sms.dll")]
private static extern int SmsGetMessageStatus(IntPtr smshHandle, int smsmidMessageID, byte[] psmssiStatusInformation, int dwTimeout);
[DllImport("sms.dll")]
private static extern int SmsGetPhoneNumber(byte[] psmsaAddress);
[DllImport("sms.dll")]
private static extern int SmsGetSMSC(byte[] psmsaSMSCAddress);
[DllImport("sms.dll")]
private static extern int SmsGetTime(byte[] ptsCurrentTime, ref int pdwErrorMargin);
[DllImport("sms.dll")]الحل الثاني لقراءة الرسال القصيرة يكون بإستعمال السي
...<pre class="code" id="ctl00_LibFrame_ctl04" space="preserve"> while (g_fContinue) {
rc = WaitForMultipleObjects (2, hWait, FALSE, INFINITE);
if (!g_fContinue || (rc != WAIT_OBJECT_0))
break;
// Point to the next free entry in the array
pNextMsg = &g_pMsgDB->pMsgs[g_pMsgDB->nMsgCnt];
// Get the message size
hr = SmsGetMessageSize (smshHandle, &dwSize);
if (hr != ERROR_SUCCESS) continue;
// Check for message larger than std buffer
if (dwSize > sizeof (pNextMsg->wcMessage)) {
if (dwSize > MAXMESSAGELEN)
continue;
pIn = bBuffer;
dwInSize = MAXMESSAGELEN;
} else {
pIn = (PBYTE)pNextMsg->wcMessage;
dwInSize = sizeof (pNextMsg->wcMessage);
}
// Set up provider specific data
tpsd.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
tpsd.psMessageClass = PS_MESSAGE_CLASS0;
tpsd.psReplaceOption = PSRO_NONE;
tpsd.dwHeaderDataSize = 0;
// Read the message
hr = SmsReadMessage (smshHandle, NULL, &pNextMsg->smsAddr, &st,
(PBYTE)pIn, dwInSize, (PBYTE)&tpsd,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA),
&dwRead);
if (hr == ERROR_SUCCESS) {
// Convert GMT message time to local time
FILETIME ft, ftLocal;
SystemTimeToFileTime (&st, &ft);
FileTimeToLocalFileTime (&ft, &ftLocal);
FileTimeToSystemTime (&ftLocal, &pNextMsg->stMsg);
// If using alt buffer, copy to std buff
if ((DWORD)pIn == (DWORD)pNextMsg->wcMessage) {
pNextMsg->nSize = (int) dwRead;
} else {
memset (pNextMsg->wcMessage, 0,
sizeof(pNextMsg->wcMessage));
memcpy (pNextMsg->wcMessage, pIn,
sizeof(pNextMsg->wcMessage)-2);
pNextMsg->nSize = sizeof(pNextMsg->wcMessage);
}</pre> ....يمكن أيضا إعتماد هذا المثال
التصنت على الرسائل القصيرة
نعود الآن الى الدوت نت وتحديدا لأجيال ما بعد 2005 من حواسيب الكف والهواتف الذكية حيث تم تجاوز عدة نقائص في الإصدارات السابقة مثال وجود المجال Microsoft.WindowsMobile.PocketOutlook.MessageInterception الذي يوفر إمكانية التصنت على الرسائل القصيرة الواردة على حاسوب الكف/الهاتف الذكي بالكيفية التالية
MessageInterceptor sms ;
void Form1_Load( ... )
{
sms = new MessageInterceptor();
sms.MessageCondition = new MessageCondition(MessageProperty.Body, MessageComparisonType.StartsWith, "Foo" );
sms.InterceptionAction = InterceptionAction.NotifyAndDelete;
sms.MessageReceived += new MessageReceivedEventHandler( sms_MessageReceived );
}و تعرفMessageReceived بالكيفية التالية:
void sms_MessageReceived(object sender, MessageReceivedEventArgs e)
{
SmsMessage message = (SmsMessage)(e.Message);
// ...
}حصلت على كود التصنت على الرسائل القصيرة من هذا الرابط
المواضيع السابقة: الوجه الآخر لهواتف نوكيا , خفايا المكتبة coredll.dll, تنظيف حاسوب الكف لزيادة مساحة الذاكرة
في هذا الكود أهم الدوال المتعلقة بقراءة الرسائل القصيرة, هناك خلل ما في تعريف الدالة SmsReadMessageلذلك من يريد تجربة الكود عليه بمراجعته أولا.