Как отправить факс для PDF из службы Windows с помощью FAXCOMEXLib?

Я видел этот вопрос раньше, но я не видел никаких определенных ответов и, безусловно, не ответил ни на какие ответы, которые решают мою проблему. Я создал службу Windows для отправки факсов (полуавтоматически) с использованием FAXCOMEXLib. До сих пор моя служба успешно отправляла текстовые файлы (.txt). Но когда я пытаюсь отправить файлы pdf, jpg или tif, я получаю сообщение об ошибке "Operation failed". В SO я видел много дискуссий о разрешениях пользователя, которым работает служба. Я пробовал множество разных опций (Local Service, Local User, пользовательский пользователь с правами администратора, позволяющий сервису взаимодействовать с рабочим столом). Но ничто, похоже, не имеет значения. Похоже, что у службы нет разрешений на открытие соответствующего приложения для "печати" файла pdf, jpg или tif. Но я только размышляю. Кто-нибудь успешно отправил факс через FAXCOMEXLib в службе Windows? Вот мой код, который отправляет факс:

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);

Если вам интересно, да, эти файлы существуют на сервере с этими именами, и они являются допустимыми файлами (я могу открыть их в Adobe Reader и Picture Viewer). И это также отлично работает, если я запускаю его локально на своей машине dev. И, конечно, соответствующий зритель появляется перед отправкой (на моей локальной машине). Я предполагаю, что по какой-то причине служба не может открыть зрителя. Кто-нибудь успешно отправил PDF этот путь в службу Windows?

Ответы

Ответ 1

Я хочу дать полный ответ на это. В ранее опубликованных ответах было некоторое решение, но они не дали полной картины всего, что мы должны были сделать, чтобы успешно отправить файл PDF через линию факсов, используя FAXCOMEXLib в нашей пользовательской службе Windows.

Я хочу начать с этого, сказав, что FAXCOMEXLib создан для консольного приложения Windows, а не для службы Windows. Вы даже можете прочитать это в документации. И я думаю, что у нас было так много проблем с работой.

Однако мы смогли заставить его работать (наконец) после долгих проб и ошибок. Большинство проблем, с которыми мы столкнулись, связаны с настройкой и разрешениями в Adobe Reader. Мы обнаружили, что Adobe Reader пытался сделать много вещей за кулисами при обработке файла PDf. И эти "вещи" пытались выполнить требуемое взаимодействие с пользователем (щелкая предупреждениями и т.д.). Когда вы запускаете это под службой 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 файлы в виде факсов. Некоторые из них перечислены в некоторых ответах, но некоторые нет, и я хотел, чтобы это был полный ответ.

  • Войдите в систему как администратор на сервере и установите роль сервера факсов на сервере.
  • Убедитесь, что устройство/карта факсимильного модема правильно установлена ​​на сервере и что линия факса активна. Вы можете просто попробовать отправить пару тестовых факсов с текстовыми файлами непосредственно из утилиты Windows Fax. (В нашем случае мы столкнулись с проблемами, потому что нам пришлось набирать "9" и секретный пароль-код, чтобы получить внешнюю, междугородную линию).
  • Установите Adobe Reader на сервер.
  • Создайте пользователя на сервере, чтобы ваша служба Windows запускала "как". Мы вызвали нашего пользователя "FaxServiceUser".
  • Войдите на сервер как этот FaxServiceUser хотя бы один раз. Во время входа в систему установите устройство "Adobe PDF" в качестве принтера по умолчанию.
  • Также во время входа в систему, как этот пользователь, откройте PDF файл с помощью Adobe и щелкните через EULA.
  • При входе в систему как этот пользователь, и пока вы открываете Adobe Reader, измените эти параметры:
    • Если флажок установлен, снимите флажок "Показывать сообщения при запуске Reader" (в разделе "Общие" ).
    • Отметьте флажок "Включить защищенный режим" при запуске (это может относиться только к Acrobat 10. В Acrobat 11 этот параметр был перенесен в Security (Enhanced) и включен при включении защищенного режима Enable Protected Mode. вы удалите эту опцию)
    • Отмените проверку "Включить расширенную безопасность" (в разделе "Безопасность (Enhanced)" - это может относиться только к Acrobat 11 и выше)
    • Выберите параметр "Обновление" и отключите автоматическую загрузку и установку обновлений.
    • Отмените проверку "Создание ссылок с URL-адресов" (в разделе "Общие" )
    • Отмените проверку "Make Hand tool читать статьи" (в разделе "Общие" )
    • Отмените проверку "Покажите мне сообщения при запуске Reader" (в разделе "Общие" )
    • Отменить проверку "Автоматически вычислять значения полей" (в разделе "Формы" )
    • Отменить проверку "Показать прямоугольники фокуса" (в разделе "Формы" )
    • Отмените проверку "Показать индикатор переполнения текстового поля" (в разделе "Формы" )
    • Отмените проверку "Включить JavaScript Acrobat" (в разделе "Javascript" )
    • Отмените проверку "Показать диалог приветствия" (в разделе "Просмотр" )
    • Отмените проверку "Показывать диалоговое окно предупреждения о подключении сервера при открытии файла" (в разделе "Просмотр" )
  • При необходимости обратитесь к этой ссылке для помощи в настройках Adobe Reader: http://kb.faxback.com/How+To+Configure+Adobe+XI+for+Use+with+NET+SatisFAXtion
  • После создания, развертывания и установки вашей службы Windows измените свойства своей службы, чтобы запустить "как" пользователь, который вы создали ранее ( "FaxServiceUser" в нашем случае).
  • Добавить разрешения для этого FaxServiceUser в любую из папок, которые ему нужно читать/писать/удалять с/на.
  • Поскольку Adobe предназначена для запуска в качестве настольного приложения, добавьте в свою службу код, чтобы освободить память, используемую Adobe Reader (вы можете видеть, как мы это сделали в myProcess.Kill() в примере кода).

