namespace SmartPhone
{
/// <summary>
/// SMS helper class.
/// </summary>
public class SMS
{
public SMS()
{
}
private const string SMS_MSGTYPE_TEXT = "Microsoft Text SMS Protocol";//消息协议模式
private const int SMS_MAX_ADDRESS_LENGTH = 256; // Max length of address
//短消息模式
private const int SMS_MODE_RECEIVE = 1; //以接收模式打开
private const int SMS_MODE_SEND = 2; // 以发送模式打开
private const int SMSAT_INTERNATIONAL = 1; // 国际格式
private const int PS_MESSAGE_OPTION_NONE = 0; // 没有消息选项
//提供商指定消息类型
private const int PS_MESSAGE_CLASS0 = 0; //立即显示但不存储
private const int PS_MESSAGE_CLASS1 = 1; //存储,并在存储后发送一个确认回服务中心
privateconst int PS_MESSAGE_CLASS2 = 2; //在向服务中心发送确认之前,先把消息转移到SIM卡上的短信区域,如果不能存储但还有空间时发送一个未指明的协议错误到服务中心
privateconst int PS_MESSAGE_CLASS3 = 3; //消息到达并可以存储时发送一个确认回服务中心
private const int PSRO_NONE = 0; // 没有替换项
//短信发送选项
private const int SMS_OPTION_DELIVERY_NONE = 0; // 没有发送选项
private const int SMS_OPTION_DELIVERY_NO_RETRY=1; //如果设置了该选项,则不再尝试重发,否则会按预定的时间表重发
//短信编码格式
private enum SMS_DATA_ENCODING
{
SMSDE_OPTIMAL=0, //最佳模式
SMSDE_GSM, //使用默认的GSM 7位编码
SMSDE_UCS2, //使用Unicode UCS2编码
}
[DllImport("sms.dll")]
private static extern int SmsOpen(
string ptsMessageProtocol,
int dwMessageModes,
ref IntPtr psmshHandle,
int phMessageAvailableEvent);
/// <summary>
///
/// </summary>
/// <param name="短信句柄"></param>
/// <param name="短消息服务中心地址,推荐为NULL"></param>
/// <param name="短消息目的地址"></param>
/// <param name="短信的有效期,可以为NULL"></param>
/// <param name="短信的数据部分,可以为NULL"></param>
/// <param name="短信的数据部分大小,可以为0"></param>
/// <param name="短信提供者指定数据"></param>
/// <param name="短信提供者指定数据大小"></param>
/// <param name="短信编码格式"></param>
/// <param name="短信发送选项"></param>
/// <param name="短信标识,如果不为空,则为短信发送成功后返回的ID,可以用于SmsGetMessageStatus"></param>
/// <returns></returns>
[DllImport("sms.dll")]
private static extern int SmsSendMessage(
IntPtr smshHandle,
int psmsaSMSCAddress,
IntPtr psmsaDestinationAddress,
int pstValidityPeriod,
IntPtr pbData,
int dwDataSize,
IntPtr pbProviderSpecificData,
int dwProviderSpecificDataSize,
SMS_DATA_ENCODING smsdeDataEncoding,
int dwOptions,
int psmsmidMessageID);
[DllImport("sms.dll")]
private static extern int SmsClose(IntPtr smshHandle);
[DllImport("coredll.dll")]
private static extern IntPtr LocalAlloc(uint uFlags, uint uBytes);
[DllImport("coredll.dll")]
internal static extern IntPtr LocalFree(IntPtr hMem);
privatestatic IntPtr AllocHGlobal(IntPtr cb)
{
IntPtr hmem;
hmem = LocalAlloc(0x40, (uint) cb);
return hmem;
}
private static void FreeHGlobal(IntPtr hglobal)
{
LocalFree(hglobal);
}
public static int SendSMS(string Number, string Message)
{
int returnValue = 0;
IntPtr smsHandle = IntPtr.Zero;
try
{
if(Number.Substring(0,3)!="+86") //国内手机必须在手机号码前加上+86
Number ="+86"+Number;
// Set address structure
byte[] smsatAddressType = BitConverter.GetBytes(SMSAT_INTERNATIONAL);
byte[] ptsAddress = Encoding.Unicode.GetBytes(Number);
byte[] smsAddressTag = new byte[smsatAddressType.Length + ptsAddress.Length];
Array.Copy(smsatAddressType, 0, smsAddressTag, 0, smsatAddressType.Length);
Array.Copy(ptsAddress, 0, smsAddressTag, smsatAddressType.Length, ptsAddress.Length);
IntPtr smsAddress = AllocHGlobal((IntPtr)smsAddressTag.Length);
Marshal.Copy(smsAddressTag, 0, smsAddress, smsAddressTag.Length);
// Set provider data structure
byte[] dwMessageOptions = BitConverter.GetBytes(PS_MESSAGE_OPTION_NONE);
byte[] psMessageClass = BitConverter.GetBytes(PS_MESSAGE_CLASS1);
byte[] psReplaceOption = BitConverter.GetBytes(PSRO_NONE);
byte[] smsProviderDataTag = new byte[dwMessageOptions.Length +psMessageClass.Length + psReplaceOption.Length];
Array.Copy(dwMessageOptions, 0, smsProviderDataTag, 0, dwMessageOptions.Length);
Array.Copy(psMessageClass, 0, smsProviderDataTag, dwMessageOptions.Length,psMessageClass.Length);
Array.Copy(psReplaceOption, 0, smsProviderDataTag, dwMessageOptions.Length +psMessageClass.Length, psReplaceOption.Length);
IntPtr smsProviderData = AllocHGlobal((IntPtr) smsProviderDataTag.Length);
Marshal.Copy(smsProviderDataTag, 0, smsProviderData, smsProviderDataTag.Length);
// Set message
byte[] smsMessageTag = Encoding.Unicode.GetBytes(Message);
IntPtr smsMessage = AllocHGlobal((IntPtr)smsMessageTag.Length);
Marshal.Copy(smsMessageTag, 0, smsMessage, smsMessageTag.Length);
// Get handle
if (0 != SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, ref smsHandle, 0))
returnValue = -1; // Could not open
// Send message
if (0 != SmsSendMessage(smsHandle, 0, smsAddress, 0,
smsMessage, smsMessageTag.Length,
smsProviderData, smsProviderDataTag.Length,
SMS_DATA_ENCODING.SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE, 0))
returnValue = -2;
FreeHGlobal(smsMessage);
FreeHGlobal(smsProviderData);
FreeHGlobal(smsAddress);
}
finally
{
// Release handle
if (smsHandle != IntPtr.Zero)
{
if (0 != SmsClose(smsHandle))
returnValue = -3; // Could not close
}
}
return returnValue;
}
}
}