Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从.NET应用程序使用WinFax Pro COM对象?_C#_.net_Com_Interop_Winfax - Fatal编程技术网

C# 如何从.NET应用程序使用WinFax Pro COM对象?

C# 如何从.NET应用程序使用WinFax Pro COM对象?,c#,.net,com,interop,winfax,C#,.net,Com,Interop,Winfax,我知道,WinFax Pro是1998年的事 (注意:这不是WinFax.dll,它显然是Windows的一部分。这是WinFax Pro,一个独立的商业附加应用程序,最初来自Delrina,后来被Symantec收购) 我现在的办公室仍然使用WinFax Pro作为操作系统。他们将客户传真号码存储在WinFax Pro“电话簿”中,并使用它通知客户服务访问。它现在的工作方式是,有人查看由Mac日历生成的(打印的)时间表,然后单击WinFax电话簿中的所有适当条目,以发送通知传真 这就像我们过去

我知道,WinFax Pro是1998年的事

(注意:这不是WinFax.dll,它显然是Windows的一部分。这是WinFax Pro,一个独立的商业附加应用程序,最初来自Delrina,后来被Symantec收购)

我现在的办公室仍然使用WinFax Pro作为操作系统。他们将客户传真号码存储在WinFax Pro“电话簿”中,并使用它通知客户服务访问。它现在的工作方式是,有人查看由Mac日历生成的(打印的)时间表,然后单击WinFax电话簿中的所有适当条目,以发送通知传真

这就像我们过去称之为“转椅”集成的东西,但它指的是两个屏幕。这甚至不是两个屏幕,而是一张纸和一个屏幕

不管怎样,我正在尝试自动化它,但遇到了麻烦

好消息:
-WinFax Pro将其功能公开为COM对象:用于传真引擎的WinFax.SDKSend;用于通讯簿的WinFax.SDKPhoneBook等。
-WinFax Pro提供了一个类型库wfxctl32.tlb,用于描述这些不同的COM对象。 -我能够通过tlbimport生成的包装器从.NET(C#)成功使用WinFax.SDKSend对象。(我正在使用.NET3.5,无法使用.NET4.0)

坏消息:
除了WinFax.SDKSend之外,我无法在WinFax COM对象上调用任何方法。签名看起来并不比WinFax.SDKSend中的签名更复杂,但我不断遇到例外情况

C#代码:

例外情况:

异常:System.InvalidCastException:无法强制转换的COM对象 将“wfxctl32.CSDKPhoneBookClass”键入接口类型 “wfxctl32.ISDKPhoneBook”。此操作失败,因为 对具有IID的接口的COM组件的QueryInterface调用 由于以下原因,{A67FCC81-9949-11D0-961E-444553540000}失败 错误:不支持此类接口(HRESULT的异常:0x80004002 (E_NOINTERFACE))

在System.RuntimeType.InvokeDispMethod(字符串名称、BindingFlags invokeAttr、对象目标、对象[]参数、布尔[]byrefModifiers、Int32区域性、字符串[]namedParameters)
位于System.RuntimeType.InvokeMember(字符串名称、BindingFlags BindingFlags、绑定器绑定器、对象目标、对象[]提供的参数、参数修改器[]修饰符、CultureInfo区域性、字符串[]namedParams)
在System.RuntimeType.ForwardCallToInvokeMember(字符串memberName、BindingFlags标志、对象目标、Int32[]aWrapperTypes、MessageData和msgData)
位于wfxctl32.CSDKPhoneBookClass.GetFolderListFirst(Int16 standardFolder,字符串folderID)


<>我将它视为最坏的解决方案,但您可以在C++(甚至可能是VB6)中为WiFaScript COM对象编写自己的包装器,并使代码执行实际工作,然后从.NET代码中调用这些包装器。这样,您就不必太担心如何将COM接口类型转换为与.Net兼容的类型等,因此这可能会使转换更加容易

我打开了Windows SDK的一部分,可以看到WinFax.SDKPhoneBook的COM接口不在对象上。嗯,这真是个惊喜。接口由类型库描述,tlbimport.exe为其生成包装。WinFax Pro SDK PDF文档中还记录了该接口。但我找不到任何人成功使用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());
}

PhoneBook类是IDispatch接口上的包装器。我为typelib中的每个方法和属性编写了一个包装器方法。我想这是.NET4.0自动为我做的。无论如何,这对我来说很有效

我在这里发布此问答,只是为了让其他与WinFax Pro打交道的人能够了解这些信息。我搜索了所有的管道,没有找到任何好的信息,所以我把它放在那里



编辑-此.NET代码现在正在ASPNET MVC应用程序中运行,允许用户从网页或REST客户端查找条目和发送传真

我无法帮助您解决您的特定问题,但请注意,COM interop仅适用于具有相同“位”的COM dll,并且.NET将默认为运行它的计算机的本机应用程序(即,它将在64位计算机上生成64位应用程序)


几乎所有的COM dll都是32位的,尤其是商用的,因此您必须通过将项目设置中的CPU类型从“Any”设置为“32位”来强制应用程序始终构建32位。

您可能已经厌倦了它,但这不是真正的原因。Tlbimp在类型库中找到双接口没有问题,服务器没有实际实现它是前所未闻的。这种事故最常见的原因是版本控制问题,即类型库与安装的版本不匹配。很普通,更新需要新的guid。@Hans-你可能是对的;我不是COM专家。但是,当我在讨论中的ProgId(
WinFax.SDKPhoneBook
)上使用OleView时,我看到了IDispatch、IUnknown、ITypeInfo和其他一些(刚才不是在机器上),但没有看到WinFax Pro定义的应用程序接口。这让我感到困惑,因为我认为如果.tlb拥有它,那么COM对象会将其作为早期绑定接口公开。我研究了版本和guid——这似乎不是问题所在。看起来赛门铁克从未实现过早期绑定接口。你认为那是不可能的吗?(严肃的问)哦,赛门铁克。我突然不再那么感兴趣了。你有事情要做,应该为你工作。祝你好运
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());
}
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;
    }
....