17

我以前看过这个问题,但我没有看到任何明确的答案,也绝对没有任何答案可以解决我的问题。我创建了一个 Windows 服务来使用 FAXCOMEXLib 库发送传真(半自动)。到目前为止,我的服务已成功发送文本文件 (.txt)。但是当我尝试发送 pdf、jpg 或 tif 文件时,我收到“操作失败”错误。在 SO 中,我看到了很多关于运行服务的用户权限的讨论。我尝试了很多不同的选项(本地服务、本地用户、具有管理员权限的自定义用户、允许服务与桌面交互)。但似乎没有什么不同。该服务似乎无权打开相应的应用程序以“打印”pdf、jpg 或 tif 文件。但我只是推测。有没有人通过 Windows 服务中的 FAXCOMEXLib 成功发送传真?这是我发送传真的代码:

fileName = @"D:\temp\FaxTest.txt"; //THIS WORKS
//fileName = @"D:\temp\FaxTest.pdf"; //Operation failed
//fileName = @"D:\temp\FaxTest.tif"; //Operation failed
faxDoc.Sender.Name = faxRec.From;
faxDoc.Sender.Company = faxRec.From;
faxDoc.Body = fileName;
faxDoc.Subject = faxRec.ReferenceId;
faxDoc.DocumentName = faxRec.ReferenceId;
var to = "xxxxxxxxxx";
faxDoc.Recipients.Add(to, "Some Name");
var serverName = Environment.MachineName;
string[] returnVal = faxDoc.Submit(serverName);

如果您想知道,是的,这些文件确实以这些名称存在于服务器上,并且它们是有效文件(我可以在 Adob​​e Reader 和 Picture Viewer 中打开它们)。如果我在我的开发机器上本地运行它,这也可以正常工作。当然,在发送之前会弹出相应的查看器(在我的本地计算机上)。我的猜测是由于某种原因该服务无法打开查看器。有没有人在 Windows 服务中以这种方式成功发送 PDF?

4

4 回答 4

4

它在MSDN 文章中有很好的记录。需要发生的重要事情是某些软件需要将文件内容转换为可以传真的可打印文本。报价:

可以作为传真正文发送的文档示例包括文本文件 (.txt)、Microsoft Word 文档 (.doc) 或 Microsoft Excel 电子表格 (.xls)。当您从客户端计算机发送传真时,正文必须与安装在该计算机上的应用程序相关联,并且该应用程序必须支持 PrintTo 动词;否则,传真将失败。

因此,您可以做的一项简单测试是右键单击资源管理器中的文件并查找“打印”命令。接下来将文件拖到打印机上以练习 PrintTo 动词。如果这些测试失败,那么它将无法工作,您需要安装一个知道如何打印文件的应用程序。

从服务中执行此操作对执行打印的应用程序提出了额外的要求。其中有很多在服务中表现不佳。尤其是当您尝试打印时,Microsoft 强烈建议您不要在服务中这样做。例如,最近 Office 应用程序不支持,这使得 MSDN 建议已经很弱了。

在我的机器上,.tif 扩展名与 UWP 应用程序相关联,该应用程序也无法在服务中工作。考虑到处理这些流行扩展的大量应用程序,很难给出好的建议,最好去 superuser.com 并命名特定的扩展程序、Windows 版本和您喜欢使用的应用程序。从用户会话中执行此操作肯定是最不麻烦的。

于 2017-10-03T15:59:02.333 回答
3

我想给出一个完整的答案。之前发布的答案有一些解决方案,但它们没有完整地说明我们必须做的所有事情,以通过传真线路成功发送 pdf 文件,在我们的自定义 Windows 服务中使用 FAXCOMEXLib。

我想首先说 FAXCOMEXLib 是为 Windows 控制台应用程序制作的,而不是 Windows 服务。您甚至可以在文档中阅读此内容。我认为这就是为什么我们很难让它发挥作用。

然而,经过多次试验和错误,我们能够(最终)让它工作。我们遇到的大多数问题都与 Adob​​e Reader 中的设置和权限有关。我们发现,在处理 PDf 文件时,Adobe Reader 试图在幕后做很多事情。它试图做的那些“事情”需要用户交互(点击离开警报框等)。在 Windows 服务下运行它时,该服务没有用户交互,这导致我们的进程无限期挂起并最终出错。但是,我们发现有办法解决所有这些问题。以下是我们的做法:

这是我们正在使用的有效代码片段:

fileName = @"D:\temp\FaxTest.pdf";
faxDoc.Sender.Name = faxRec.From;
faxDoc.Sender.Company = faxRec.From;
faxDoc.Body = fileName;
faxDoc.Subject = faxRec.ReferenceId;
faxDoc.DocumentName = faxRec.ReferenceId;
var to = "xxxxxxxxxx";
faxDoc.Recipients.Add(to, "Some Name");
var serverName = Environment.MachineName;
var myProcesses = Process.GetProcessesByName("AcroRd32");
foreach (var myProcess in myProcesses)
{
    if (DateTime.Now.Ticks - myProcess.StartTime.Ticks > TimeSpan.FromSeconds(30).Ticks) {
        myProcess.Kill();
    }
}
string[] returnVal = faxDoc.Submit(serverName);

