[ 新規に投稿する ]

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_returnxx関数をひとつ増やすか。

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.Dictionaryに変換するのが合理的かもしれないです。
ハッシュなので配列とは違いますが、ハッシュの名前部分を数値にすると配列のように扱え、文字列/数値判定もできそうです。
こういう方法でやってみようかと思います。
#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.DictionaryかArrayListかは意識せずに使えたらよさそうです。
[ ]
RE:09399 COM呼び出しについてNo.09405
h-tom さん 21/05/25 23:26 [ コメントを投稿する ]
  h-tom です。

>文字列か数値かの判定については、コレクションではやりにくいので、Scripting.Dictionaryに変換するのが合理的かもしれないです。
>ハッシュなので配列とは違いますが、ハッシュの名前部分を数値にすると配列のように扱え、文字列/数値判定もできそうです。
>こういう方法でやってみようかと思います。
これは、戻り値が 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"で取得できる何らかのオブジェクトということにしておこうと思います。
[ ]

[ 新規に投稿する ]