VBScriptに引数を渡すには?

解決


Kent  2010-10-07 20:03:56  No: 39313

いつもお世話になります。

VBScriptに引数を渡すにはどうすれば良いでしょうか?
下の方法では渡せませんでした。
アドバイスをお願い致します。
--------------------------------
var
  Fname : string;
begin
  FName := 'Test.vbs';
  ShellExecute(Handle, 'OPEN', PChar(FName),
  PChar('1'), nil, SW_NORMAL);
end;
--------------------------------
'test.vbs
msgbox WScript.Arguments.Item(0)


Kent  2010-10-07 21:14:22  No: 39314

Mr.Xrayさんのサイトで見つけました。
http://mrxray.on.coocan.jp/Delphi/plSamples/950_VBScript.htm#05
ありがとうございました。


Mr.XRAY  2010-10-07 21:31:46  No: 39315

こんにちは.Mr.XRAYです.
サイトご利用ありがとうございます.解決ということですが,

http://mrxray.on.coocan.jp/Delphi/plSamples/950_VBScript.htm#05

はちょっと質問の趣旨とは意味あいが違うと思われますが.
VBScriptに限らず,ShellExecuteでコマンドライン引数を渡して起動する場合,
Stringとして明示的にキャストすれば渡せます.

動作確認は,Windows XP(SP3) + Delphi 2010(UP5) Pro

procedure TForm1.Button1Click(Sender: TObject);
var
  Fname : String;
  Para  : String;
begin
  FName := 'Test.vbs';
  Para  := '1';
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar(Para), nil, SW_NORMAL);
end;

あるいは

procedure TForm1.Button2Click(Sender: TObject);
var
  Fname : String;
begin
  FName := 'Test.vbs';
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar(String('1')), nil, SW_NORMAL);
end;


Mr.XRAY  2010-10-07 21:41:14  No: 39316

更に,あるいはNull文字を追加してやります.

procedure TForm1.Button3Click(Sender: TObject);
var
  Fname : String;
