特定のアプリに終了イベントを送るには?

解決


takeshi  2005-10-31 03:46:36  No: 127101

VBScriptから特定のアプリを終了させたく、以下の様なスクリプトを書きました。

Set ws = WScript.CreateObject("WScript.Shell")
Set p = ws.Exec("hoge.exe")
ws.AppActivate(p.ProcessID)
WScript.Sleep 100
ws.SendKeys "%{F4}"

しかしこれだと「ws.AppActivate」の後、クリック等で「hoge.exe」が裏に回って
別のアプリが終了する場合があります。
特定のアプリケーションを強制終了するのではなく、「X」ボタンクリックや
ALT+F4と同じように終了させるにはどうすれば良いでしょうか?


魔界の仮面弁士  2005-10-31 18:06:27  No: 127102

Win32_ProcessクラスのTerminateメソッドを試してみるとか。


もげ  2005-10-31 19:14:37  No: 127103

魔界の仮面弁士殿お薦めの
http://wmifun.atinfinity.net/sample/win32_processc.html
か、
そのアプリのウィンドウ(FindowWindowで探して)
に対して、WM_CLOSEをSendMessageしてあげるとか。


takeshi  2005-11-01 00:06:41  No: 127104

Terminateメソッドはアプリが強制終了してしまうようなので、今回の目的には合いません。(アプリ側で終了処理を行いたいため。)
「WM_CLOSE」「SendMessage」を手がかりに調べて、以下のようなスクリプトを書いてみました。

set UserWrap = CreateObject("DynamicWrapper")
UserWrap.Register "USER32.DLL", "FindWindow", "i=ss", "f=s", "r=h" 
UserWrap.Register "USER32.DLL", "PostMessage", "i=huuu", "f=s", "r=l"
const WM_CLOSE = &h10
set ws = CreateObject("WScript.Shell")
ws.Run "NOTEPAD.EXE"
WScript.Sleep 500
hWnd = FindWindow(vbnullstring, "無題 - メモ帳")
WScript.Sleep 5000
result = UserWrap.PostMessage( hWnd, WM_CLOSE, 0, 0 )

しかし1行目でエラーになってしまいます。
「ActiveXコンポーネントはオブジェクトを作成できません。:'DynamicWrapper'」

参考にしたのは、
http://66.102.7.104/search?q=cache:s63wWTBlT24J:pc5.2ch.net/test/read.cgi/win/1100489339/100n-+DynamicWrapper+vbscript+wm_close&hl=ja&lr=lang_ja
の442以降です。

何か追加で記述すべきものが抜けているのでしょうか?
実行環境はWindowsXP SP2です。

よろしくお願いします。


Blue  2005-11-01 00:20:08  No: 127105

参考サイト
http://madia.world.coocan.jp/vb/API/AppWinExit.htm


魔界の仮面弁士  2005-11-01 00:47:03  No: 127106

> set UserWrap = CreateObject("DynamicWrapper")
> UserWrap.Register "USER32.DLL", "FindWindow", "i=ss", "f=s", "r=h" 
> UserWrap.Register "USER32.DLL", "PostMessage", "i=huuu", "f=s", "r=l"
1 つの DynamicWrapper オブジェクトに、複数の API を割り当てるのではなく、
それぞれの API ごとに、個別に生成した方が無難です。

> 「ActiveXコンポーネントはオブジェクトを作成できません。:'DynamicWrapper'」
下記の DynaCall をインストールしないと使えません。http://people.freenet.de/gborn/WSHBazaar/WSHDynaCall.htm


takeshi  2005-11-01 07:09:10  No: 127107

Blueさん>
サンプルを見てみたのですが、VBのコードですね。
VBの知識が無いため、これをどうやってVBScriptに変換すれば良いのかわかりません。
特に「Public Declare 〜」の部分なんですが、これはWindows APIを呼ぶための構文だと思うのですが
これをVBScriptでどう記述すれば良いのでしょうか。

魔界の仮面弁士さん>
「DynaCall をインストール」とはリンク先にあるdynwrap.dllをパスの通っているところに置けば良いのでしょうか。
ためしにVBScriptファイルと同じ階層に置いて実行してみましたが、うまく動きませんでした。

せっかく色々ヒントをいただいているにも関わらず、私の知識が未熟なためそれを活かす事ができなくて
申し訳ありません。
再びヒントをお願いいただけますでしょうか?


030  2005-11-01 09:25:24  No: 127108

