• ベストアンサー

VB6.0 SHELLで起動したプログラムを終了さしたいのですが

(1)メインプログラムから電卓を実行します。  Shell("C:\WINNT\system32\CALC.EXE", 1) (2)メインプログラムで電卓を終了させるにわ、どうすればいいのですか  教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.5

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。 Microsoftの終了方法と、定数が違いますが、こちらでも終了ができます。 コメントを見たら、処理の流れがわかると思いますが、処理の流れを記します。 Shellで電卓を起動します。Shell関数は起動したアプリのプロセスIDを返します。 次に Call EnumWindows(AddressOf EnumWinProc, 0&)を実行します。 これはたった一文で、FOR文/DO~LOOP文を使用してませんが、EnumWinProc関数内を何度も実行します。実行回数はWindowsに存在するハンドルの数だけ実行されます。 そしてその関数内で電卓のプロセスと同じハンドルを探し、電卓に終了の命令を送ってます。 EnumWinProc内を詳しく説明します。 GetParentが'0'ゼロの時、未処理としています。 これは何を意味するかというと、フォームだけでなく、フォームの中に存在するボタン、リストボックス、ラベル、それぞれのコントロールにハンドルが存在します。 しかしフォームとその中のコントロールには親子の関係があります。 GetParent(子のハンドル)の時 → '0以外'の数値を返します。基本的にフォーム(親)のハンドルのを返します。 GetParent(フォームのハンドル)の時 → '0'を返します。親が存在しないためです。 電卓にも多くのボタンが存在してます。そのボタンのハンドルはチェックする必要がないのでGoto文で未処理にさせています。必要なのは電卓本体が必要で、GetParentで0を返すものが、チェックの候補となるわけです。 あとは電卓のプロセスと比較し、一致するハンドルを取得するだけです。 Option Explicit ' ウィンドウのプロセスIDとスレッドIDを取得する関数の宣言 Private Declare Function GetWindowThreadProcessId Lib "user32.dll" _   (ByVal hwnd As Long, lpdwProcessId As Long) As Long '親ハンドルを取得する関数の宣言 Private Declare Function GetParent Lib "user32" _   (ByVal hwnd As Long) As Long 'ウィンドウを列挙する関数の宣言 Public Declare Function EnumWindows Lib "user32" _   (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long 'ウィンドウにメッセージ定数を送る関数の宣言 Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _   (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long Public Const WM_CLOSE = &H10 '見つかったウィンドウハンドル Private FindWinWnd As Long '探すべきプロセス Private FindPrs   As Long Sub Main()   Dim lngSts As Long   '初期化を行う   FindWinWnd = 0   FindPrs = 0   'とりあえず電卓を起動と同時に、電卓のプロセスを得る   FindPrs = Shell("Calc.exe")      'プロセス=0のとき起動失敗   If FindPrs = 0 Then     MsgBox "電卓の起動失敗"     GoTo PGMEND   End If      'Windowsに存在する全部のハンドルから、電卓のプロセスの一緒のハンドルを探す   Call EnumWindows(AddressOf EnumWinProc, 0&)      '電卓を終了します。   If (FindWinWnd <> 0&) Then     MsgBox "電卓が見つかりませた。終了します。"     Call SendMessage(FindWinWnd, WM_CLOSE, 0&, 0&)   Else     MsgBox "電卓が見つかりませんでした。"   End If    PGMEND: End Sub 'Windowsの全ハンドルを得ることができる関数 '内部処理は、 '(1)指定のプロセスを探す '(2)見つかったプロセスのハンドルを記憶 Public Function EnumWinProc(ByVal hwnd As Long, lParam As Long) As Boolean   Dim lngTrd As Long 'スレッド   Dim lngPrs As Long 'プロセス      'Trueの間は、Windowsに存在するハンドルを最後まで取得しようとする   EnumWinProc = True      '子ウィンドウは未処理   If Not (GetParent(ByVal hwnd) = 0) Then GoTo PGMEND      'スレッドとプロセスを取得する   lngTrd = GetWindowThreadProcessId(hwnd, lngPrs)      '同じプロセスだとしたら   If lngPrs = FindPrs Then     '取得してきたハンドルを記憶     FindWinWnd = hwnd     'これ以上のハンドルは取得しないでもいいので、Falseをセット     EnumWinProc = False   End If    PGMEND: End Function

chiba-masaru
質問者

お礼

ありがとうございました、いちどためさしていただきます。 また何かありましたらよろしくお願いします。

その他の回答 (4)

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.4

あっSendMessageの回答がでましたね。 で注意して欲しいのは、FindWindowを使う点です。 これはWindowのCaption、もしくはクラス名でWindowを探す点です。 クラス名は[CTRL]+[ALT]+[DEL]で起動中のアプリのクラス名の一覧が出てきます。 あれから参考にしてみてください。 電卓は複数起動が可能です。 Microsoftのサンプルでは、すでに電卓を起動してあったとき、先に起動してあったほうを終了させるおそれがあります。 よってFindWindowだけでWindowを探すには注意が必要です。 (それでもSendkeysよりは、かなりいいと思います。) もし自分で作成したソフトをShellで起動するなら、このままでも大丈夫かもしれませんが、そうでなければShellで起動した時のプロセスIDを取得して、起動中のアプリ達のプロセスIDと比較し、自分の起動したEXEかをチェックする必要があるのです。 今までのサンプルで大丈夫ならいいのですが、帰ってから締め切ってなかったら、またあとで書き込みます。 ちなみに書き込もうとしてるサンプルはVB6限定です。

chiba-masaru
質問者

お礼

ありがとうございました、いちどためさしていただきます。 また何かありましたらよろしくお願いします。

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.3

API関数を使うなら...

参考URL:
http://www.microsoft.com/JAPAN/support/kb/articles/j044/1/40.htm
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.2

Sendkeys は一番手っ取り早いです。 確かにHELPにも出ています。 しかし、どのVBのメーリングリストもSendkeysは使用しない方向でやっております。 それはWindowsにかかっている負荷の状況により、Sendkeysの処理が必ずしも一致するわけではないからです。 以前にサンプルを作ったのですが、どうやら自宅においたままになっているようなので、またあとで書き込みます。 キーワードはSendMessageです。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

SendKeyで終了のキー操作情報を送信してやります。 たしかHELPのサンプルが電卓を終了させるものだったと記憶しています。

関連するQ&A

  • エクセルで電卓表示

    いろいろネット検索して下記の記述で電卓が呼び出せるのはわかりました。 Sub 電卓呼び出し() x = Shell("C:\WINNT\system32\calc.exe") End Sub ただ、この記述だと、calc.exeのある場所が限定されてしまい、そこになければエラーになります。 calc.exeを検索して呼び出すためにはどのように書き換えればいいのでしょうか? それから x = Shell の意味を教えていただけると幸いです。

  • WSHプログラミングで、Shell実行プロセスが終了しない内に、次の処理が実行されちゃいます・・・

    WSH(WindowsScriptingHost)でプログラミングを行っております。 以下のように、「A.exe」実行後、「B.exe」を実行するようにスクリプトを記述しています。 ところが、実際に実行してみると、「A.exe」が終了しない内に、「B.exe」が実行されてしまっている様なのです。 しかし、プログラム処理上、「A.exe」が実行終了してからでないと、「B.exe」を実行するのはまずいのです。 WSHで、「A.exe」が実行終了するまで、「B.exe」を実行させないようなスクリプトの記述方法を教えて下さい。 Set Shell = CreateObject("WScript.Shell") Shell.Run "cmd.exe /c D:\A.exe" Shell.Run "cmd.exe /c D:\B.exe"

  • VBで別のプログラムを起動し他の処理を中断したい

    VBプログラムの実行中に、shell("hoge.exe")で別のプログラムを起動しそのプログラムが終了すれば次の処理に移るという処理をしたいんですが、実現方法がわかりません。どうすればよいでしょうか?アドバイスよろしくお願いします。

  • VBAのShellの同期的実行

    ExcelVBAについての質問です。コマンドプロンプトで実行するプログラムをCで作成しました(これをXXX.exeとします)。このプログラムは計算が終了した後で、その結果のファイルを作成します(これをYYY.txtとします)。このプログラムを操作し、結果を表にして出力するために、ExcelVBAでshellを使って以下のようなプログラムを作成しました。   shell("XXX.exe")   call Output Outputでは、XXX.exeが作成したファイルYYY.txtからデータを読み込んでシートに結果を出力するのですが、うまくファイルを読み込みません。多分、shellにより実行したXXX.exeが終了する前にOutputが呼ばれているのだと思うのですが、もしそうだとしたらどのような解決方法があるのでしょうか。よろしくお願いします。 WinXp、Excel2000です

  • VB6のWScript.Shellについて

    VB6のWScript.Shellで、他のVB6プログラムを起動する時の戻り値について教えてください。 AというVBプログラムからBというVBプログラムを起動するシステムがあります。 Bというプログラムで取得した値をAに返す方法はありますでしょうか? Aのソースは以下の通りです。 --------------------------------------------- sub test() dim objWshShell set objWshShell = Wscript.CreateObject("WScript.Shell") objWshShell.Run "C:\B.exe" & " " & hikisu1 & " " & hikisu2 , 1, wait End Function ---------------------------------------------- objWshShell.Runの戻り値はtrueまたはfalseのみのようです。 B.exeからtrue、false以外の値を取得する方法はありますか? また、やり方はobjWshShell.Runでなくてもよいです。 よろしくお願いします。

  • Shell関数で起動したメディアプレーヤーを終了したい。

    以前このコーナーで質問して教えて頂いたShell関数でメディアプレーヤーを起動できました。(以下にそのコーディングを記載しました) 今度は起動したメディアプレーヤーをVBから終了する方法が知りたいのですが教えて頂けませんか。 Shell ("C:\Program Files\Windows Media Player\wmplayer.exe /1 G:\TEST.wma ,vbMinimizedFocus") 宜しくお願いします。

  • VBプログラムの終了

    VB6.0で作成した実行ファイル(exe)を終了させても タスクマネージャのプロセスに残ってしまい、 もう一度プログラムを起動することができません。 (プログラムで二重起動防止の処理をしています) このプログラムをVBのラインタイムが入っていない マシンで動かしているのですが、 やはりそれが問題なのでしょうか? それとも別に何か原因があるのでしょうか?

  • Access2000vbaで、shell関数で起動させたExcellを終了する方法を教えてください。

    Access2000vbaで、shell関数で起動させたExcellを終了する方法を教えてください。 以下のように、shell関数で、既存のExcelファイルを起動させました。 どうすれば、Excelファイルを終了できますか? 宜しくお願いします。 Dim fl_name As String fl_name = "C:\XE2.xls" Shell "C:\Program Files\Microsoft Office\Office\EXCEL.EXE " & fl_name, vbNormalFocus

  • Shell とcmd.exe /c start

    Shell "cmd.exe /c start " & Label1.Caption ラベルにURLを設定し、クリックした時にURLに飛ぶとあります。 コードの理解が難しく、お助け頂けませんか。 プログラミングもPCもド素人ですのでご了承下さい。。。 Shell:実行可能なプログラム(この場合ならcmd.exe?)を実行し、実行が完了するとプログラムのタスクIDを示す(このタスクidでプログラムを操作することになるのだろうか?)。 cmd.exe:コマンドプロンプト cmd.exe/c:コマンドプロンプトで特定のコマンド(URL先へ飛ぶ?)を実行後に終了させる? Label1.Caption:ラベルの内容(URL) startがわからない。何をstartするためのstart? cmd.exeのstart(起動)をShellが実行して、URL先に飛ぶ命令は残りのコードにある? 参照ページでも歓迎です。宜しくお願いします。

  • VB6.0 Shellによる終了監視について

    VB6.0について困っております。 VB6.0にてファイル管理ソフトを開発しています。VBより他アプリ(MS OfficeやAutoCAD等)ファイルを起動させ、終了を監視(終了処理実行のため)しています。 具体的にはWshのshell.Runコマンドを使用して wsh.run("アプリ",NormalFocus,True)として起動させています。 ここで、複数ファイルを起動した場合、最後に起動したファイルが終了しないと、他の終了が検知できません。 例) ファイルAを起動 ファイルBを起動 ファイルCを起動 ファイルDを起動 ↓ ファイルAを終了 ←終了しても終了検知しない ファイルBを終了 ←終了しても終了検知しない ファイルCを終了 ←終了しても終了検知しない ファイルDを終了 ←終了するとA・B・C・Dの終了をまとめて検知し終了処理実行 これを、各ファイルごとに終了を検知させる方法はありませんでしょうか? よろしくお願い致します。