I know, WinFax Pro is so 1998.
(note: this is not WinFax.dll, which is apparently part of Windows. This is WinFax Pro, a separate commercial add-on app originally from Delrina, and later acquired by Symantec).
I'm working in an office that still uses WinFax Pro as an operational system. They have customer fax numbers stored in the WinFax Pro "PhoneBook", and use it to notify customers of service visits. The way it works now is, someone looks at the (printed) schedule, generated from a Mac Calendar, then clicks on all the appropriate entries in the WinFax phonebook, to send a notification fax.
This is like something We used to call "swivel chair" integration, but that referred to 2 screens. This isn't even 2 screens - it's one sheet of paper and one screen.
Anyway I'm trying to automate it and having trouble.
The good news:
- WinFax Pro exposes its functions as COM objects: WinFax.SDKSend for the fax sxending engine; WinFax.SDKPhoneBook for the address book, and so on.
- WinFax Pro ships a type library, wfxctl32.tlb, that describes these various COM objects.
- I am able to successfully use the WinFax.SDKSend object from .NET (C#), via wrappers generated from tlbimport. (I'm using .NET 3.5, can't do .NET 4.0) .
The bad news:
I haven't been able to invoke any of the methods on WinFax COM objects other than WinFax.SDKSend. The signatures don't look any more complicated than those in WinFax.SDKSend, but I keep getting exceptions.
The C# code:
public void Run()
{
var pb = new wfxctl32.CSDKPhoneBook();
string id = pb.GetFolderListFirst(1, "");
}
The exception:
Exception: System.InvalidCastException: Unable to cast COM object of type 'wfxctl32.CSDKPhoneBookClass' to interface type 'wfxctl32.ISDKPhoneBook'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{A67FCC81-9949-11D0-961E-444553540000}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at wfxctl32.CSDKPhoneBookClass.GetFolderListFirst(Int16 standardFolder, String folderID)
I opened up the OleView tool, part of the Windows SDK, and I can see that the COM interface for the WinFax.SDKPhoneBook is not present on the object. Hmm, that is a surprise. The interface is described by the type library, and tlbimport.exe generates a wrapper for it. Also the interface is documented in the WinFax Pro SDK PDF doc. But I could not find a single example of anyone successfully using the early-bound interface for WinFax.SDKPhoneBook.
When I tried this with javascript calling into the COM object, it worked just fine.
That led me to conclude that the WinFax Pro COM interfaces are not dual interfaces - they are IDispatch (late bound) only, and are accessible naturally from VB6, VBScript, Javascript, Perl, Python, and other late-bound languages, but not directly from .NET languages like C# or VB.NET.
Does C# .NET support IDispatch late binding? tells me how to connect with IDispatch interfaces from C#. Using that, I can do something like this:
The PhoneBook class is a wrapper on the IDispatch interface. I wrote one wrapper method for each method and property in the typelib. I think this is kinda what .NET 4.0 would do automagically for me. In any case, this worked well for me.
I'm posting this Q&A here only so that other people who deal with WinFax Pro might have the information. I searched all over the intertubes and couldn't find any good information, so I'm putting this out there.
EDIT - this .NET code is now running in an ASPNET MVC app, allowing users to lookup entries and send faxes from a web page or a REST client.