リンク先に使い方が記されてるんですけど。

Using the Dynacall.dll
Download the ZIP-Archive and unpack the archive into a separate folder. The archive contains the source code, a few samples Michael Hines and other provides and the already compiled Dynacall.dll. Take care to get the Win 9x or the Win NT version. The register the DLL using the program RegSvr32.dll with the following command:

RegSvr32.exe <path>dynacall.dll
where <path> is the path to your folder containing the dll. Unregistering the dll may be done with the /u switch for RegSvr32.exe (although I got an error message for the Win 9x version during this step).

After you have registered the dll, you can use an automation object to call your external functions


takeshi  2005-11-02 08:21:58  No: 127109

サイトの方に説明が書いてあったんですね。
完全に見落としていました。
で、結果うまく動作させる事ができました。

ただ、DLLを組み込む際にレジストリを更新するのがちょっと怖いですね。
インストーラやアンインストーラを自前で用意するのも使いたい機能に対して大げさすぎますし。
このDLLに何か欠陥があった場合、自分で解決できないというのも将来的に不安です。
できればWindows標準の機能のみでVBScriptからアプリの終了処理を実現したいのですが、
無理なのでしょうか?

わがまま言ってばかりで本当に申し訳ありません。


Dental  2005-11-02 08:56:11  No: 127110

> できればWindows標準の機能のみでVBScriptからアプリの終了処理を実現したいのですが
どこまでを Windows 標準と呼ぶのかにもよるのでは。
たとえば初期バージョンの Windows 95 だと、コンポーネントを追加しないと、VBScript 自体が使えなかったりするわけですし。

まぁそれは極端だとしても、仕様を満たすための選択肢は、あまり無いでしょう。
MS のスクリプト関係の記事でさえ、Win32_Process.Terminate で終了させているようなので、WM_CLOSE に相当する方法が VBScript から呼べための機能が用意されているかとなると、かなり難しい注文だと思われます。

http://www.microsoft.com/japan/msdn/columns/scripting/scripting02142000.asp
http://msdn.microsoft.com/library/en-us/dnclinic/html/scripting02142000.asp

結局は、API に頼るしかないのでしょうけれども、VBScript からは API を呼び出せないので、外部コンポーネントに頼らざるを得ませんしね。

DynaCall なども使いたくないという事であれば、いっそ、(C言語等で) APIを呼ぶアプリを作った方が無難な気がします。前提条件からは外れますが。

どうしても VBScript で行いたい、そして、API 呼び出しが必要という事であれば、VBScript から Excel 等を操作して、そこから VBA 経由で API を呼び出すという方法もあります。もちろん、Office がインストール済みというのが必須条件になってしまいますし、セキュリティ的な制限もありますけど。

Office すら使いたくないのであれば、あとは Microsoft .NET Framework とか。
VB.NET でアプリを作って、それを配布して、あるいはそのアプリをVBScript から呼び出すとか……(ここまで来ると、もはや本末転倒ですが)


あん  2005-11-02 09:42:05  No: 127111

WindowsXP PEだと
taskkillというコマンドがあるんですけどね


takeshi  2005-11-02 10:09:43  No: 127112

Dentalさん>
やはりWindows標準機能では無理ですか‥‥。

私は本来マックユーザなんですが、マックならAppleScriptで

tell application "iTunes"
    quit
end tell

と書くだけなのでWindowsも簡単にいけるだろうとタカをくくってたのですが、甘かったようです。
なんでVBScriptにこだわっているかというと、実行ファイルをユーザ環境にインストールしなくても良いからです。
(アプリ側でスクリプトファイルを自動生成。終了時にファイル削除、という運用です。)
ユーザが複数の場所に結構な人数いるので、なるべく導入コストを減らしたいのです。

仕方ないので最初に書いたSendKeysを使用して終了させる事にし、ユーザには
「絶対画面を動かしちゃダメ!」
と説明する事にします。

あんさん>
PEとはProfessional Editionの事でしょうか。
ユーザは全員XP Proなのでtaskkillコマンドの事も調べてみます。

アドバイスいただきました皆さん、本当にありがとうございました。


あん  2005-11-02 10:16:07  No: 127113

>あんさん>
>PEとはProfessional Editionの事でしょうか。
>ユーザは全員XP Proなのでtaskkillコマンドの事も調べてみます。
そうです。
じゃ解決できるかも
がんばってください


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

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






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