関数に引数を渡すには?


五里霧中  2005-09-06 23:15:54  No: 124957

【環境】WinXP,WSH5.6

関数の呼び出しについてご教授下さい。

test.vbsからtest.funcを呼び出しています。
その中で、

**test.vbs**
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFunc = objFSO.OpenTextFile(cnsFuncFile,1,False)
Execute objFunc.ReadAll
Call TestSub(strSvrNum)

**test.func**
Sub TestSub(strSvrNum)
  処理
End Sub

という記述をしています。
この場合、「引数の数が一致していません。または不正なプロパティを指定しています。:'TestSub'」というエラーになってしまいます。
strSvrNumには3桁の文字列が入っています。
引数の数が一致しない、とはどういう意味なのでしょうか?
宜しくお願い致します。


Geo=TK3  2005-09-06 23:28:27  No: 124958

当方で簡単な VBScript ファイル作ってみたのですが、ファイル分割を
しないとそれらしい現象は再現しませんでした。
もしかして test.vbs と test.func は別のファイルでしょうか?

もし別のファイルであればとりあえず test.func の内容を test.vbs に
含めて試してみてください。


五里霧中  2005-09-06 23:40:49  No: 124959

>Geo=TK3さん

ご回答ありがとうございます。
おっしゃる通り、test.vbsとtest.funcは別ファイルにしています。説明が足りず失礼致しました。

test.funcの内容をtest.vbsに含めた場合は問題なく動作(デバッグコードを入れて正常に流れることを確認)しました。
なのですが…実は既存のプログラムに関数を追加しようとしている為、ファイルを廃止するのは難しい状況なのです。
二つのファイルは別々のままで'TestSub'の部分を呼び出すよう処理したいのですが…

何か根本的に勘違いしている気もして怖いのですが、ご指摘をお願い致します。


Geo=TK3  2005-09-07 00:43:24  No: 124960

>なのですが…実は既存のプログラムに関数を追加しようとしている為、ファイルを廃止するのは難しい状況なのです。
>二つのファイルは別々のままで'TestSub'の部分を呼び出すよう処理したいのですが…

