VBA 外部プログラムやコマンドライン(cmd.exe)の実行(shell)

■ Shell関数の基本構文

Shell(pathname [, windowstyle])
  • pathname:実行するプログラムのパスやコマンド(文字列)
  • windowstyle(省略可能):コマンド実行時のウィンドウの表示方法(整数)

■ windowstyleの主なオプション一覧

定数名説明
vbHide0ウィンドウを非表示
vbNormalFocus1通常のウィンドウでフォーカスあり
vbMinimizedFocus2最小化状態でフォーカスあり
vbMaximizedFocus3最大化状態でフォーカスあり
vbNormalNoFocus4通常ウィンドウでフォーカスなし
vbMinimizedNoFocus6最小化状態でフォーカスなし

■ 基本的な例

Sub RunNotepad()
Shell "notepad.exe", vbNormalFocus
End Sub

このコードはメモ帳(Notepad)を起動します。


■ コマンドプロンプト(cmd.exe)の実行例

例えば、コマンドラインでディレクトリを削除する場合:

Sub DeleteFolderViaCmd()
Dim folderPath As String
folderPath = "C:\TestFolder"

Shell "cmd /c rmdir /s /q """ & folderPath & """", vbHide
End Sub

解説:

  • cmd /c:コマンド実行後にウィンドウを閉じる
  • rmdir /s /q
    • /s:サブディレクトリ含めて削除
    • /q:確認なし(quietモード)
  • """:VBA内でダブルクォーテーションを文字として使う場合、3重にする必要があります(実際には1文字分)

■ 外部プログラムへの引数付き実行

Sub OpenFileWithProgram()
Dim filePath As String
filePath = "C:\example.txt"
Shell "notepad.exe """ & filePath & """", vbNormalFocus
End Sub

ダブルクォーテーションの扱いに注意が必要です。ファイル名にスペースがある場合、正しく囲まないとエラーになります。


■ Shell関数の戻り値とプロセスID

Dim pid As Long
pid = Shell("notepad.exe", vbNormalFocus)
MsgBox "起動されたプロセスID: " & pid

Shell関数は起動されたプロセスのIDを返しますが、プロセスの完了を待機することはできません。それには別のAPIが必要です(後述)。


■ ShellAndWait:Shellで実行後に完了を待つ方法

VBAやVBでは、Shellの実行を待機する標準機能はないため、Windows APIを使って「終了を待つ」関数を作成するのが一般的です。

ShellAndWait関数(API使用)

Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As LongPtr

Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As LongPtr, ByVal dwMilliseconds As Long) As Long

Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long

Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF

Sub ShellAndWait(cmd As String)
Dim pid As Long
Dim hProc As LongPtr

pid = Shell(cmd, vbHide)
hProc = OpenProcess(SYNCHRONIZE, False, pid)

If hProc <> 0 Then
WaitForSingleObject hProc, INFINITE
CloseHandle hProc
End If
End Sub

使用例:

Sub TestShellAndWait()
ShellAndWait "cmd /c timeout /t 5"
MsgBox "完了しました!"
End Sub

このコードは5秒待ってからメッセージを表示します。


■ ファイルの存在確認後に開く例

Sub OpenIfExists()
Dim path As String
path = "C:\test\document.txt"

If Dir(path) <> "" Then
Shell "notepad.exe """ & path & """", vbNormalFocus
Else
MsgBox "ファイルが存在しません"
End If
End Sub

■ トラブル回避のための注意点

問題対応方法
パスにスペースがある""" で囲む
コマンド完了を待たないShellAndWaitを使う
管理者権限が必要な操作通常のShellでは実行不可
実行できない/無反応パスやコマンドの文法ミスを確認する
32bit/64bit互換性Declare PtrSafe の使用に注意(特にVBA)

■ 応用:バッチファイルの実行

Sub RunBatchFile()
Shell "cmd /c ""C:\scripts\mybatch.bat""", vbHide
End Sub

■ まとめ

  • ShellはVB/VBAから外部コマンドやプログラムを呼び出す基本機能。
  • ファイルやパスにスペースがある場合はダブルクォーテーションで正確に囲む必要がある。
  • 実行後の完了待ちはAPIを使うことで可能(ShellAndWait)。
  • トラブルを避けるには、引数の構文や権限などにも注意する必要がある。
タイトルとURLをコピーしました