How can I send a fax for a pdf from a Windows Service using FAXCOMEXLib?

2k views Asked by At

I've seen this question asked before, but I have not seen any definite answers, and definitely not any answers that solve my problem. I created a windows service to send faxes (semi-automatically) using the FAXCOMEXLib library. So far, my service has been successful at sending text files (.txt). But when I try to send pdf, jpg, or tif files, I get the "Operation failed" error. In SO, I've seen a lot of discussion about the permissions of the user that the service is running under. I've tried a lot of different options (Local Service, Local User, custom user with admin privileges, allow service to interact with desktop). But nothing seems to make a difference. It seems that the service does not have permissions to open the appropriate app to "print" the pdf, jpg, or tif file. But I am only speculating. Has anyone been successful in sending a fax through FAXCOMEXLib in a Windows service? Here is my code that sends the fax:

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

In case you're wondering, yes, those files do exist on the server with those names, and they are valid files (I can open them up in Adobe Reader and Picture Viewer). And this also works just fine if I run this locally on my dev machine. And of course, the appropriate viewer pops up before sending (on my local machine). My guess is that for some reason the service cannot open the viewer. Has anyone been successful sending a PDF this way in a Windows service?

4

There are 4 answers

1
Matt Spinks On BEST ANSWER

I want to give a complete answer to this. The previously posted answers had some of the solution, but they did not give a complete picture of everything we had to do to successfully send a pdf file through a fax line, using FAXCOMEXLib in our custom Windows service.

I want to start this off by saying that FAXCOMEXLib is made for a windows console app, not a windows service. You can even read this in the documentation. And I think that's why we had so much trouble getting it working.

However, we were able to get it to work (finally) after much trial and error. Most of the problems we faced were related to setting and permissions in Adobe Reader. What we found is that Adobe Reader was trying to do a lot of things behind the scenes when processing a PDf file. And those "things" it was trying to do required user interaction (clicking away alert boxes, etc). When running this under a Windows service, there is no user interaction from that service, which caused our process to hang indefinitely and eventually error out. But, we found that there is a way around all that. Here is how we did it:

Here is the snippet of code that we are using that works:

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

There is more code than this in our service, of course. The other code does things like handle callback event handlers to track the status of sending/completed/failed faxes, etc. But this is the "heart" of the code that actually initiates the "send".

And here is a list of configuration changes we made to the server to make our custom Windows service properly decode, render, and send pdf files as faxes. Some of these are listed in some of the answers, but some are not, and I wanted this to be a complete answer.

  1. Log on as admin to the server and install the Fax Server role on the server.
  2. Make sure the fax modem device/card is installed properly on the server, and that the fax line is active. You might just try to send a couple test faxes with text files directly from the Windows Fax utility. (In our case we ran into problems because we had to dial "9" and a secret pass-code to get an outside, long-distance line).
  3. Install Adobe Reader on the server.
  4. Create a user on the server for your Windows service to run "as". We called our user "FaxServiceUser".
  5. Log on to the server as this FaxServiceUser at least once. While logged in, set the "Adobe PDF" device as the default printer.
  6. Also while logged in as this user, open a PDF file using Adobe and click through the EULA's.
  7. While logged in as this user, and while you have Adobe Reader open, change these settings:
    • If checked, un-check "Show me messages when I launch Reader" (Under "General")
    • Un-check the "Enable Protected Mode" at startup check box (This might only apply to Acrobat 10. In Acrobat 11, this option was moved to Security (Enhanced) and is titled Enable Protected Mode at startup. Just make sure you un-check this option)
    • Un-check the "Enable Enhanced Security" (Under "Security(Enhanced)" - this might only apply to Acrobat 11 and higher)
    • Select the Updater option and disable Automatic Download and Install Updates.
    • Un-check "Create links from URLs" (Under "General")
    • Un-check "Make Hand tool read articles" (Under "General")
    • Un-check "Show me messages when I launch Reader" (Under "General")
    • Un-check "Automatically calculate field values" (Under "Forms")
    • Un-check "Show focus rectangles" (Under "Forms")
    • Un-check "Show text field overflow indicator" (Under "Forms")
    • Un-check "Enable Acrobat JavaScript" (Under "Javascript")
    • Un-check "Show welcome dialog" (Under "Reviewing")
    • Un-check "Show server connection warning dialog when opening file" (Under "Reviewing")
  8. If needed, consult this link for assistance with the Adobe Reader settings: http://kb.faxback.com/How+To+Configure+Adobe+XI+for+Use+with+NET+SatisFAXtion
  9. After building, deploying, and installing your Windows service, change the properties of your service to run "as" the user you created earlier ("FaxServiceUser" in our case).
  10. Add permissions for that FaxServiceUser to any of the folders it needs to read/write/delete from/to.
  11. Since Adobe is meant to be run as a desktop app, add some code in your service to release memory used by Adobe Reader (You can see how we did this in the myProcess.Kill() function in the sample code).

And that should do it. It's a little bit cumbersome, but I hope this gives a complete example of how to set up Adobe Reader in conjunction with your custom Windows service to send faxes from pdf files on a Windows server. We've been doing it for a couple months now with no issues. Our client does a low volume of faxes, so I cannot speak to how this works with a high volume of faxes. So, if you are looking for a "free" way to send faxes, without paying for something like Interfax, this could be a viable option, at least for low volume.

3
Nawfel On

The problem appears to be related to the process named "AcroRd32" , which opens the fax in Acrobat Reader and convert it to TIFF file before sending it. This process is not releasing memory.

Try to stop the process as follows

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

I hope this is helpful.

4
Hans Passant On

It is documented pretty well in the MSDN article. The non-trivial thing that needs to happen is that some software needs to convert the file content to printable text that can be faxed. Quoting:

Examples of documents that you can send as a fax body are a text file (.txt), a Microsoft Word document (.doc), or a Microsoft Excel spreadsheet (.xls). When you send a fax from a client computer, the body has to be associated with an application that is installed on that computer, and the application has to support the PrintTo verb; otherwise, the fax will fail.

So one simple test you can do is right-click the file in Explorer and look for the "Print" command. Next drag the file to a printer to exercise the PrintTo verb. If these test fail then it isn't going to work and you need to install an app that knows how to print the file.

Doing this from a service puts extra requirements on the app that does the printing. There are a lot of them that don't behave particularly well in a service. Especially so when you try to print, Microsoft strongly recommends to never do that in a service. Office apps don't for example as of late, making the MSDN advice already weak sauce.

On my machine, the .tif extension is associated with a UWP app, that isn't going to work in a service either. Giving good advice is difficult given the large number of apps that handle these popular extensions, best to go to superuser.com and name the specific extension, Windows version and the app you prefer to use. Doing this from a user session is certainly the least troublesome.

0
Yosef Hajebi On

I also wanted to send a fax through the Windows service using faxcomexlib, but after researching, I realized that this Windows library is not usable in the service, and I realized this using a process monitor, because I decided to use a fax server. To create an .exe file and call it from the service and send the desired arguments to it, then I had a session problem in calling the process through Windows service, then I solved this problem and now sending a fax through Windows The service is easily done.