COM MSXML2でエラーNo.05517
h-tom さん 10/04/04 19:45
 

h-tom です。

秀丸エディタ:Ver.8.00
OS:Windows VistaSP2(32bit)

Unicodeを含む設定を保存するのに、XMLを使おうと思い、"MSXML2"を
COM経由で、使用しましたが、うまく動きません。
オブジェクト(?)を引数にしている箇所で、エラーとなります。
(callmethod → member に変えてみましたがエラーになります。)
これは、対応可能でしょうか?
(COM関連は、型が異様に多いみたいですが)

・実行したマクロ
・実行結果
・同じ処理を行うVBS
を、添付します。
"D:\temp"に、XMLファイルを書き出します。

// マクロ ここから
debuginfo 1;
#reader = createobject("MSXML2.SAXXMLReader");
#writer = createobject("MSXML2.MXXMLWriter");
#xmldoc = createobject("MSXML2.DOMDocument");
#xmlout = createobject("MSXML2.DOMDocument");
setpropnum #xmldoc, "preserveWhiteSpace", 1;
setpropnum #writer, "indent", 1;
setpropnum #writer, "standalone", 1;
setpropstr #writer, "Encoding", "UTF-8";
setpropobj #reader, "contentHandler",#writer;
callmethod #reader, "putProperty", "http://xml.org/sax/properties/lexical-ha
ndler",#writer;
call DBCOM "0";
#head = callmethod_returnobj(#xmldoc, "createProcessingInstruction","xml", "
version='1.0' encoding='UTF-8'");
call DBCOM "1";
callmethod #xmldoc, "appendChild", #head;
call DBCOM "2";
//root作成
#root= callmethod_returnobj(#xmldoc, "createElement", "root");
call DBCOM "3";
callmethod #xmldoc, "appendChild", #root;
call DBCOM "4";
//sctionノード作成
#section = callmethod_returnobj(#xmldoc, "createElement", "sction");
call DBCOM "5";
//key1ノード作成
#key1= callmethod_returnobj(#xmldoc, "createElement", "key1");
call DBCOM "6";
//key1ノードにテキスト追加
#addname = callmethod_returnobj(#xmldoc, "createTextNode", "設定1");
call DBCOM "7";
callmethod #key1, "appendChild", #addname;
call DBCOM "8";
//key2ノード作成
#key2 = callmethod_returnobj(#xmldoc, "createElement", "key2");
call DBCOM "9";
//key2ノードにテキスト追加
#addyear = callmethod_returnobj(#xmldoc, "createTextNode", "設定2");
call DBCOM "10";
callmethod #key2, "appendChild", #addyear;
call DBCOM "11";
//sectionにkey1,key2を追加
callmethod #section, "appendChild", #key1;
call DBCOM "12";
callmethod #section, "appendChild", #key2;
call DBCOM "13";
//rootにsectionを追加
callmethod #root, "appendChild", #section;
call DBCOM "14";
callmethod #xmldoc, "save", "D:\\temp\\test_mac.xml";
call DBCOM "15";
$xml = getpropstr(#xmldoc,"xml");
call DBCOM "16";
callmethod #reader, "Parse", $xml;
call DBCOM "17";
#out1 = getpropobj(#writer, "output");
call DBCOM "18";
callmethod #xmlout, "loadXML", #out1;
call DBCOM "19";
callmethod #xmlout, "save", "D:\\temp\\test_mac2.xml";
call DBCOM "20";
endmacro;
DBCOM:
        debuginfo rightstr("00" + $$1, 3) + ":result=" + str(getresultex(1
0)) + ":0x" +
                  rightstr("0000000000" + hex(getresultex(11)), 8) + "\n";
return;
// マクロ ここまで

// 出力結果 ここから
80070057 E_INVALIDARG        プロシージャの呼び出し、または引数が不正です。
80020005 DISP_E_TYPEMISMATCH 型が一致しません。

No.:Result  :HRESULT
-----------------------
000:result=0:0x80070057
001:result=1:0x00000000
002:result=0:0x80020005
003:result=1:0x00000000
004:result=0:0x80020005
005:result=1:0x00000000
006:result=1:0x00000000
007:result=1:0x00000000
008:result=0:0x80020005
009:result=1:0x00000000
010:result=1:0x00000000
011:result=0:0x80020005
012:result=0:0x80020005
013:result=0:0x80020005
014:result=0:0x80020005
015:result=1:0x00000000
016:result=1:0x00000000
017:result=0:0xC00CE558
018:result=0:0x00000000
019:result=1:0x00000000
020:result=1:0x00000000
// 出力結果 ここまで

//  ここから 同じ処理をしているVBS
set reader = createObject("MSXML2.SAXXMLReader")
set writer = createObject("MSXML2.MXXMLWriter")
set xmldoc = createObject("MSXML2.DOMDocument")
set xmlout = createObject("MSXML2.DOMDocument")
xmldoc.preserveWhiteSpace = True
writer.indent = True
writer.standalone = True
writer.Encoding = "UTF-8"
set reader.contentHandler = writer
call reader.putProperty("http://xml.org/sax/properties/lexical-handler", wri
ter)
set head = xmldoc.createProcessingInstruction("xml", "version='1.0' encoding
='UTF-8'")
xmldoc.appendChild(head)
'ルート作成
set root = xmldoc.createElement("root")
xmldoc.appendChild(root)
'sectionノード作成
set section = xmldoc.createElement("sction")
'key1ノード作成
set key1 = xmldoc.createElement("key1")
'key1ノードにテキスト追加
key1.appendChild(xmldoc.createTextNode("設定1"))
'key2ノード作成
set key2 = xmldoc.createElement("key2")
'key2ノードにテキスト追加
key2.appendChild(xmldoc.createTextNode("設定2"))
'sectionにkey1とkey2を追加
section.appendChild(key1)
section.appendChild(key2)
'rootにsectionを追加
root.appendChild(section)
'保存
xmldoc.save("D:\temp\test.xml")
'インテントで整形して保存
reader.Parse xmldoc.xml
xmlout.loadXML(writer.output)
xmlout.save("D:\temp\test2.xml")
//  ここまで 同じ処理をしているVBS

[ ]
RE:05517 COM MSXML2でエラーNo.05520
秀丸担当 さん 10/04/05 12:22
 

>Unicodeを含む設定を保存するのに、XMLを使おうと思い、"MSXML2"を
>COM経由で、使用しましたが、うまく動きません。
>オブジェクト(?)を引数にしている箇所で、エラーとなります。
>(callmethod → member に変えてみましたがエラーになります。)
>これは、対応可能でしょうか?
>(COM関連は、型が異様に多いみたいですが)

マクロの通りにして、全く同じように再現させることができました。
おっしゃる通り、オブジェクトをパラメータにしている所でエラーになっている
ようです。
オブジェクトは秀丸エディタ内部で順番に割り当てられた数値でしかなく、これ
をそのまま渡すと単なる数値として渡してしまうため、だめなようです。

オブジェクトを渡すことができるのは setpropobj だけで、setpropobjで指定し
た数値はオブジェクトとして解釈されます。
callmethod等では指定した数値はオブジェクトとしては解釈されず、オブジェク
トを渡す方法は文法的に存在していませんでした。

事前にパラメータの種類を調べればなんとかなりそうかと思ったのですが、試し
にやってみたところ、パラメータの種類はVT_VARIANTになっていて、特定できな
いようになっていました。VT_DISPATCHだったらなんとかなったのですが。

単純に失敗したらオブジェクトとして解釈して再試行でやってみたらできました。
しかし、数値を全てオブジェクトとして解釈してしまうのはあまり良くなさそう
です。
また、再試行が入ると getresultex(11) で得られるコードも何に対してのエ
ラーなのかわからなくなってしまいそうです。

将来的に何らかの新しい文法を考えないといけないかもしれません。
現時点ではできないということでお願いするしかないかもしれないです。

[ ]
RE:05520 COMMSXML2でエラーNo.05522
h-tom さん 10/04/05 14:03
 

h-tom です。

>将来的に何らかの新しい文法を考えないといけないかもしれません。
>現時点ではできないということでお願いするしかないかもしれないです。
了解です。


>単純に失敗したらオブジェクトとして解釈して再試行でやってみたらできました。
>しかし、数値を全てオブジェクトとして解釈してしまうのはあまり良くなさそう
>です。
引数で渡す時に、数値 = オブジェクト と見なすような表記法とか、変換関数み
たいなのを追加ですかね?
  (例)
  callmethod #obj1, "function", @#obj2;       (先頭に何か記号を追加)
  callmethod #obj1, "function", {#obj2};      (括弧等で囲む)
  callmethod #obj1, "function", xxxobj(#obj2);(変換関数?)

[ ]
RE:05522 COMMSXML2でエラーNo.05523
秀丸担当 さん 10/04/05 15:01
 

>引数で渡す時に、数値 = オブジェクト と見なすような表記法とか、変換関数み
>たいなのを追加ですかね?
>  (例)
>  callmethod #obj1, "function", @#obj2;       (先頭に何か記号を追加)
>  callmethod #obj1, "function", {#obj2};      (括弧等で囲む)
>  callmethod #obj1, "function", xxxobj(#obj2);(変換関数?)

具体的にはあまりいい方法がいまのところ思いつかないです。
上記の方法だと数値でも文字列でもない変数を作る必要があって根本から変えな
いといけなさそうです。

既存のマクロ文法のままだとすると、

  callmethod_objparam #obj1, "function", #obj2;

とか

  callmethod_ex #obj1,"function"
               0, #num,    //パラメータ1 数値
               1, $str,    //パラメータ2 文字列
               2, #obj2;   //パラメータ3 オブジェクト

というような感じがいいかもしれないです。
あるいはもっといい方法があればいいですが、将来のネタということにさせてい
ただこうと思います。

[ ]
RE:05523 COMMSXML2でエラーNo.05524
h-tom さん 10/04/05 19:31
 

h-tom です。

>  callmethod_ex #obj1,"function"
>               0, #num,    //パラメータ1 数値
>               1, $str,    //パラメータ2 文字列
>               2, #obj2;   //パラメータ3 オブジェクト
>
>というような感じがいいかもしれないです。
>あるいはもっといい方法があればいいですが、将来のネタということにさせてい
>ただこうと思います。

参考にまでに、阿部 紀行氏のmacrodll.dllで、COM/OLEを扱う場合の方法です。
macrodll関数一覧
http://www.ms.u-tokyo.ac.jp/~abenori/mycreate/hidemaru/dllfunc.html#f82beb3487cfe557ed5ae60d0b301d74
第一引数:対象オブジェクト
第二引数:プロパティ/関数名
第三引数:引数の順番と型指定を行う文字列
          順番にiなら整数型,sなら文字列型,dならオブジェクト.NULLにすると
引数無し
第四引数以降は、プロパティ/関数の引数。

[ ]
RE:05524 COMMSXML2でエラーNo.05526
秀丸担当 さん 10/04/06 10:30
 

>第三引数:引数の順番と型指定を行う文字列
>          順番にiなら整数型,sなら文字列型,dならオブジェクト.NULLにすると
>引数無し
>第四引数以降は、プロパティ/関数の引数。

情報ありがとうございます。
この方法でしたら、パラメータの数が少なくて済みますね。
参考にさせていただきます。

[ ]