begin
  FName := 'Test.exe';
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar('1'+ #0), nil, SW_NORMAL);
end;


Fusa  2010-10-07 21:53:17  No: 39317

こんにちは。

http://yozda.exblog.jp/tags/Delphi/
こちらの方もページを作っておられるようです

プログラムにスクリプト機能が内蔵されると
いろんなことができそうで、いいですね。


Mr.XRAY  2010-10-07 22:47:48  No: 39318

>http://yozda.exblog.jp/tags/Delphi/

おおっ,こんなすばらしい記事が,サンクスです.

VBScriptの記事書くときFusaさんの記事を参考にさせていただきました.
このリンクの記事は見落としていたようです(調べたのか? > 自分)


Kent  2010-10-07 23:12:16  No: 39319

Mr.XRAYさん、Fusaさん
ありがとうございました。

質問の趣旨を断念し、スクリプトファイルに追記する方向で進んでいました(^^;
今まで漠然とやっていたのですが、
「Stringとして明示的にキャストすれば渡せます」でスッキリしました。

ところで、恥ずかしい話ですが、もしお時間ありましたら詳しく教えて下さい。
1.明示的にキャストしていない'1'はStringで無く何なのか。
2.'1'+ #0 の意味
    何故これが「String('1')」や「var Para:String;のPara:='1'」と
    同じ扱いになるのか。

キーワードが一般的すぎて検索しても該当の説明を見つけられずにおります。
よろしくお願いいたします。


Tent  2010-10-08 00:05:29  No: 39320

直接定数を書いたり、const S = '1'とした場合などは真の定数となり、型は可変です。
string型を必要とする引数として渡した場合はstring型に、PChar型を必要とする引数として渡した場合はPChar型になります。

簡単な例で示せば、

const Value = '1';
procedure ProcA(S: PChar);
procedure ProcB(S: string);

という前提の場合、

ProcA(Value); // ←このValueはPChar型
ProcB(Value); // ←このValueはstring型

というようにコンパイル時に自動的に変換されます。
これはstring型の変数にPChar型の定数を入れたり、
PChar型の変数にstring型の定数を代入するなど、
実行時に不要な変換が起こらないようにするためです。

つまり必要な型に応じて自動的に変換されるので、
PChar(String('1'))というようなキャストは不要ですし、
どちらの場合も自動的に末尾にnullが付加されるので、
PChar('1'+ #0)といった記述も不要です。
ただしconst Value: string = '1'といったように、
型付きの定数にした場合は変数と同じ扱いになるため、キャストが必要です。

// この辺りの動作はデバッグ実行時にIDEのCPUウィンドウを開くと分かります


Kent  2010-10-08 01:53:23  No: 39321

Tentさん、ありがとうございました。

◆上記案1
  var Para  : String;
  Para  := '1';
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar(Para), nil, SW_NORMAL);
  の場合はString型として定義済みの為、PChar(Para) とする必要がある。

◆上記案2
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar(String('1')), nil, SW_NORMAL);
  は、PChar(String('1'))  としなくても  '1'  だけで良い。

◆上記案3
  ShellExecute(Handle, 'OPEN', PChar(FName), PChar('1'+ #0), nil, SW_NORMAL);
  は型を定義していないため、PChar('1'+ #0) としなくても  '1'  だけで良い。

◆備考
  ①PChar(String('1')) や ②PChar('1'+ #0) が成功するのに、
  ③PChar('1') が成功しない理由は、
  ①はString('1')の時点で自動変換でヌル文字が付く、
  ②は手動でヌル文字を付けているが③は付いていないため。

という事なのですね。(備考部分は自信が無いですが…)
とても良く理解できました。
ありがとうございました。

◆メモ:String型とPChar型の関係
  ShellExecuteはWindows APIなので文字列を渡すには、
  DelphiでのString型とは違いポインタ変数であるPChar型を使う必要がある。
  PChar型は文字列の最後にヌル文字#0が付加してある型。


KHE00221  2010-10-08 09:20:22  No: 39322

var
   P:PChar
begin
   P := PChar('1') 

ここで1文字だけ指定すると本来 '' で囲まれた文字列が格納されている
アドレスを返さないといけないのに '' で囲まれた1文字のコード
を返しているみたい。

2文字以上あればアドレスを返してるのでバグのような気がするけど


Kent  2010-10-08 19:31:28  No: 39323

KHE00221さん
ありがとうございます。

上の備考で書いたものの
・PChar(String('1')) や PChar('1'+ #0) が成功するのに、
  PChar('1') が成功しない
点が、どうも納得できてなかったのですが、
バグであるとすると納得できます。

こんな単純(?)なバグってあるんですね...
言語のバグに遭遇することが初めてなので驚きです。


というより  2010-10-08 21:07:56  No: 39324

>ここで1文字だけ指定すると本来 '' で囲まれた文字列が格納されている
>アドレスを返さないといけないのに '' で囲まれた1文字のコード
>を返しているみたい。
>2文字以上あればアドレスを返してるのでバグのような気がするけど

バグではないと思いますよ。
Delphiは「文字列」と「文字定数」は同じ書き方になっていて、'1'と書くと「文字列」と「文字定数」の両方の解釈が出来ます。
「長さが 1 の文字列」は どの「文字型」とも互換性があり、1文字だけの場合は「明示的に文字列」としないかぎり「文字定数」とみなされるので、
> P := PChar('1');
のPの値が「文字列'1'の格納アドレス」にならず、「文字'1'の文字コード」になるのは当然です。
この場合の'1'は「文字定数」と解釈されるので、定数値 #$31 をPChar型にキャストしても $31 の値は変わりませんから。


Tent  2010-10-09 00:50:49  No: 39325

というよりさんの仰る通りバグではありません。
SizeOf('1')とSizeOf('11')の返値を見れば分かると思います。
ヘルプにも、長さが1の場合は(文字列型ではなく)文字型と互換性を持つ、と書いてあります。


Tent  2010-10-09 00:53:52  No: 39326

書き忘れましたが、キャストは最低限にしたほうが良いと思います。
上記の通り定数は自動的に適切な型に変換される機構がありますから、
不必要なキャストや意味を理解せずにするキャストは本来不要な問題を引き起こします。


Mr.XRAY  2010-10-09 02:33:36  No: 39327

あれまっ,
ちょっとした間にいろいろ参考になる内容が.
あまり解説付きでレスすると文章が長くなるし,嫌われそうなのでので省略しましたが.

PChar('1'+ #0)

のコード書いておけば終端文字のことを調べるかな〜と,想定して.

>書き忘れましたが、キャストは最低限にしたほうが良いと思います。

ですね.ということで,

PChar('1'),

もできればやめた方がいいです.もちろん,PChar(String('1'))も.
OPENにもつけていませんよね.
Delphiでは,型を指定して値を代入するという方法が良いかも知れません.
と言いつつ,私もよくやっていますけど.自戒も含めて.


KHE00221  2010-10-09 10:15:42  No: 39328

var
   P:PChar
begin
   P := Char('1')

の場合きちんとアドレスになるわけだが・・・・


KHE00221  2010-10-09 10:22:22  No: 39329

動きとしては
    P := PChar(100);
    P := PChar(300);
なんかと同じなんだよね・・・


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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