И это должно сделать это. Это немного громоздко, но я надеюсь, что это дает полный пример того, как настроить Adobe Reader в сочетании с вашей собственной службой Windows для отправки факсов из pdf файлов на сервере Windows. Мы делали это уже пару месяцев без каких-либо проблем. Наш клиент делает небольшой объем факсов, поэтому я не могу говорить, как это работает с большим объемом факсов. Итак, если вы ищете "бесплатный" способ отправки факсов, не платя за что-то вроде Interfax, это может быть жизнеспособным вариантом, по крайней мере, для малого объема.

Ответ 2

Это хорошо документировано в статье MSDN. Нетривиальная вещь, которая должна произойти, заключается в том, что некоторым программам необходимо преобразовать содержимое файла в печатный текст, который можно отправить по факсу. Цитирование:

Примерами документов, которые вы можете отправить в качестве тела факса, являются текстовый файл (.txt), документ Microsoft Word (.doc) или электронная таблица Microsoft Excel (.xls). Когда вы отправляете факс с клиентского компьютера, тело должно быть связано с приложением, установленным на этом компьютере, и приложение должно поддерживать глагол PrintTo; в противном случае факс будет терпеть неудачу.

Итак, один простой тест, который вы можете сделать, - это щелкнуть правой кнопкой мыши файл в проводнике и найти команду "Печать". Затем перетащите файл на принтер, чтобы использовать глагол PrintTo. Если эти тесты терпят неудачу, то это не сработает, и вам нужно установить приложение, которое знает, как распечатать файл.

Выполнение этого с помощью службы добавляет дополнительные требования к приложению, которое выполняет печать. Многие из них не очень хорошо себя ведут в сервисе. Тем более, что при попытке печати Microsoft настоятельно рекомендует никогда не делать этого в службе. Офисные приложения, например, не относятся к концу, что делает совет MSDN уже слабым соусом.

На моей машине расширение .tif связано с приложением UWP, которое также не будет работать в службе. Предоставление хороших советов трудно, учитывая большое количество приложений, которые обрабатывают эти популярные расширения, лучше всего перейти на superuser.com и назвать конкретное расширение, версию Windows и приложение, которое вы предпочитаете использовать. Выполнение этого из сеанса пользователя, безусловно, является наименее сложным.

Ответ 3

Проблема, похоже, связана с процессом с именем "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

Я надеюсь, что это будет полезно.