タスクスケジューラ起動のプログラムでコンソールを表示しない
目次
はじめに
タスクスケジューラで .bat ファイルやコンソールアプリを実行すると、黒いウィンドウ(コンソール)が一瞬表示される。 この黒いウィンドウの正体はコンソールホストウィンドウと呼ばれるもの。
Windows がコンソールアプリ(.bat ファイルは cmd.exe というコンソールアプリで実行される)を起動する時、コンソールホスト(conhost.exe)が起動され、そのコンソールホストにより黒い画面(コンソールホストウィンドウ)が表示される。コンソールアプリケーションはコンソールホストウィンドウを経由して入出力を行うことになる。
- コンソールアプリとコンソールホストの関係
[コンソールアプリ (プロセスID: XXXX)]
↑ 標準入出力 (stdin/stdout/stderr)
↓
[コンソールホスト(conhost.exe プロセスID: YYYY)]
↑ コンソールホストウィンドウ(黒いウィンドウ)
↓
ユーザーの画面、キーボード入力
PowerShell を使用して、コンソールを非表示にしてみる(失敗)
PowerShell で引数 -WindowStyle Hidden
を指定すると、コンソールホストにウィンドウを非表示にするように指示を出せる。
powershell -WindowStyle Hidden -Command "Start-Process [プログラム] -WindowStyle Hidden"
1つ目の -WindowStyle Hidden
は PowerShell
自体のウィンドウを非表示にして起動。
2つ目の -WindowStyle Hidden
は指定したプログラムを非表示で実行。
例)C:\var\ほげ.bat
を実行
powershell -WindowStyle Hidden -Command "Start-Process 'C:\var\ほげ.bat' -WindowStyle Hidden"
このコマンドを起動済みのコマンドプロンプトから実行すると、コマンドプロンプトが最小化され、実行が開始される。タスクバーのコマンドプロンプトをクリックするとウィンドウ表示に戻り、他のウィンドウは表示されない。
一見、期待通りに動作しているように思えるが「ファイル名を指定して実行(Win + R)」で、このコマンドを実行すると、黒いウィンドウが一瞬表示されてしまう。 これはアプリケーションの起動時にコンソールホストウィンドウが先に表示されてしまい、その後で -WindowStyle Hidden
が適用されるのが原因。タスクスケジューラに登録した場合も同様に黒いウィンドウが一瞬表示されることになる。
解決策
1. VB Script(WSH) を使用する
wscript.exe はコンソールアプリケーションではなく GUI アプリケーション。そのため、実行時にコンソールホストウィンドウは表示されない。(cscript.exe はコンソールアプリなので、コンソールホストウィンドウが表示される)
wscript.exe /e:vbscript /b "CreateObject(""WScript.Shell"").Run ""C:\var\ほげ.bat"", 0, False"
/e:vbscript
引数で渡したコードを VB Script として実行/b
警告、スクリプト エラー、または入力プロンプトを表示しないバッチモードを指定CreateObject("WScript.Shell").Run
- 第1引数: 実行するプログラム
- 第2引数: ウィンドウスタイル(0: 非表示)
- 第3引数: False: 非同期実行
タスクスケジューラに登録する場合
- プログラム/スクリプト
wscript.exe
- 引数の追加(オプション)
/e:vbscript /b "CreateObject(""WScript.Shell"").Run ""C:\var\ほげ.bat"", 0, False"
2. 「ログオン状態にかかわらず実行」を選択する
タスクスケジューラーのタスクのプロパティ > 全般タブの ユーザーがログオンしているかどうかにかかわらず実行する
を選択する。これを選択することでタスクは非対話型モードで実行される。非対話型モードの場合、コンソールホストウィンドウは表示されない。
- 非対話型モードの注意点
- ユーザーのデスクトップとは切り離されている
- Excel などの GUI アプリが実行できない場合がある
- ドライブレターを指定したネットワークドライブは見えない(UNCパスなら見えるはず)
- 実行するユーザーに「バッチジョブとしてログオンする権利」が必要