c#使用FAXCOMEXLib发送传真的流程以及容易出现的问题
服务运行环境 windows server2019,开发工具VS2022
1. 配置fax服务,勾上图中的选项
2. 项目属性-》添加com引用-》选择Microsoft Fax Service,这里一定要注意,f 开头的两个版本不对,一定要引用M开头的版本
3.发送传真的具体方法
//自定义发送类,并初始化,Connect方法参数传空,表示使用本地连接的传真机器,本项目中连的是传真猫
public FaxSender() { try { faxServer = new FaxServer(); faxServer.Connect(""); RegisterFaxServerEvents(); } catch (Exception ex) { logger.Error(ex, "Error connecting to fax server"); } }
// 注册传真发送事件监听
private void RegisterFaxServerEvents() { faxServer.OnOutgoingJobAdded += new IFaxServerNotify2_OnOutgoingJobAddedEventHandler(faxServer_OnOutgoingJobAdded); faxServer.OnOutgoingJobChanged += new IFaxServerNotify2_OnOutgoingJobChangedEventHandler(faxServer_OnOutgoingJobChanged); faxServer.OnOutgoingJobRemoved += new IFaxServerNotify2_OnOutgoingJobRemovedEventHandler(faxServer_OnOutgoingJobRemoved); var eventsToListen = FAX_SERVER_EVENTS_TYPE_ENUM.fsetFXSSVC_ENDED | FAX_SERVER_EVENTS_TYPE_ENUM.fsetOUT_QUEUE | FAX_SERVER_EVENTS_TYPE_ENUM.fsetOUT_ARCHIVE | FAX_SERVER_EVENTS_TYPE_ENUM.fsetQUEUE_STATE | FAX_SERVER_EVENTS_TYPE_ENUM.fsetACTIVITY | FAX_SERVER_EVENTS_TYPE_ENUM.fsetDEVICE_STATUS; faxServer.ListenToServerEvents(eventsToListen); }
//监听事件触发的自定义处理事件
#region Event Listeners private static void faxServer_OnOutgoingJobAdded(FaxServer pFaxServer, string bstrJobId) { logger.Info("OnOutgoingJobAdded event fired. A fax is added to the outgoing queue."); } private static void faxServer_OnOutgoingJobChanged(FaxServer pFaxServer, string bstrJobId, FaxJobStatus pJobStatus) { logger.Info("OnOutgoingJobChanged event fired. A fax is changed to the outgoing queue."); pFaxServer.Folders.OutgoingQueue.Refresh(); PrintFaxStatus(pJobStatus); } private static void faxServer_OnOutgoingJobRemoved(FaxServer pFaxServer, string bstrJobId) { logger.Info("OnOutgoingJobRemoved event fired. Fax job is removed to outbound queue."); } #endregion private static void PrintFaxStatus(FaxJobStatus faxJobStatus) { if (faxJobStatus.ExtendedStatusCode == FAX_JOB_EXTENDED_STATUS_ENUM.fjesDIALING) { logger.Info("Dialing..."); } if (faxJobStatus.ExtendedStatusCode == FAX_JOB_EXTENDED_STATUS_ENUM.fjesTRANSMITTING) { logger.Info("Sending Fax..."); } if (faxJobStatus.Status == FAX_JOB_STATUS_ENUM.fjsCOMPLETED && faxJobStatus.ExtendedStatusCode == FAX_JOB_EXTENDED_STATUS_ENUM.fjesCALL_COMPLETED) { logger.Info("Fax is sent successfully."); } }
重点来了,发送传真到传真服务器的方法
/// <summary> /// 发送传真的方法 /// </summary> /// <param name="body">是一个要传真的文件路径</param> /// <param name="faxMessage">自定义model,这里用到sender(传真发送方,可空)和recipient(传真接收号码)</param> /// <param name="subject">传真主题,可空</param> /// <param name="docName">文件名,可空</param> public void SendFax(string body, FaxMessage faxMessage, string subject = null, string docName = null) { try { logger.Debug("begin FaxDocumentSetup"); FaxDocumentSetup(subject, docName, body, faxMessage.Sender, faxMessage.Recipient); logger.Debug("end FaxDocumentSetup and begin Submit"); var submitReturnValue = faxDoc.Submit(faxServer.ServerName);//这里返回值应该是传真事件的id,可以用来主动查询传真发送的状态 logger.Debug($"end Submit,submit result:{JsonConvert.SerializeObject(submitReturnValue)}"); faxDoc = null; } catch (Exception comException) { logger.Error(comException, "Error SendFax to fax server. Error Message: " + comException.Message); } } /// <summary> /// 初始化要发送的传真文档 /// </summary> /// <param name="subject"></param> /// <param name="docName"></param> /// <param name="body"></param> /// <param name="sender"></param> /// <param name="recipient"></param> private void FaxDocumentSetup(string subject, string docName, string body, string sender, string recipient) { faxDoc = new FaxDocument { Priority = FAX_PRIORITY_TYPE_ENUM.fptLOW, ReceiptType = FAX_RECEIPT_TYPE_ENUM.frtNONE, AttachFaxToReceipt = true, Body = body, Subject = subject ?? body.Substring(0, 1), DocumentName = docName ?? body.Substring(0, 1) }; faxDoc.Sender.Name = sender; faxDoc.Sender.Company = ""; faxDoc.Recipients.Add(recipient); }
注意,上面FaxDocumentSetup方法中,FaxDocument.Priority有三种,如果使用FAX_PRIORITY_TYPE_ENUM.fptHIGH,且项目以windows service方式运行的话,无法打印pdf文件
会报"System.IO.FileLoadException: Operation failed" "System.UnauthorizedAccessException: Access denied"这两种错误
方法使用:直接FaxSender.SendFax 传参就行
注意!注意!!注意!!!
本项目测试过传真txt文档,tif图片和pdf文档,其中传真pdf文档最麻烦
传真pdf文档需要电脑上安装pdf viewer,别人有推荐Adobe Acrobat Reader和FoxiReader的,楼主两种都试过,FoxiReader中间出了点问题,最后选择了Adobe Acrobat Reader,估计FoxiReader也是没问题的
如果不安装pdf viewer,会报以下错误"System.Runtime.InteropServices.COMException (0x80070102): Operation failed."
总结起来要传真pdf就是安装pdf viewer,并且faxdocument的Priority使用FAX_PRIORITY_TYPE_ENUM.fptLOW,这里权限还有一种fptNORMAL,有兴趣的可以自行尝试
其他的可传真文件类型楼主没有一一尝试,有兴趣的可以自行研究下
传送门:
https://docs.microsoft.com/zh-cn/windows/win32/api/faxcomex/
https://blog.csdn.net/cunchi8090/article/details/107485727
https://www.codeproject.com/Tips/1041737/Work-with-Fax-Using-FAXCOMEXLib?msg=5477440#xx5477440xx