当然,我们的服务中还有比这更多的代码。其他代码执行诸如处理回调事件处理程序以跟踪发送/完成/失败传真的状态等。但这是实际启动“发送”的代码的“心脏”。

这是我们对服务器所做的配置更改列表,以使我们的自定义 Windows 服务正确解码、呈现和发送 pdf 文件作为传真。其中一些列在一些答案中,但有些没有,我希望这是一个完整的答案。

  1. 以管理员身份登录到服务器并在服务器上安装传真服务器角色。
  2. 确保传真调制解调器设备/卡已正确安装在服务器上,并且传真线路处于活动状态。您可能只是尝试直接从 Windows 传真实用程序发送几个带有文本文件的测试传真。(在我们的例子中,我们遇到了问题,因为我们必须拨“9”和一个秘密密码才能获得外部的长途线路)。
  3. 在服务器上安装 Adob​​e Reader。
  4. 在服务器上为您的 Windows 服务创建一个用户以“作为”运行。我们称我们的用户为“FaxServiceUser”。
  5. 至少以该 FaxServiceUser 身份登录到服务器一次。登录后,将“Adobe PDF”设备设置为默认打印机。
  6. 同样以该用户身份登录时,使用 Adob​​e 打开 PDF 文件并单击 EULA。
  7. 以该用户身份登录并打开 Adob​​e Reader 时,更改以下设置:
    • 如果选中,请取消选中“启动阅读器时显示消息”(在“常规”下)
    • 取消选中“启动时启用保护模式”复选框(这可能仅适用于 Acrobat 10。在 Acrobat 11 中,此选项已移至安全(增强)并标题为启动时启用保护模式。只需确保您取消 -选中此选项)
    • 取消选中“启用增强的安全性”(在“安全性(增强)”下 - 这可能仅适用于 Acrobat 11 及更高版本)
    • 选择更新程序选项并禁用自动下载和安装更新。
    • 取消选中“从 URL 创建链接”(在“常规”下)
    • 取消选中“使手工具阅读文章”(在“常规”下)
    • 取消选中“启动阅读器时显示消息”(在“常规”下)
    • 取消选中“自动计算字段值”(在“表单”下)
    • 取消选中“显示焦点矩形”(在“表单”下)
    • 取消选中“显示文本字段溢出指示器”(在“表单”下)
    • 取消选中“启用 Acrobat JavaScript”(在“Javascript”下)
    • 取消选中“显示欢迎对话框”(在“审查”下)
    • 取消选中“打开文件时显示服务器连接警告对话框”(在“查看”下)
  8. 如果需要,请参阅此链接以获取有关 Adob​​e Reader 设置的帮助:http: //kb.faxback.com/How+To+Configure+Adobe+XI+for+Use+with+NET+SatisFAXtion
  9. 在构建、部署和安装您的 Windows 服务之后,更改您的服务的属性以“作为”您之前创建的用户(在我们的例子中为“FaxServiceUser”)运行。
  10. 将该 FaxServiceUser 的权限添加到它需要读取/写入/删除的任何文件夹。
  11. 由于 Adob​​e 旨在作为桌面应用程序运行,因此在您的服务中添加一些代码以释放 Adob​​e Reader 使用的内存(您可以myProcess.Kill()在示例代码的函数中看到我们是如何做到这一点的)。

那应该这样做。这有点麻烦,但我希望这提供了一个完整的示例,说明如何将 Adob​​e Reader 与您的自定义 Windows 服务一起设置,以从 Windows 服务器上的 pdf 文件发送传真。我们已经做了几个月了,没有任何问题。我们的客户处理的传真量很少,所以我无法说明它是如何处理大量传真的。因此,如果您正在寻找一种“免费”的方式来发送传真,而无需支付 Interfax 之类的费用,这可能是一个可行的选择,至少对于低容量而言是这样。

于 2017-12-04T19:58:43.473 回答
1

该问题似乎与名为 "AcroRd32" 的进程有关,该进程在 Acrobat Reader 中打开传真并在发送之前将其转换为 TIFF 文件。这个进程没有释放内存。

尝试停止该过程如下

Dim myProcesses() As Process Dim myProcess As Process
' How to retrieve the program associat with pdf, when i only know the file extension ?
myProcesses = Process.GetProcessesByName("AcroRd32") For Each myProcess In myProcesses
If Date.Now.Ticks - myProcess.StartTime.Ticks > TimeSpan.FromSeconds(30).Ticks Then
myProcess.Kill()
End If
Next

我希望这是有帮助的。

于 2017-09-30T21:16:58.353 回答
-1

我也想用faxcomexlib通过windows服务发送传真,但研究后发现这个windows库在服务中不可用,我通过进程监视器实现了这一点,因为我决定使用传真服务器。创建一个 .exe 文件并从服务调用它并向它发送所需的参数,然后我在通过 Windows 服务调用进程时遇到了会话问题,然后我解决了这个问题,现在通过 Windows 发送传真服务很容易完毕。

于 2020-08-15T08:36:42.660 回答