うーん、そうなんですか。
私もある VBScript の中から別の VBScript 内に定義したプロシー
ジャの呼び出し方知らないんですよね (^^;; 。

とりあえず Google で検索してみた処では
# 使用キーワード: VBScript スクリプト ファイル 複数

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/script56/html/wsAdvantagesOfWs.asp

の「インクルードステートメント」の機能を使うか

http://www.atmarkit.co.jp/fwin2k/win2ktips/475scriptlet/scriptlet.html

みたいな感じで test.func の機能を Scriptlets 化して test.vbs からは
CreateObject する事で対応するしかない感じです。
# 共に未検証です m(__)m 。

もう少し簡単に別スクリプトファイルの機能を呼び出す方法が欲しい
処ですね。
# import とか include とか require とか (^^; 。

> 何か根本的に勘違いしている気もして怖いのですが、ご指摘をお願い致します。

上記のような状況故にまともな回答が出来ないので申し訳ないのですが。

(1) 出来れば一つのファイルにまとめる。<今回は要件上無理か (^^;; 。
(2) .wsf ファイルを使って回避?<一番現実的かなぁ
(3) test.func を ScriptLets 化して回避??<COM コンポーネント作るので微妙

という方法で対応するしかないかな?って感じです...


五里霧中  2005-09-07 01:35:51  No: 124961

>Geo=TK3さん

またまたご回答ありがとうございます。

>「インクルードステートメント」の機能を使う

なるほど…これは、test.wsf(元のtest.vbs)→test.vbs(元のtest.func)という形で呼び出す、ということですよね。
vbsを学習中に(といってもここ2ヶ月ほどなのですが)、検索で引っかかってきた .wsfなるキーワードに興味を持って、すこしいじりかけたことはあります。
が、xml自体を知らない為、「とりあえず後回し…」な状態のままでした。
これを使うとなれば、xmlから勉強してみます。

>test.func の機能を Scriptlets 化して test.vbs からは
CreateObject する

す、すくりぷとれっとですか。。。
こちらは初耳のキーワードでした。
ご提示頂いたリンク先を見たところ、関数なり頻出するロジックなりを部品化する手法、までは分かりました。
VBAやASPからの利用も可能ということは、上記のwsfファイルを使用する場合に比べ、より広範な部品化を目的にする、という理解でいいのでしょうか…?

今回のスクリプトの場合、test.func自体は単なるテキストファイルで、test.vbsの中でReadAllした後に関数部分をCallしているのですが、「なんだ、これで動くんだ〜」と思っておりました。
実際、引数を使用していない関数については動いています。
引数を使ったら、wsfやスクリプトレットを導入しなければならない、というのも正直ややこしいですね(-_-;)

浅薄な知識で見当外れなことを書いてしまったかもしれませんが、ご提示頂いた方法含め解決策をさらに調査し、またご報告致します。


Geo=TK3  2005-09-07 02:14:52  No: 124962

>なるほど…これは、test.wsf(元のtest.vbs)→test.vbs(元のtest.func)という形で呼び出す、ということですよね。

そうです。

>VBAやASPからの利用も可能ということは、上記のwsfファイルを使用する場合に比べ、より広範な部品化を目的にする、という理解でいいのでしょうか…?

そういう理解で良いと思います。
VBScript などの WSH 対応言語で COM コンポーネントが作成出来ると
言う事だと思いますので、VBA や ASP に限らず COM コンポーネントが
使える言語であれば万事オーケィなのではないかと。

>今回のスクリプトの場合、test.func自体は単なるテキストファイルで、test.vbsの中でReadAllした後に関>数部分をCallしているのですが、「なんだ、これで動くんだ〜」と思っておりました。
>実際、引数を使用していない関数については動いています。
>引数を使ったら、wsfやスクリプトレットを導入しなければならない、というのも正直ややこしいですね(-_-;)

あー、ごめんなさい。
まさか test.func 読み込んで Execute 掛けてるとは思わなかったんで
その調査はしてませんでした。
で、改めて追調査したら .wsf やら ScriptLets などを使わなくても
引数渡しの呼び出しに成功する場合がありました (^^;; 。

という処で再度確認なのですが、実際のコードでは Execute の直後に
test.func 側のファンクションを呼んでいるのでしょうか?
それとも test.vbs 中の別ファンクションで呼び出しているんでしょ
うか?


五里霧中  2005-09-07 02:56:42  No: 124963

>Geo=TK3さん

大変失礼致しました。そもそもの説明が不足していたようです!
test.vbsでは処理はほとんど無く、変数の宣言、ファイルのオープン、処理ごとに分かれた関数の呼び出し、等しかしていません。

つまり、test.vbsではExecuteした直後(間にIfやらFor文は入りますが)にtest.func側の関数をCallしています。
これだと引数渡しでも上手く行くのでしょうか?

自分でも調べてはみたのですが、「どうして今の記述で動かないか?」を判断することはできませんでした…
是非ご教授下さいm(_ _)m


魔界の仮面弁士  2005-09-07 07:02:52  No: 124964

とりあえず、VBScript Version 5.6.8820 の環境にて、提示されたような
下記のコードで実験してみましたが……特に問題なく動作しました。(^^;

'=====C:\test.func=====
Sub TestSub(strSvrNum)
    MsgBox strSvrNum
End Sub

'=====呼び出し元=====
Option Explicit 'On
Const cnsFuncFile = "C:\test.func"
Dim objFSO, objFunc,strSvrNum
strSvrNum = "123"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFunc = objFSO.OpenTextFile(cnsFuncFile, 1, False)
Execute objFunc.ReadAll
objFunc.Close
Set objFunc = Nothing
Set objFSO = Nothing
Call TestSub(strSvrNum)

なお、実験に使ったのは、以下の4種のホスト環境です。
     CScript.exe 5.6.0.8820
     WScript.exe 5.6.0.8820
     Microsoft スクリプト コントロール 1.0.0.8820
     Internet Explorer 6.0.2900.2180.xpsp_sp2_gdr.050301-1519

> 「どうして今の記述で動かないか?」を判断することはできませんでした…

以下、確認事項。

1. 提示されたコードの場合、エラーが発生しているのは、
  『Call TestSub(strSvrNum)』の行なのでしょうか。それとも、
  別の行なのでしょうか?

2. 掲示板に提示していない、他の部分のコードに原因が
  あったりはしませんか? 簡単なテスト用のコードを書いて
  確認してみてください。

3. Execute の代わりに、ExecuteGlobal を使ってみた場合はどうですか?

4. 呼び出し側から渡す引数の数を変更してみてください。
  メッセージに何か変化はありますか?

5. 『Call TestSub(strSvrNum)』を呼び出す「直前」にて、
            MsgBox TypeName(GetRef("TestSub"))
  という一行を入れてみてください。正しく実装されているならば、
  『Object』というメッセージが表示されるはずです。

6. 『Call TestSub(strSvrNum)』を呼び出す「直前」にて、
            MsgBox TypeName(TestSub)
  という一行を入れてみてください。正しく実装されているならば、
  『型が一致しません。』のエラーになるはずです。

7. 『Execute objFunc.ReadAll』を呼び出す「直前」にて、
            MsgBox TypeName(TestSub)
  という一行を入れてみてください。正しく実装されているならば、
  Option Explicitがあれば、『この変数は宣言されていません』エラー、
  Option Explicitが無いと、『Empty』と表示されるはずです。

8. 『Execute objFunc.ReadAll』を呼び出す「直前」にて、
            MsgBox TypeName(GetRef("TestSub"))
  という一行を入れてみてください。正しく実装されているならば、
  『プロシージャの呼び出し、または引数が不正です。』エラーに
  なるはずです。


五里霧中  2005-09-07 19:58:32  No: 124965

>魔界の仮面弁士さん
ご丁寧なご回答、本当にありがとうございます。
確認事項を試してみましたので、以下に結果を報告致します。
大変長くなってしまいましたが、ご確認下さい。

>1. 提示されたコードの場合、エラーが発生しているのは、
>  『Call TestSub(strSvrNum)』の行なのでしょうか。それとも、
>  別の行なのでしょうか?
★Callの行です。エラー表示の際の行番号("test.vbs(x,y)"のxの値)から判断致しました。

>2. 掲示板に提示していない、他の部分のコードに原因が
>  あったりはしませんか? 簡単なテスト用のコードを書いて
>  確認してみてください。
★自分でも大いに怪しい(デバッグしている際は大抵このようなつまらないミスではまったりしますので…)と思ったのですが、現時点では原因でなさそうです。
  引数を使用しない場合は同じルートで流れる、Callの直前でechoしたところ到達していた、ことから判断致しました。

>3. Execute の代わりに、ExecuteGlobal を使ってみた場合はどうですか?
★Executeと同じエラーになりました。

>4. 呼び出し側から渡す引数の数を変更してみてください。
>  メッセージに何か変化はありますか?
★引数を複数にしてみましたが、同様のエラーでした。

>5. 『Call TestSub(strSvrNum)』を呼び出す「直前」にて、
>            MsgBox TypeName(GetRef("TestSub"))
>  という一行を入れてみてください。正しく実装されているならば、
>  『Object』というメッセージが表示されるはずです。
★『Object』が表示されました。エラーは同様のものでした。

>6. 『Call TestSub(strSvrNum)』を呼び出す「直前」にて、
>            MsgBox TypeName(TestSub)
>  という一行を入れてみてください。正しく実装されているならば、
>  『型が一致しません。』のエラーになるはずです。
★『型が一致しません。』のエラーがでました。

>7. 『Execute objFunc.ReadAll』を呼び出す「直前」にて、
>            MsgBox TypeName(TestSub)
>  という一行を入れてみてください。正しく実装されているならば、
>  Option Explicitがあれば、『この変数は宣言されていません』エラー、
>  Option Explicitが無いと、『Empty』と表示されるはずです。
★Option Explicitを入れているので、『この変数は宣言されていません』になりました。

>8. 『Execute objFunc.ReadAll』を呼び出す「直前」にて、
>            MsgBox TypeName(GetRef("TestSub"))
>  という一行を入れてみてください。正しく実装されているならば、
>  『プロシージャの呼び出し、または引数が不正です。』エラーに
>  なるはずです。
★『プロシージャの呼び出し、または引数が不正です。』エラーになりました。

と、ここまで書いてきて、バージョンの確認をしてないな…と気づき調べてみました。
     CScript.exe 5.6.0.8515
     WScript.exe 5.6.0.8515
     Microsoft スクリプト コントロール
       #↑はなんという名前になりますでしょうか?ダウンロード時の名前が「sct10jp.exe」のものかと思うのですが…
       #WSHインストール後に個別でダウンロードしていないので、入っていないはずだと思います。
     Internet Explorer 6.0.2900.2180.xpsp_sp2_gdr.050301-1519

結果、見事にバージョンが違っていました(-_-;)
正常に動作していたGeo=TK3さんの環境ともバージョンが異なっていたのでしょうか。
この差異で動かないのか、それともまだ気づいていないミスがあるのか…
全体でも300ステップ程度ですので、もう一度頭から確認をし直してみます。
進展あり次第、ご報告致します。

経過報告しかできませんでしたが、Geo=TK3さん、魔界の仮面弁士さんありがとうございました。


魔界の仮面弁士  2005-09-07 20:53:27  No: 124966

> ★Callの行です。エラー表示の際の行番号("test.vbs(x,y)"のxの値)から判断致しました。
Callの行でエラーが発生する場合は、
  a) TestSub の呼び出し自体が失敗している場合
  b) TestSub 内部で、何らかの関数呼び出しが失敗している場合
のいずれかが考えられます。

もっとも、後者は、「行番号 0」として表示される可能性が高いので、
おそらくは前者なのだと思いますけれども。

> 引数を使用しない場合は同じルートで流れる、Callの直前で
> echoしたところ到達していた、ことから判断致しました。
現在使用中のソースではなく、私が書いたソースでは現象が再現しますか?
再現しないなら、やはりソースのどこかに原因があると思うのですが、
正直、ソース全体を見ないとわからないですね……。

>>4. 呼び出し側から渡す引数の数を変更してみてください。
>>  メッセージに何か変化はありますか?
>★引数を複数にしてみましたが、同様のエラーでした。
「複数」とは、具体的には何個でしょう? (「0個」も試されましたか?)

> Microsoft スクリプト コントロール
> #↑はなんという名前になりますでしょうか
これは、「MSSCRIPT.OCX」ですね。
でも、*.vbsをダブルクリックして実行されているなら、今回は無関係です。

# 私はVBScriptをテストする際、VBSファイルを作って実行させるのが
# わずらわしいので、スクリプトファイルを保存せずに実行できるよう、
# スクリプト コントロールを使った自作アプリを使う事が多いのです。

> 結果、見事にバージョンが違っていました(-_-;)
あれ? 最初の質問時に
>> 【環境】WinXP,WSH5.6
と書かれていましたので、CScript.exe のバージョンも、
5.6.* 系だと思っていましたが……。(もしかして、5.1系でしたか?)

S = ScriptEngine & vbCrLf
S = S & ScriptEngineMajorVersion & "."
S = S & ScriptEngineMinorVersion & "."
S = S & ScriptEngineBuildVersion

MsgBox S, vbInformation


Geo=TK3  2005-09-07 22:47:54  No: 124967

魔界の仮面弁士さん、フォローしていただきありが
とうございます m(__)m 。

>正常に動作していたGeo=TK3さんの環境ともバージョンが異なっていたのでしょうか。

私が試験した環境の各バージョンを以下に記載します。

  cscript.exe  5.6.0.8820
  wscript.exe  5.6.0.8820
  Microsoft スクリプト コントロール  1.0.0.8820
  InternetExplorer  6.0.2900.2180.xpsp_sp2_gdr.050301-1519

また仮面の魔界弁士さんが投稿してくれた Script エン
ジンのバージョン表示スクリプトにより表示されたバー
ジョンは下記の通りです。

  VBScript
  5.6.8820


魔界の仮面弁士  2005-09-07 23:41:04  No: 124968

> 結果、見事にバージョンが違っていました(-_-;)
あ。勘違いしてました。これって、

>>     CScript.exe 5.6.0.8820
>      CScript.exe 5.6.0.8515
の“ビルドバージョン”の違いの事を言っておられたのですね。

でも、ビルドバージョンの違いだけでは、そこまで大きな
違いがでるとは思えないのですが……。

実際、手元の Virtual PC に、
   Win2000/SP4 + CScript.exe 5.6.0.6626
の環境があったので試してみましたが、先の私のサンプルは、
やはりエラーにならず、問題なく TestSub を呼び出せましたし。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加