4

基本的に、VB6を使用してupnp.dll内の関数を呼び出そうとすると、このエラーが発生します。upnp.dllは、VB6でサポートされていないデータ型を返します。以前は、これと同じエラーが発生しましたが、関数/変数が異なり、解決策はoleview.exeでupnp.dllを開き(タイプライブラリ情報を表示するため)、発生するすべての「UnsignedLong」を「Long」に置き換えることでした。次に、「Unsigned」キーワードを削除して新しいTypeLibをコンパイルすると、そのシナリオの問題が解決しました。

ここで、同じ問題を解決する必要がありますが、関数/変数が異なりますが、問題は、upnp.dllのoleviewのTypeLibビューにいるときに、どの変数データ型を変更または削除する必要があるかわからないことです。

完全を期すために、このエラーが発生している場所をお知らせします。次に、変更に問題があるoleview/TypeLibビューの関連部分を示します。(参考までに、upnp.dllはwindows \ system32に含まれており、oleview.exeはまだマシンにインストールされていない場合はWindows SDK Toolkitに付属しています)。

.InvokeAction sActionName, aryIns, aryOutsaryInsとaryOutsが次のように宣言されたバリアントである関数を呼び出しています。-Dim aryIns As Variant, aryIns As Variant基本的に、一般的に宣言し、必要な入力データをaryIns内に配置すると、InvokeAction呼び出しの結果でaryOutsを取得します。良いことは、InvokeActionは、私の一般的なVariantを、使用しているActionNameに対して返される出力アイテムの数を反映する適切なディメンションの配列に変換することです。

エラーが発生している点については、「WAN接続デバイス」の下の「WanIPConnection」で(sActionNameに)「GetStatusInfo」を使用しています。この呼び出しは入力引数を必要としないため、aryInsの項目を定義する必要はありませんが、3つの項目(結果)を提供(返し)、それらをaryOutsに配置します。したがって、aryOutsは、インデックス0から2までのアイテム(合計3アイテム)の配列になります...このaryOuts配列をループすると、アイテム0と1が出力され、完全に(問題なく)表示されますが、3日目になります。 item(aryOuts(2))上記の例外が発生します。

基本的に、最初の2つの引数は単純な文字列です(これらにアクセスしても問題ありません)が、3番目の引数はUPnPの人々によってUnsigned 4 Byte Integer(そしてこれが問題の原因である)と定義されています。VB6はこのデータ型を解釈できず、私に許可しません。この配列項目(aryOuts(2))にアクセスすると、InvokeActionaryOutsの定義がTypeLibでVARIANT*として記述されているため、TypeLibのどの部分を変更する必要があるかがわかりませんでした。関連する部分は次のとおりです。あなたの見解のためのTypeLibの(私が関連すると理解している領域を含めました、追加の領域を投稿したい場合は、私に知らせてください、そして私はこれを行うことができます):

[
  odl,
  uuid(A295019C-DC65-47DD-90DC-7FE918A1AB44),
  helpstring("IUPnPService Interface"),
  dual,
  nonextensible,
  oleautomation
]
interface IUPnPService : IDispatch {
    [id(0x600209c5), helpstring("method QueryStateVariable")]
    HRESULT QueryStateVariable(
                    [in] BSTR bstrVariableName, 
                    [out, retval] VARIANT* pValue);
    [id(0x600209c6), helpstring("method InvokeAction")]
    HRESULT InvokeAction(
                    [in] BSTR bstrActionName, 
                    [in] VARIANT vInActionArgs, 
                    [in, out] VARIANT* pvOutActionArgs, 
                    [out, retval] VARIANT* pvRetVal);
    [id(0x600209c7), propget, helpstring("property ServiceTypeIdentifier")]
    HRESULT ServiceTypeIdentifier([out, retval] BSTR* pVal);
    [id(0x600209c8), helpstring("method AddStateChangeCallback")]
    HRESULT AddCallback([in] IUnknown* pUnkCallback);
    [id(0x600209c9), propget, helpstring("property Id")]
    HRESULT Id([out, retval] BSTR* pbstrId);
    [id(0x600209ca), propget, helpstring("property LastTransportStatus")]
    HRESULT LastTransportStatus([out, retval] long* plValue);
};

私が前に話していたaryOuts()配列は、宣言の[in, out] VARIANT* pvOutActionArgs行(上記のTypeLib)によって定義されています。InvokeAction基本的に、配列全体がVARIANT *(これは問題ありません)としてpvOutActionArgs定義されていますが、上記で定義された配列の3番目の要素(インデックスアイテム番号2)にアクセスできません。この問題を回避するには、TypeLibを変更するにはどうすればよいですか?

参考までに、そして興味のある方のために、Hans Passant(@HansPassant)は、oleview.exeによって公開されたupnp.dll TypeLibからテキストのUnsignedセクションを削除するように依頼することで、同様のシナリオを解決するのを手伝ってくれました。これ(および次の投稿で新しいTypeLib(upnp.tbl)を生成およびコンパイルするために必要な残りの手順: 制限付きとしてマークされた関数またはインターフェイス、または関数がVisualBasicでサポートされていない自動化タイプを使用する

4

1 に答える 1

6

変数 ( ) に代入aryOuts(2)してみてください。ループ (バリアントである) またはバリアントからバリアントへの割り当てで窒息していない限り、VB6 でバリアントにアクセスしても問題はありません。この動作を回避するために、typelib でできることは何もありません。他に何も機能しない場合は、 where = 3のようなものでバリアントタイプを手動で変更できますLonglStatusBits = aryOuts(2)VT_UI4For Each vElem ...vElemCall CopyMemory(aryOuts(2), VT_I4, 2)VT_I4

COM バリアントは、変数に格納されるデータの型を定義する vartype と呼ばれる int16 メンバーで始まるデータ構造です (このaryOuts(2)場合)。

VarTypeVT_UI4は、符号なし int32 値に使用されます。VB6は署名付きバリアントLongに変換されます。VT_I4 = 3

VarTypeVT_UI2は unsigned int16 値に使用されます。VB6は署名付きバリアントIntegerに変換されます。VT_I2 = 2

変数のバリアント型を変更することは、自分が何をしているのかを理解していない限り、非常に危険です。この場合、メモリリークやその他の副作用なしに、符号なしの型を符号付きの対応する型に安全に変換できます。

于 2012-08-31T08:52:04.643 に答える