使用C#开发纽曼USB来电小秘书客户端小结

在前面用C#开发完CRM的来电弹屏之后,有些客户有了新的要求,他们希望不但能够实现来电弹屏,更希望能够将呼入呼出的电话录音并上传到CRM服务器上,方便日后跟踪记录。于是便有了来电小秘书客户端的开发。 
  来电小秘书客户端的开发是基于纽曼USB来电通客户端的基础上进行开发的,由于纽曼USB来电通的硬件没有录音功能,于是硬件上使用了纽曼的另一个硬件产品来电小秘书,虽然是同一个厂家的产品,可是它们的API却是完全不兼容,更烦的是,来电小秘书API没有来电的回调接口,无法通过回调触发程序,也没有C#的Demo,很多功能只能通过一个不是那么详细的文档和一个Delphi的Demo摸索着做了,经历了一些挫折和困惑,终于完成了这个客户端程序。 
  首先,开发要做的就是与硬件的API进行沟通,依然通过C#的P/Invoke来完成,以下是来电小秘书的P/Invoke代码。 
 

C#代码   收藏代码
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Runtime.InteropServices;  
  5.   
  6. namespace WindowsApplication1  
  7. {  
  8.     class LDT1  
  9.     {  
  10.         [DllImport("usbms.dll", EntryPoint = "LoadDRV")]  
  11.         public static extern int LoadDRV();  
  12.   
  13.         [DllImport("usbms.dll", EntryPoint = "EnableCard")]  
  14.         public static extern int EnableCard();  
  15.   
  16.         [DllImport("usbms.dll", EntryPoint = "StopSigCheck")]  
  17.         public static extern int StopSigCheck(int Handle);  
  18.   
  19.         [DllImport("usbms.dll", EntryPoint = "ReSetUsb")]  
  20.         public static extern int ReSetUsb(int Handle);  
  21.   
  22.         [DllImport("usbms.dll", EntryPoint = "HangUp")]  
  23.         public static extern int HangUp(int Handle);  
  24.   
  25.         [DllImport("usbms.dll", EntryPoint = "InitDtmfBuf")]  
  26.         public static extern int InitDtmfBuf(int Handle);  
  27.   
  28.         [DllImport("usbms.dll", EntryPoint = "SetDialPara")]  
  29.         public static extern int SetDialPara(UInt16 RingBack1, UInt16 RingBack0, UInt16 BusyLen, UInt16 RingTimes, UInt16 SendNoSignalLen);  
  30.   
  31.   
  32.         [DllImport("usbms.dll", EntryPoint = "DisableCard")]  
  33.         public static extern int DisableCard();  
  34.   
  35.         [DllImport("usbms.dll", EntryPoint = "FreeDRV")]  
  36.         public static extern int FreeDRV();  
  37.   
  38.         [DllImport("usbms.dll", EntryPoint = "GetDtmfCode")]  
  39.         public static extern int GetDtmfCode(UInt16 Line);  
  40.   
  41.         [DllImport("usbms.dll", EntryPoint = "IsRing")]  
  42.         public static extern bool IsRing(UInt16 Line);  
  43.   
  44.         [DllImport("usbms.dll", EntryPoint = "GetCallerIDStr")]  
  45.         public static extern UInt16 GetCallerIDStr(UInt16 Line, StringBuilder IDStr);  
  46.   
  47.   
  48.         [DllImport("usbms.dll", EntryPoint = "IsOffHook")]  
  49.         public static extern bool IsOffHook(UInt16 Line);  
  50.   
  51.   
  52.         [DllImport("usbms.dll", EntryPoint = "StartRecordFile")]  
  53.         public static extern bool StartRecordFile(UInt16 Line, string FileName, UInt32 dwRecordLen);  
  54.   
  55.         [DllImport("usbms.dll", EntryPoint = "CheckRecordEnd")]  
  56.         public static extern bool CheckRecordEnd(UInt16 Line);  
  57.   
  58.   
  59.         [DllImport("usbms.dll", EntryPoint = "StopRecordFile")]  
  60.         public static extern bool StopRecordFile(UInt16 Line);  
  61.   
  62.         [DllImport("usbms.dll", EntryPoint = "PCMtoWave")]  
  63.         public static extern int PCMtoWave(string SourceFileName, string TargetFileName);  
  64.   
  65.         [DllImport("usbms.dll", EntryPoint = "ReadCheckResult")]  
  66.         public static extern int ReadCheckResult(int line, int mode);  
  67.   
  68.         [DllImport("usbms.dll", EntryPoint = "StartSigCheck")]  
  69.         public static extern void StartSigCheck(int line);  
  70.   
  71.         [DllImport("usbms.dll", EntryPoint = "ReadUsbState")]  
  72.         public static extern bool ReadUsbState(int line);  
  73.   
  74.         [DllImport("usbms.dll", EntryPoint = "GetRingNum")]  
  75.         public static extern int GetRingNum(int line);  
  76.   
  77.         [DllImport("usbms.dll", EntryPoint = "InitRingNum")]  
  78.         public static extern void InitRingNum(int line);  
  79.   
  80.         [DllImport("usbms.dll", EntryPoint = "ReadSerialNo")]  
  81.         public static extern int ReadSerialNo(int line,StringBuilder serialNo);  
  82.   
  83.     }  
  84. }  
  85.   
  86.     


  然后就是关于设备状态检测了,由于没有API直接支持来电回调,所以只能自己手动的检测设备状态来判断,要实现这一部分一般有两种方式,使用Timer或者使用Thread,Delphi的Demo中使用了Timer,可是Timer实现的弊端需要使用异步的思考方式,不符合我的思维模式,灵活度也不够,而且C#创建线程太方便了,而线程是通过同步方式思考的,所以使用了Thread模式。 
  然后在特定的时刻,记录电话号码、弹屏(如果是来电)、电话结束后录音和上传文件和信息到CRM服务器,其中来电号码可以很容易的获取,可是播出的号码获取就比较的麻烦了,C#中可以使用如下代码: 
 

