はじめに
Exec実行中コマンドプロンプトがずっと表示されるのがうっとうしい!
ExcelやAccessで外部のexeを起動してやりとりしたいことって多々あると思います。
外部のexeを起動する関数としてRunとExecが有名だと思いますが、Runはコマンドプロンプトを非表示にする引数がありますが、Execにはありません。ですがExecには標準入出力から値を受け渡しできるメリットがあります。
今回はExecで外部exe実行中勝手に表示されるコマンドプロンプトを無理矢理非表示にしてやろうという記事です。
方法は「Exec実行後コマンドプロンプトが表示されていればそのウインドウをサイズ変更する」というものです。
使用するWinAPI
・FindWindow
・IsWindowVisible
・GetClassName
・GetNextWindow
・MoveWindow
・Sleep
以下64bit環境ならそのままコピペで宣言できます。
32bitならばPtrSafeを消したり少し手を加える必要があるかと思います。(#if Win32で環境によって場合分けできるといいかも)
'ウインドウハンドルを取得する
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
'ウインドウが可視かどうかを取得する
Declare PtrSafe Function IsWindowVisible Lib "user32" _
(ByVal hwnd As Long) As Long
'ウインドウのクラス名を取得する
Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'取得中のウインドウの次または前のウインドウハンドルを取得する
Declare PtrSafe Function GetNextWindow Lib "user32" Alias "GetWindow" _
(ByVal hwnd As Long, ByVal wFlag As Long) As Long
' 指定されたウィンドウの位置およびサイズを変更
Declare PtrSafe Function MoveWindow& Lib "user32" (ByVal hwnd&, ByVal X&, ByVal y&, ByVal nWidth&, ByVal nHeight&, ByVal bRepaint&)
'遅延
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
サイズ変更サブルーチン
Sub コマンドプロンプトが開いていれば最小化する()
Dim ret As Long
Dim className As String
Dim i As LongPtr
i = 1
Const GW_HWNDLAST = 1
Const GW_HWNDNEXT = 2
Dim strClassName As String * 100
Dim strCaption As String * 80
Dim hwnd As Long
hwnd = FindWindow(vbNullString, vbNullString) '引数を両方ともvbNullStringにして1つめのウインドウを取得する
Do
GetClassName hwnd, strClassName, Len(strClassName) ' クラスネームの取得 プロンプトなら ConsoleWindowClass
If IsWindowVisible(hwnd) Then '見えているウインドウならば
className = Left(strClassName, InStr(strClassName, vbNullChar) - 1)
If "ConsoleWindowClass" = className Then 'コマンドプロンプトが開いていれば
ret = MoveWindow(hwnd, 0, 0, 1, 1, True) 'そのウインドウをサイズ変更 引数(ウインドウのオブジェクト,X,Y,幅,高さ,再描画?)
End If
End If
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT)
Loop Until hwnd = GetNextWindow(hwnd, GW_HWNDLAST)
End Sub
'比較部分を変えればコマンドプロンプト以外にも応用できるかと思います。
'引数として与えてもいいかもです。
If "ConsoleWindowClass" = className Then 'コマンドプロンプトが開いていれば
使用例
Exec実行の1秒後にコマンドプロンプトのウインドウサイズを変更します。
'通信用exeファイル起動
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
'プロンプトの表示完了までを待つ
Call Sleep(1000)
'十分に待ったところでプロンプト画面サイズ変更処理
Call コマンドプロンプトが開いていれば最小化する()
'戻値を受け取る exe側の処理が終わるまでここで止まる
Result = wExec.StdOut.ReadAll