COM呼び出しについてNo.09389
ラフ さん 21/05/23 19:56
 
Scripting.DictionaryのKeysメソッドがエラーになります。
getresultex(11)の値は0x80020011なのでDoes not support a collectionのようですが
WSHや秀丸ファイラーClassicのスクリプトでは普通にKeysが取れるので
秀丸からのCOM接続が何か違うのかなって言う気がするのですが。
Keysが返してくるのが配列だからですかね。
以下のソース何か間違ってますか?

#objHash = createobject("Scripting.Dictionary");
if( getresultex(10) == false ) {
 message "createobjectエラー";
 endmacro;
}
setpropnum #objHash, "CompareMode", 1;
if( getresultex(10) == false ) {
 message "setpropnum失敗";
 goto macro_end;
}
callmethod #objHash, "add", "str1", "value1";
if( getresultex(10) == false ) {
 message "add失敗";
 goto macro_end;
}
callmethod #objHash, "add", "num1", 2;
if( getresultex(10) == false ) {
 message "add失敗";
 goto macro_end;
}
$a = getpropstr(#objHash, "Item", "str1");
message $a;
#b = getpropnum(#objHash, "Item", "num1");
message str(#b);
$keys = member(#objHash, "Keys");
if( getresultex(10) == false ) { // ここでfalseになっている
 message "Keys取得失敗:"+hex(getresultex(11));
 goto macro_end;
}
macro_end:
releaseobject #objHash;
endmacro;


[ ]
RE:09389 COM呼び出しについてNo.09390
秀丸担当 さん 21/05/24 11:03
 

試してみたところ、Scripting.DictionaryのKeysメソッドは確かにできませんでした。
返ってくる内容を調べてみたところ、いわゆるSafeArrayという種類で、配列がまる
ごと1つの返り値として帰ってくるものでした。
Itemsメソッドというものもあるようで、これも同様で、文字列と数値が混在した配
列が、1つの返り値でまるごと、ということになるようです。
これを秀丸マクロの文法で表現する方法は無くて、そのままでは無理そうでした。

特殊な例としては、allowobjparam 2;の指定で、バイナリ(バイト値の配列)を文字
列に変換して受け取るというものがあります。1バイトが16進数2文字として、それを
連結した文字列です。
かなりトリッキーですが、連結した長い1つn文字列といったような手法であればな
んとかなるかもしれないです。
長い文字列は、ある特定の区切り文字でsplit()関数で再び配列に分解する方法があ
ります。
でも文字列と数値の混在はやっぱり表現できないので、数値も文字列に変換するとか
しないとできないと思います。
そういった方法でできないか検討します。

[ ]
RE:09390 COM呼び出しについてNo.09391
ラフ さん 21/05/24 15:07
 
なんかややこしそうですね(^^;
配列をマクロ側に返す手段があればよかったんですが、サブルーチンも配列返せない
ですもんね。

これってFileSystemObjectのFoldersコレクションのように内部でコレクションに変
換ってできないですか?
配列を返すメソッドだから変換してねってマクロ側から先に教えるか、callmethod_r
eturnxx関数をひとつ増やすか。

KeysやItems取りたい場合って、結局取り出してからFor文(秀丸ならwhile文)回す使
い方しかしないように思います。
ならば、コレクションでwhile文で回して取り出してもマクロ書く側はあまり変わら
ないし。
内部的に何番目取り出しているか管理がいるから却って面倒ですかね。

[ ]
RE:09391 COM呼び出しについてNo.09392
ラフ さん 21/05/24 15:10
 
文章がおかしいな。

>これってFileSystemObjectのFoldersコレクションのように内部でコレクションに変
>換ってできないですか?

これってFileSystemObjectのFoldersコレクションのような取り出しができるように、
配列で返ってくるデータを内部でコレクションに変換ってできないですか?

という意味合いです。

[ ]
RE:09392 COM呼び出しについてNo.09393
秀丸担当 さん 21/05/24 16:39
 

コレクションでできてもいいと思います。
コレクションと同等のものにするのは、それはそれで難しいところがいろいろあるの
ですが、できたとして、数値と文字列が混在する場合はやっぱりできないということ
もあります。
まだ手を付けていないのですが、コレクションも含めてできそうなところを検討しま
す。

[ ]
RE:09393 COM呼び出しについてNo.09394
ラフ さん 21/05/24 18:45
 
数値と文字の混在ですが、ArrayListのItemメソッドでも起きていて、取り出すデー
タの型がどちらかわからないと取り出せない。
で、仕方なく、まず文字列で取り出してみてエラーなら数値で取り出しなおすという
方法で逃げています。
なので、コレクションできるなら同じ方法でマクロ作成側で工夫で逃げられるかなと
は思います。エラーを返してもらえるならですが(^^;
数値でもエラーならもうオブジェクトや配列を入れたくらいしかないので、問題はな
い気がします。秀丸マクロで入れられるかどうかは試してませんが、あえてオブジェ
クトをハッシュやArrayListに入れる事はまずないだろうと思っています。

でも内部的にコレクションに変換するのは大変そうですよね。
現状のgetcollectionどうしているのかわかりませんが。

[ ]
RE:09394 COM呼び出しについてNo.09395
ラフ さん 21/05/24 18:58
 
でもあれか、getcollectionした後のデータの取り出しのmemberとかで取り出すプロ
パティ("Name"とか)が無いか。

[ ]
RE:09395 COM呼び出しについてNo.09399
秀丸担当 さん 21/05/25 09:24
 

文字列か数値かの判定については、コレクションではやりにくいので、Scripting.Di
ctionaryに変換するのが合理的かもしれないです。
ハッシュなので配列とは違いますが、ハッシュの名前部分を数値にすると配列のよう
に扱え、文字列/数値判定もできそうです。
こういう方法でやってみようかと思います。
#objHash = createobject("Scripting.Dictionary");
//...
#objKeys = member(#objHash, "Keys"); //#objKeysもScripting.Dictionary
#c=getpropnum(#objKeys,"Count");
#i=0;
while(#i<#c){
  $a=getpropstr(#objKeys,"Item",#i);
  if(getresultex(10)==false){
    #a=getpropnum(#objKeys,"Item",#i);
  }
  #i=#i+1;
}

ArrayListというのは、.netのSystem.Collections.ArrayListのことだと思いますが、
これもCOMオブジェクトとして使えるのですね。
ArrayListも"Count"と"Item"で上記と同じ書き方にできるようです。
というか"Count"と"Item"を使うということにして、#objKeysがScripting.Dictionar
yかArrayListかは意識せずに使えたらよさそうです。

[ ]
RE:09399 COM呼び出しについてNo.09405
h-tom さん 21/05/25 23:26
 
h-tom です。

>文字列か数値かの判定については、コレクションではやりにくいので、Scripting.D
>ictionaryに変換するのが合理的かもしれないです。
>ハッシュなので配列とは違いますが、ハッシュの名前部分を数値にすると配列のよ
>うに扱え、文字列/数値判定もできそうです。
>こういう方法でやってみようかと思います。
これは、戻り値が SafeArray の場合、Scripting.Dictionaryに変換するということ
でしょうか?

>ArrayListというのは、.netのSystem.Collections.ArrayListのことだと思いますが、
>これもCOMオブジェクトとして使えるのですね。
前に、以下の「.NET Freamework」のコレクションクラスが、COMから使えるとありま
したよ。
・ArrayList(System.Collections.ArrayList)
  動的配列
・Hashtable(System.Collections.Hashtable)
  連想配列
・SortedList(System.Collections.SortedList)
  キーによってソートされる連想配列
・Queue(System.Collections.Queue)
  先入れ先出しリスト
・Stack(System.Collections.Stack)
  後入れ先出しリスト

うちのwebサイトで公開している「HidemaruMacroWscLib」は、ArrayListの中身が数
値か文字列か判定するためのメソッドを追加して、対処しました。
(vbsのTypeName関数呼んでるだけ)

[ ]
RE:09405 COM呼び出しについてNo.09406
秀丸担当 さん 21/05/26 10:07
 

>これは、戻り値が SafeArray の場合、Scripting.Dictionaryに変換するということで
>しょうか?

内部的には一応そうしようかと思っていますが、ようは"Count"と"Item"でアクセス
できればいいということにして、独自の実装でもArrayListでもいいかなと考えてま
した。

>うちのwebサイトで公開している「HidemaruMacroWscLib」は、ArrayListの中身が数値
>か文字列か判定するためのメソッドを追加して、対処しました。
>(vbsのTypeName関数呼んでるだけ)

いろいろな手法があるということで参考になります。
ArrayListを調べるライブラリということで、Scripting.Dictionaryに変換ではなく、
ArrayListに変換ということにしておけば、h-tomさんのライブラリも使えるというこ
とになりそうな気がします。
Scripting.DictionaryはやめてArrayListで検討してみます。

[ ]
RE:09406 COM呼び出しについてNo.09407
こみやんま さん 21/05/26 17:08
 
ArrayListやHashtableはマイクロソフトがわざわざ名指しで新規制作物での使用を
「非推奨」として長く経過しています。
(実際C#でもこれを使うような人はまず見かけません)

実装するとしてもそこは飲んだ上でといった形をおすすめします。

[ ]
RE:09407 COM呼び出しについてNo.09409
秀丸担当 さん 21/05/28 08:54
 

表面上の仕様としては、ArrayListとは明確にはせず、"Count"と"Item"で取得できる
何らかのオブジェクトということにしておこうと思います。

[ ]