C#代码   收藏代码
  1. while (LDT1.IsOffHook((ushort)this.line))  
  2. {  
  3.       int temp = LDT1.GetDtmfCode((ushort)this.line);  
  4.        if (temp > 0)  
  5.        {  
  6.              phonenum = phonenum + this.convertInt(temp);  
  7.         }  
  8.        Thread.Sleep(300);  
  9.               
  10.   }  
  11.   
  12. private string convertInt(int code)  
  13.     {  
  14.         string ret="";  
  15.         switch (code)  
  16.         {  
  17.             case 10:  
  18.                 ret = "0";  
  19.                 break;  
  20.             case 11:  
  21.                 ret = "*";  
  22.                 break;  
  23.             case 12:  
  24.                 ret = "#";  
  25.                 break;  
  26.             case 13:  
  27.                 ret = "A";  
  28.                 break;  
  29.             case 14:  
  30.                 ret = "B";  
  31.                 break;  
  32.             case 15:  
  33.                 ret = "C";  
  34.                 break;  
  35.             case 16:  
  36.                 ret = "D";  
  37.                 break;  
  38.             default:  
  39.                 ret = code.ToString();  
  40.                 break;  
  41.         }  
  42.         return ret;  
  43.     }  


  下面说一下C#中的大文件上传吧,网上有很多例子了,我参考了如下blog的代码进行开发http://www.cnblogs.com/bccu/archive/2009/01/05/1363771.html,可是无法上传成功,于是我读了一下代码,发现他将信息中的\r\n用空字符代替了,导致服务器无法识别,于是我更改了他的代码,解决了问题,代码如下: 

