OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

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

  • すぐに回答を!
  • 質問No.157242
  • 閲覧数1883
  • ありがとう数9
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 23% (40/169)

(1)メインプログラムから電卓を実行します。
 Shell("C:\WINNT\system32\CALC.EXE", 1)
(2)メインプログラムで電卓を終了させるにわ、どうすればいいのですか
 教えてください。
通報する
  • 回答数5
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

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

  • 回答No.5
レベル12

ベストアンサー率 65% (276/422)

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。
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

お礼率 23% (40/169)

ありがとうございました、いちどためさしていただきます。
また何かありましたらよろしくお願いします。
投稿日時 - 2001-10-25 23:19:01
-PR-
-PR-

その他の回答 (全4件)

  • 回答No.1
レベル14

ベストアンサー率 33% (1403/4213)

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

たしかHELPのサンプルが電卓を終了させるものだったと記憶しています。


  • 回答No.2
レベル12

ベストアンサー率 65% (276/422)

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

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

ベストアンサー率 59% (729/1235)

API関数を使うなら... ...続きを読む
  • 回答No.4
レベル12

ベストアンサー率 65% (276/422)

あっSendMessageの回答がでましたね。 で注意して欲しいのは、FindWindowを使う点です。 これはWindowのCaption、もしくはクラス名でWindowを探す点です。 クラス名は[CTRL]+[ALT]+[DEL]で起動中のアプリのクラス名の一覧が出てきます。 あれから参考にしてみてください。 電卓は複数起動が可能です。 Microsoftのサンプルでは、すでに電卓 ...続きを読む
あっSendMessageの回答がでましたね。

で注意して欲しいのは、FindWindowを使う点です。
これはWindowのCaption、もしくはクラス名でWindowを探す点です。
クラス名は[CTRL]+[ALT]+[DEL]で起動中のアプリのクラス名の一覧が出てきます。
あれから参考にしてみてください。

電卓は複数起動が可能です。
Microsoftのサンプルでは、すでに電卓を起動してあったとき、先に起動してあったほうを終了させるおそれがあります。
よってFindWindowだけでWindowを探すには注意が必要です。
(それでもSendkeysよりは、かなりいいと思います。)

もし自分で作成したソフトをShellで起動するなら、このままでも大丈夫かもしれませんが、そうでなければShellで起動した時のプロセスIDを取得して、起動中のアプリ達のプロセスIDと比較し、自分の起動したEXEかをチェックする必要があるのです。

今までのサンプルで大丈夫ならいいのですが、帰ってから締め切ってなかったら、またあとで書き込みます。

ちなみに書き込もうとしてるサンプルはVB6限定です。
お礼コメント
chiba-masaru

お礼率 23% (40/169)

ありがとうございました、いちどためさしていただきます。
また何かありましたらよろしくお願いします。
投稿日時 - 2001-10-25 23:19:25
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