我知道,WinFax专业是如此的1998年。
(注意:这不是WinFax.dll,它显然是Windows的一部分。这是WinFax Pro,这是一个独立的商业附加应用,最初来自Delrina,后来被赛门铁克收购)。
我在一个仍然使用WinFax Pro作为操作系统的办公室工作。他们将客户传真号码存储在WinFax Pro "PhoneBook“中,并使用它通知客户服务访问。现在的工作方式是,有人查看从Mac生成的(打印)计划,然后单击WinFax电话簿中的所有适当条目发送传真。
这就像我们以前称之为“转椅”集成的东西,但它指的是两个屏幕。这甚至不是两个屏幕-它是一张纸和一个屏幕。
不管怎么说,我正试图使它自动化,并且遇到了麻烦。
好消息是:
坏消息是:
我无法在WinFax COM对象上调用除WinFax.SDKSend之外的任何方法。签名看起来并不比WinFax.SDKSend中的签名更复杂,但我总是遇到异常。
C#代码:
public void Run()
{
var pb = new wfxctl32.CSDKPhoneBook();
string id = pb.GetFolderListFirst(1, "");
}例外情况:
异常: System.InvalidCastException:无法将'wfxctl32.CSDKPhoneBookClass‘类型的COM对象转换为接口类型'wfxctl32.ISDKPhoneBook’。此操作失败,因为QueryInterface调用与IID '{A67FCC81-9949-11D0-961E-444553540000}‘接口的COM组件失败:不支持此类接口( HRESULT: 0x80004002 (E_NOINTERFACE)例外)。 at System.RuntimeType.InvokeDispMethod(字符串名称、BindingFlags invokeAttr、对象目标、Object[] args、Boolean[] byrefModifiers、Int32区域性、String[] namedParameters) at System.RuntimeType.InvokeMember(字符串名称、bindingFlags BindingFlags、绑定器、对象目标、Object[] providedArgs、ParameterModifier[]修饰符、CultureInfo文化、String[] namedParams) 在System.RuntimeType.ForwardCallToInvokeMember(String memberName,BindingFlags标志,对象目标,Int32[] aWrapperTypes,MessageData& msgData) 在wfxctl32.CSDKPhoneBookClass.GetFolderListFirst(Int16 standardFolder,String folderID)
发布于 2011-01-25 15:36:30
我打开了Windows的一部分OleView工具,我可以看到对象上没有WinFax.SDKPhoneBook的COM接口。嗯,这是个惊喜。接口由类型库描述,tlbimport.exe为它生成一个包装器。此外,接口记录在WinFax Pro中。但是,我找不到一个成功使用WinFax.SDKPhoneBook早期绑定接口的例子。
当我尝试使用javascript调用COM对象时,它运行得很好。
function say(x){ WScript.Echo(x); }
var Folder = function(id) {
this.Id = id;
this.DisplayName = null;
this.Parent = null;
};
Folder.prototype.GetFolderName = function() {
if (this.DisplayName === null) {
this.DisplayName = comObject.GetFolderDisplayName(this.Id);
}
return (this.Parent === null) ? this.DisplayName
: this.Parent.GetFolderName() + "/" + this.DisplayName;
};
var comObject = new ActiveXObject("WinFax.SDKPhoneBook");
var GetPbFoldersForId = function(firstId) {
// stage 1 - do searches for folders
var list = [];
var id = firstId;
do {
list.push(new Folder(id));
id = comObject.GetFolderListNext();
} while (id != "");
// stage 2 - get subfolders, if any, for each folder
var subs =[];
for (var i=0; i<list.length; i++) {
id = comObject.GetFolderListFirst(0,list[i].Id);
if (id != "") {
var a = GetPbFoldersForId(id); // recurse
for (var j=0; j < a.length; j++) {
if (a[j].Parent === null) {a[j].Parent = list[i];}
subs.push(a[j]);
}
}
}
for (var k=0; k<subs.length; k++) {
list.push(subs[k]);
}
return list; // a list of folders
};
var id = comObject.GetFolderListFirst(1, "");
Folders = GetPbFoldersForId(id);
for (var k=0; k<Folders.length; k++) {
say(Folders[k].GetFolderName());
}这使我得出结论,WinFax Pro COM接口不是双重接口--它们仅限于IDispatch (后期绑定),可以从VB6、VBScript、Javascript、Perl、Python和其他晚绑定语言自然访问,但不能直接从.NET语言(如C#或VB.NET )访问。
C# .NET支持IDispatch后期绑定吗?告诉我如何从C#连接IDispatch接口。用它,我可以做这样的事情:
public sealed class PhoneBook // a singleton
{
Object comObject;
Type type;
private readonly static PhoneBook _instance = new PhoneBook();
public static PhoneBook Instance { get { return _instance; } }
private PhoneBook()
{
var t = Type.GetTypeFromProgID("WinFax.SDKPhoneBook");
if (t == null)
throw new ArgumentException("WinFax Pro is not installed.");
comObject = Activator.CreateInstance(t);
type = comObject.GetType();
}
public string GetUserGroupFirst(int flavor, string id)
{
var parameters = new Object[2];
parameters[0] = flavor;
parameters[1] = id;
string s = type.InvokeMember("GetUserGroupFirst",
BindingFlags.InvokeMethod,
null,
comObject,
parameters) as String;
return s;
}
....PhoneBook类是IDispatch接口上的包装器。我在类型库中为每个方法和属性编写了一个包装器方法。我认为这是.NET 4.0会自动为我做的事情。在任何情况下,这对我来说都很好。
我在这里张贴这个问答,只是为了让其他与WinFax专业人士打交道的人可能有这些信息。我搜遍了所有的内线,找不到任何好的信息,所以我把这个放出来了。
编辑--这段.NET代码现在运行在ASPNET应用程序中,允许用户查找条目并从网页或REST客户端发送传真。
发布于 2011-01-25 15:35:30
我认为它是最坏的解决方案,但是您可以在C++ (甚至VB6)中为Winfax对象编写自己的包装器,让该代码完成实际工作,然后从.Net代码中调用包装器。这样,您就不必太担心如何将COM接口类型转换为.Net兼容类型等等,因此这可能会使它变得更容易一些。
发布于 2011-01-25 15:41:02
我无法帮助您解决您的特殊问题,但请注意,COM互操作仅适用于具有相同"bitness“的com dll,而.NET将默认使用它正在运行的计算机上的本地应用程序(即。它将在64位计算机上生成一个64位应用程序)。
几乎所有的COM dll都是32位,尤其是商业的,所以您必须强制应用程序始终构建32位,方法是将项目设置中的CPU类型从"Any“设置为"32位”。
https://stackoverflow.com/questions/4795287
复制相似问题