質問するログイン新規登録

回答編集履歴

1

追記

2016/06/08 03:18

投稿

jawa
jawa

スコア3021

answer CHANGED
@@ -4,4 +4,122 @@
4
4
  ```
5
5
  lngPid = Shell("notepad.exe", vbNormalFocus)
6
6
  ```
7
- を行い、新たなメモ帳を起動し、そのウィンドウハンドルに対してクロ-ズしているからではないでしょうか?
7
+ を行い、新たなメモ帳を起動し、そのウィンドウハンドルに対してクロ-ズしているからではないでしょうか?
8
+
9
+ 追記
10
+ ---
11
+ TerminateProcessで完結したものと思い込んでいましたが、まだ未解決のようでしたので遅くなってしまいましたが追記いたします。
12
+
13
+ ---
14
+
15
+ まず、CloseHandleについてですが、ハンドルを解放する関数とされているので私もこれで終了できるつもりでいましたが、実際できないようです。
16
+ ここらへん知識乏しくて申し訳ないです。※詳しい方いましたら補足お願いしますm(__)m
17
+
18
+ ---
19
+
20
+ 次にOpenProcessについてですが、この戻り値はプロセスのハンドルでありウィンドウハンドルではありません。
21
+ このため、取得結果に対してSendMessageしても目的のウィンドウには届きません。
22
+ ※運が悪ければ意図しない他のアプリを終了してしまうかもしれません。
23
+
24
+ ---
25
+
26
+ 最後にTerminateProcessについてですが、これはプロセスIDを使ってプロセスを終了することができます。
27
+ しかしタスクマネージャから強制終了(KILL)させているような終了方法なので、あまり好ましい方法ではありません。
28
+
29
+
30
+ ---
31
+
32
+ TerminateProcess以外の方法で終了させる方法を紹介します。
33
+
34
+ 方法1:プロセスIDでアプリをアクティブ化して、SendKeyで終了操作を送信する。
35
+ ```
36
+ Sub Sample1()
37
+ 'メモ帳をShell起動してプロセスIDを取得
38
+ lngPid = Shell("notepad.exe", vbNormalFocus)
39
+ Call Shell("calc.exe", vbNormalFocus) '←ダミーで別アプリも起動
40
+
41
+ 'プロセスIDでアプリをアクティブ化
42
+ Call AppActivate(lngPid)
43
+
44
+ 'メモ帳の終了操作(Alt→F→X)をSend
45
+ Application.SendKeys "%FX"
46
+ End Sub
47
+ ```
48
+ 対象アプリを一度アクティブ化するので、画面最前面に表示されることになります。
49
+
50
+
51
+ 方法2:プロセスIDからウィンドウハンドルを取得する
52
+ ```
53
+ Option Explicit
54
+
55
+ 'WindowsAPI定義
56
+ Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
57
+ Public Declare Function IsWindowVisible Lib "user32.dll" (ByVal hwnd As Long) As Long
58
+ Public Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As Long, ByRef ProcessId As Long) As Long
59
+ Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
60
+
61
+ '定数定義
62
+ Public Const WM_CLOSE = &H10
63
+
64
+ '共通変数
65
+ Public lngPid As Long
66
+ Public lngWid As Long
67
+
68
+ Sub Sample2()
69
+ Dim lWid As Long
70
+
71
+ 'メモ帳をShell起動してプロセスIDを取得する
72
+ lngPid = Shell("notepad.exe", vbNormalFocus)
73
+ Call Shell("calc.exe", vbNormalFocus) '←ダミーで別アプリも起動
74
+
75
+ 'プロセスIDからウインドウハンドルを取得
76
+ lWid = GetHwndFromPid(lngPid)
77
+
78
+ If lWid = 0 Then
79
+ MsgBox "NotFound"
80
+ Exit Sub
81
+ End If
82
+
83
+ Call SendMessage(lngWid, WM_CLOSE, 0&, 0&)
84
+
85
+ End Sub
86
+
87
+ 'プロセスIDからウィンドウハンドルを検索
88
+ Public Function GetHwndFromPid(ByVal pid As Long) As Long
89
+ Dim hwnd As Long
90
+ '初期化
91
+ lngWid = 0
92
+ Call EnumWindows(AddressOf GetProc, 0)
93
+
94
+ GetHwndFromPid = lngWid
95
+
96
+ End Function
97
+
98
+ 'EnumWindowsのコールバック関数
99
+ Public Function GetProc(ByVal hwnd As Long, lParam As Long) As Boolean
100
+ GetProc = True
101
+ If IsWindowVisible(hwnd) <> 0 Then
102
+ '非表示ウィンドウでない場合、PIDのチェック
103
+ If GetPidFromHwnd(hwnd) = lngPid Then
104
+ '同じPIDを見つけたら、ウィンドウハンドルを格納
105
+ lngWid = hwnd
106
+ '戻り値FalseでEnumWindowsのループが終了
107
+ GetProc = False
108
+ End If
109
+ End If
110
+ End Function
111
+
112
+ 'ウィンドウハンドルからをプロセスIDを取得
113
+ Public Function GetPidFromHwnd(ByVal hwnd As Long) As Long
114
+ Dim pid As Long
115
+
116
+ Call GetWindowThreadProcessId(hwnd, pid)
117
+
118
+ GetPidFromHwnd = pid
119
+ End Function
120
+ ```
121
+ APIも多く、コールバック関数を使ったりと難易度高めになってしまいますが、ウィンドウハンドルを取得する場合はこの方法が確実です。
122
+
123
+ ---
124
+
125
+ 遅レスとなってしまいましたが、参考になれば幸いです。