Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

Using FAXCOMEXLib to send a fax in .Net 2005, version 2.0, with a Windows XP computer

Published:
I finally figured out a combination of things that allow the Microsoft Fax Service COM Type Library to work in ASP.NET.  I just kept trying different things, and finally got it.  If you're having this problem, try the following:

Be sure you have a PDF viewer installed on the computer, for all PDF, FDF types.  You can use FoxIT reader, which is free, or Adobe Acrobat, which is also free.   I personally got it working with Foxit.

You need the Interop library as a reference in your program.  Go to "Add a Reference" to your program, choose the "COM" tab, then look for the following: "Microsoft Fax Service Extended COM Type Library".  It is listed under M for Microsoft, not under F for faxing.  The other library under F is WRONG--do not use this.

Be sure to log on as an administrator account.  We use a domain where I work, and the Domain Admin did NOT work.  The local administrator account seemed to be the only thing I could get to work, no matter what permissions I changed on the fax printer, the directories in question, etc.

I declared by fax server once, as a part of the class.  See below:

   
    public class NightlyInvoiceCreditFaxWorkerProgram
    {
        private FAXCOMEXLib.FaxServer _faxServer = new FaxServerClass();
        public FAXCOMEXLib.FaxServer faxSrv
        {
            get
            { return _faxServer; }
            set
            { _faxServer = value; }
        } 
       

Open in new window


Then I used code like this, to access:
 
       
       NightlyInvoiceCreditFaxWorkerProgram nws = new NightlyInvoiceCreditFaxWorkerProgram();
            try
            {
                nws.faxSrv = new FaxServerClass(); 

                nws.faxSrv.Connect(""); 
        

Open in new window


Because I wrote this into a Windows service, I wrote many events to the Windows event log to see where I was hanging up.  This is a big part of the programming, so you know what's going on.

Then I used this code to listen for events:

         
                nws.faxSrv.ListenToServerEvents(FAXCOMEXLib.FAX_SERVER_EVENTS_TYPE_ENUM.fsetOUT_QUEUE); 
                nws.faxSrv.OnOutgoingJobAdded += new FAXCOMEXLib.IFaxServerNotify_OnOutgoingJobAddedEventHandler(faxSrv_OnOutgoingJobAdded);
                nws.faxSrv.OnOutgoingJobChanged += new FAXCOMEXLib.IFaxServerNotify_OnOutgoingJobChangedEventHandler(faxSrv_OnOutgoingJobChanged);
                nws.faxSrv.OnOutgoingJobRemoved += new FAXCOMEXLib.IFaxServerNotify_OnOutgoingJobRemovedEventHandler(faxSrv_OnOutgoingJobRemoved); 
          

Open in new window


I used the code below for each item I needed to fax, since I send many items at once as a part of a nightly faxing routine:

       
        try {
         FaxDocument faxDoc = new FaxDocumentClass();
         faxDoc.Priority = FAX_PRIORITY_TYPE_ENUM.fptHIGH;
         faxDoc.ReceiptType = FAX_RECEIPT_TYPE_ENUM.frtNONE; 

        //THIS CODE IS TO MAKE SURE THE FILE IS NOT IN USE WHEN WE TRY TO ATTACH AND THEN SEND
        ReadFile:
            FileStream fs = null;
            try
            {
                fs = File.OpenRead(attachmentPath); 
            }
            catch (IOException)
            {
                InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "Waiting for file to clear", EventLogEntryType.Information, 3);
                goto ReadFile;
            }
            finally
            {
                InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "File finally clear", EventLogEntryType.Information, 3);
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
            } 
            faxDoc.Body = attachmentPath;
            faxDoc.Subject = thisItem.InvoiceNumber; 
            faxDoc.DocumentName = thisItem.RecipientName + " - Invoice: " + thisItem.InvoiceNumber; 
            faxDoc.Recipients.Add(thisItem.FaxNumber, thisItem.RecipientName); 
            object garb = faxDoc.Submit(faxSrv.ServerName); 
            InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "Successful Fax Send!!", EventLogEntryType.Information, 10); 
            returnString = "Send Success for Item ID: " + thisItem.ID.ToString() + " for: " + thisItem.RecipientName + "  " + thisItem.InvoiceNumber + " "; 
            faxDoc = null;
            
        }catch (System.Runtime.InteropServices.COMException ce)
            { 
                InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "Error connecting to fax server.  Error Message: " + ce.Message + " " + ce.StackTrace, EventLogEntryType.Information, 5);
            }
        

Open in new window


And, finally the event handlers for the fax server:

       
        private static void faxSrv_OnOutgoingJobRemoved(FAXCOMEXLib.FaxServer pFaxServer, string bstrJobId)
        {
            InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "Job Removed to outbound queue.", EventLogEntryType.Information, 4);
        } 
        private static void faxSrv_OnOutgoingJobChanged(FAXCOMEXLib.FaxServer pFaxServer, string bstrJobId, FAXCOMEXLib.FaxJobStatus pJobStatus)
        {
            InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "There was a fax changed to the outgoing queue.  WAITING UNTIL FINISHED SENDING", EventLogEntryType.Information, 4); 
            while (pJobStatus.Status != FAXCOMEXLib.FAX_JOB_STATUS_ENUM.fjsCOMPLETED)
            {
                //loop until this job is completed, then go back to the program
            }
        } 
        
        private static void faxSrv_OnOutgoingJobAdded(FAXCOMEXLib.FaxServer pFaxServer, string bstrJobId)
        {
            InvoiceCreditFaxServiceExVersion.WriteEventToWindowsLog("InvoiceCreditFaxAndEmailServiceExVersion", "There was a fax added to the outgoing queue.", EventLogEntryType.Information, 4);
        }
        

Open in new window


The class I used was:

using FAXCOMEXLib;

Open in new window


This seems to work perfectly--it queues up the items into the Windows Fax Viewer, which then takes care of all the rest of the stuff.  If you have any specific questions about this process feel free to let me know.  I'm glad I was able to figure it out (finally), as the documentation online is terrible for this type of thing.

Compatibility is only verified in Windows XP--I didn't try with Vista or 7.
2
10,540 Views

Comments (2)

Mark WillsTopic Advisor
CERTIFIED EXPERT
Distinguished Expert 2018

Commented:
Thanks, good handy article, will keep this around...

Author

Commented:
By the way - I programmed this into a Windows Service so that it would "always run" and just set a timer for every 10 minutes to check and see if there is anything new to fax out.  The service itself checks a database table that is updated when a user wants to send a fax out.  If there is anything in status 0, my program sends the items using the code above and then sets the status on them to "1" in the database table.  

As far as I know, this code would work in a Windows Application as well.  In a Windows Application, errors and stuff would be much more visible as well, with no need to write events out to the Windows Log.  If anyone needs any more specific information on this, feel free to contact me via EE.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.

Get access with a 7-day free trial.
You Belong in the World's Smartest IT Community