C#代码   收藏代码
  1. public static string UploadFileEx(string uploadfile, string url,  
  2.      string fileFormName, string contenttype, NameValueCollection querystring,  
  3.      CookieContainer cookies)  
  4.   {  
  5.       if ((fileFormName == null) ||  
  6.           (fileFormName.Length == 0))  
  7.       {  
  8.           fileFormName = "file";  
  9.       }  
  10.   
  11.       if ((contenttype == null) ||  
  12.           (contenttype.Length == 0))  
  13.       {  
  14.           contenttype = "application/octet-stream";  
  15.       }  
  16.   
  17.   
  18.       string postdata;  
  19.       postdata = "?";  
  20.       if (querystring != null)  
  21.       {  
  22.           foreach (string key in querystring.Keys)  
  23.           {  
  24.               postdata += key + "=" + querystring.Get(key) + "&";  
  25.           }  
  26.       }  
  27.       Uri uri = new Uri(url + postdata);  
  28.   
  29.   
  30.       string boundary = "----------" + DateTime.Now.Ticks.ToString("x");  
  31.       HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);  
  32.       //webrequest.CookieContainer = cookies;  
  33.       webrequest.ContentType = "multipart/form-data; boundary=" + boundary;  
  34.       webrequest.Method = "POST";  
  35.       string huanhang = "\r\n";  
  36.       byte[] huanhangbyte = Encoding.UTF8.GetBytes(huanhang);  
  37.   
  38.       // Build up the post message header     
  39.       StringBuilder sb = new StringBuilder();  
  40.       sb.Append("--");  
  41.       sb.Append(boundary);  
  42.       sb.Append("\r\n");  
  43.       sb.Append("Content-Disposition: form-data; name=\"");  
  44.       sb.Append(fileFormName);  
  45.       sb.Append("\"; filename=\"");  
  46.       sb.Append(Path.GetFileName(uploadfile));  
  47.       sb.Append("\"");  
  48.       sb.Append("\r\n");  
  49.       sb.Append("Content-Type: ");  
  50.       sb.Append(contenttype);  
  51.       sb.Append("\r\n");  
  52.       sb.Append("\r\n");  
  53.   
  54.       string postHeader = sb.ToString();  
  55.       byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);  
  56.   
  57.       // Build the trailing boundary string as a byte array     
  58.       // ensuring the boundary appears on a line by itself     
  59.       byte[] boundaryBytes =  
  60.              Encoding.ASCII.GetBytes("--" + boundary + "");  
  61.   
  62.       FileStream fileStream = new FileStream(uploadfile,  
  63.                                   FileMode.Open, FileAccess.Read);  
  64.       long length = postHeaderBytes.Length + fileStream.Length +  
  65.                                              boundaryBytes.Length + huanhangbyte.Length;  
  66.       webrequest.ContentLength = length;  
  67.   
  68.       Stream requestStream = webrequest.GetRequestStream();  
  69.   
  70.       // Write out our post header     
  71.       requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);  
  72.   
  73.       // Write out the file contents     
  74.       byte[] buffer = new Byte[checked((uint)Math.Min(4096,  
  75.                                (int)fileStream.Length))];  
  76.       int bytesRead = 0;  
  77.       while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)  
  78.           requestStream.Write(buffer, 0, bytesRead);  
  79.       requestStream.Write(huanhangbyte, 0, huanhangbyte.Length);  
  80.       // Write out the trailing boundary     
  81.       requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);  
  82.       fileStream.Dispose();  
  83.       requestStream.Dispose();  
  84.       WebResponse responce = webrequest.GetResponse();  
  85.       Stream s = responce.GetResponseStream();  
  86.       StreamReader sr = new StreamReader(s);  
  87.       string retval=sr.ReadToEnd();  
  88.       sr.Dispose();  
  89.   
  90.       if (File.Exists(uploadfile))  
  91.       {  
  92.           try  
  93.           {  
  94.               File.Delete(uploadfile);  
  95.           }catch(Exception e)  
  96.           {  
  97.           }  
  98.       }  
  99.       return retval;  
  100.   }  


  CRM来电小秘书客户端完成了,当然要配合这个功能,服务器端CRM系统也要做一些修改,不过不是这篇文章的主要内容,关于服务器端的修改的小节,就等下次再说吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DDE(Dynamic Data Exchange)是一种在 Windows 操作系统中使用的进程间通信(IPC)机制。使用DDE,一个应用程序可以向另一个应用程序发送数据或请求数据。在C#中,可以使用System.Windows.Forms命名空间中的DdeClient类来实现DDE客户端。 以下是一个简单的DDE客户端示例,它将连接到Microsoft Excel并获取单元格A1的值: ```csharp using System; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Security.Permissions; namespace DDEClientExample { public partial class Form1 : Form { private const int WM_DDE_ACK = 0x03; private const int WM_DDE_DATA = 0x05; [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { if (m.Msg == WM_DDE_DATA) { // Get the data from the DDE server string data = Marshal.PtrToStringAuto(m.LParam); // Display the data MessageBox.Show(data); } else if (m.Msg == WM_DDE_ACK) { // The DDE server has acknowledged our connection request MessageBox.Show("Connected to DDE server."); } base.WndProc(ref m); } public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // Connect to Microsoft Excel DdeClient ddeClient = new DdeClient("excel", "sheet1"); // Subscribe to the DDE server's events ddeClient.Disconnected += DdeClient_Disconnected; ddeClient.Advise += DdeClient_Advise; // Connect to the DDE server ddeClient.Connect(); // Request data from the DDE server byte[] data = ddeClient.Request("A1"); // Disconnect from the DDE server ddeClient.Disconnect(); } private void DdeClient_Disconnected(object sender, EventArgs e) { MessageBox.Show("Disconnected from DDE server."); } private void DdeClient_Advise(object sender, DdeAdviseEventArgs e) { // Handle DDE advise events here } } } ``` 在此示例中,我们使用 DdeClient 类连接到 Microsoft Excel 的“sheet1”工作表,并使用 Request 方法获取单元格 A1 的值。我们还订阅了 DDE 服务器的 Disconnected 和 Advise 事件。 请注意,DDE 已经过时,Microsoft 建议使用其他通信机制,例如 COM、.NET Remoting 或 WCF。如果可能的话,应该尽量避免使用 DDE。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值