3

私が知っている、WinFax Pro は 1998 年です。

(注: これは明らかに Windows の一部である WinFax.dll ではありません。これは WinFax Pro であり、もともと Delrina から提供され、後に Symantec によって買収された別の商用アドオン アプリです)。

私は今でも WinFax Pro を運用システムとして使用しているオフィスで働いています。彼らは顧客のファックス番号を WinFax Pro の「電話帳」に保存しており、それを使用して顧客にサービス訪問を通知しています。現在の動作方法は、誰かが Mac カレンダーから生成された (印刷された) スケジュールを見て、WinFax 電話帳の該当するすべてのエントリをクリックして、通知 FAX を送信することです。

これは、以前は「回転椅子」の統合と呼ばれていたもののようなものですが、それは 2 つの画面を指していました。これは 2 画面ではなく、1 枚の紙と 1 つの画面です。

とにかく、私はそれを自動化しようとしていますが、問題があります。

良いニュース:
- WinFax Pro は、その機能を COM オブジェクトとして公開します。ファックス sxending エンジン用の WinFax.SDKSend。アドレス帳には WinFax.SDKPhoneBook など。
- WinFax Pro には、これらのさまざまな COM オブジェクトを記述するタイプ ライブラリ wfxctl32.tlb が付属しています。- tlbimport から生成されたラッパーを介して、.NET (C#) から WinFax.SDKSend オブジェクトを正常に使用できます。(私は .NET 3.5 を使用しています。.NET 4.0 はできません) .

悪いニュース:
WinFax.SDKSend 以外の WinFax COM オブジェクトのメソッドを呼び出すことができませんでした。署名は WinFax.SDKSend の署名よりも複雑に見えませんが、例外が発生し続けています。

C# コード:

public void Run()
{
    var pb = new wfxctl32.CSDKPhoneBook();
    string id = pb.GetFolderListFirst(1, "");
}

例外:

例外: System.InvalidCastException: タイプ 'wfxctl32.CSDKPhoneBookClass' の COM オブジェクトをインターフェイス タイプ 'wfxctl32.ISDKPhoneBook' にキャストできません。IID '{A67FCC81-9949-11D0-961E-444553540000}' を持つインターフェイスの COM コンポーネントでの QueryInterface 呼び出しが次のエラーにより失敗したため、この操作は失敗しました: No such interface supported (HRESULT からの例外: 0x80004002 (E_NOINTERFACE)) .

System.RuntimeType.InvokeDispMethod (文字列名、BindingFlags invokeAttr、オブジェクト ターゲット、オブジェクト [] args、Boolean [] byrefModifiers、Int32 カルチャ、文字列 [] namedParameters)
で System.RuntimeType.InvokeMember (文字列名、BindingFlags bindingFlags、バインダー バインダー、
System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)で
wfxctl32.CSDKPhoneBookClass. GetFolderListFirst(Int16 standardFolder, String folderID)

4

3 に答える 3

1

Windows SDK の一部である OleView ツールを開くと、WinFax.SDKPhoneBookの COM インターフェイスがオブジェクトに存在しないことがわかります。うーん、それは驚きです。インターフェイスはタイプ ライブラリによって記述され、tlbimport.exe はそのラッパーを生成します。また、インターフェイスは WinFax Pro SDK PDF ドキュメントに記載されています。しかし、WinFax.SDKPhoneBook の初期バインド インターフェイスを使用して成功した例は 1 つも見つかりませんでした。

COMオブジェクトへのjavascript呼び出しでこれを試したところ、うまくいきました。

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、およびその他のレイト バインド言語から自然にアクセスできますが、直接ではないと結論付けました。 C# や VB.NET などの .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 インターフェイスのラッパーです。typelib のメソッドとプロパティごとに 1 つのラッパー メソッドを記述しました。これは、.NET 4.0 が自動的にやってくれることだと思います。いずれにせよ、これは私にとってはうまくいきました。

この Q&A をここに掲載するのは、WinFax Pro を扱う他の人が情報を入手できるようにするためです。インターチューブをあちこち探しましたが、良い情報が見つからなかったので、これを公開します。


編集- この .NET コードは現在、ASPNET MVC アプリで実行されており、ユーザーはエントリを検索し、Web ページまたは REST クライアントからファックスを送信できます。

于 2011-01-25T15:36:30.657 に答える
0

特定の問題についてはお手伝いできませんが、COM相互運用は同じ「ビット数」のcom dllでのみ機能し、.NETはデフォルトで、実行中のコンピューターにネイティブなアプリケーションを生成することに注意してください(つまり、. 64 ビット コンピューターで 64 ビット アプリを生成します)。

ほとんどすべての COM dll、特に商用の dll は 32 ビットであるため、プロジェクト設定で CPU タイプを「任意」から「32 ビット」に設定して、アプリを常に 32 ビットでビルドするように強制する必要があります。

于 2011-01-25T15:41:02.817 に答える
0

最悪の場合の解決策だと思いますが、Winfax COM オブジェクト用の独自のラッパーを C++ (またはおそらく VB6) でいつでも作成し、そのコードで実際の作業を実行してから、.Net コードからそれらのラッパーを呼び出すことができます。 . そうすれば、COM インターフェイス タイプを .Net 互換タイプなどに変換する方法を考え出すことについてあまり心配する必要がないため、かなり簡単になる可能性があります。

于 2011-01-25T15:35:30.023 に答える