ゆるおたノート

Tomorrow is another day.

【バッチファイル】指定した順番にアプリケーションを開くスクリプトを書いてみた

スタートアップフォルダにいくつかショートカットを入れておいて、PCを立ち上げて、アプリケーションの起動を待つ…

これだけでも結構便利なのですが、ふと「これ、順番も指定できるといいのにな…」と思いました。

少し調べてみたところ、バッチファイルの練習にも良いらしいので、スクリプトを書いてみました。

スタートアップの起動順を指定するスクリプト

:::
:: メイン処理
:Main
  @rem ▼前処理
  @rem ウィンドウ出力を消す
  @echo off
 
  @rem ▼アプリを順次起動
  call :openApps
 
@rem ▼コマンドプロンプトを閉じて終了
exit
  
::  ~以下、関数シーケンス~
  
:::
:: アプリを指定順に起動する
::
:: 【参考】
:: Windows、バッチファイル(.bat)を終了するときは「exit」ではなく「exit /B」を使おう|マコトのおもちゃ箱 ~ぼへぼへ自営業者の技術メモ~
:: http://piyopiyocs.blog115.fc2.com/blog-entry-884.html
::
:: @note
::  パスにスペースがあるとエラーが出て実行できないので、パスも""で囲むこと。
:: 【例】────────────────────────
:: start "" /max "C:\xxx.xxx"
:: call :sleep
:: ────────────────────────────
:openApps
 
  rem GoogleChrome.exe(ユーザーごとに開く)
  set chromeExe="C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
 
    @rem userA
    set userA="Default"
    start "" /max %chromeExe% --profile-directory=%userA%
 
    @rem 別ウィンドウでChatworkのアプリも開く
    set chatworkId="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    start "" /max %chromeExe% --profile-directory=%userA% --app-id=%chatworkId%
    call :sleep
 
    @rem userB
    set userB="Profile 1"
    start "" /max %chromeExe% --profile-directory=%userB%
    call :sleep
 
  rem Slack.exe
  set slackExe="C:\Program Files\Slack\Slack.exe"
  start "" /max %slackExe%
  call :sleep
 
  rem Evernote Clipper.exe
  start "" "C:\Program Files (x86)\Evernote\Evernote\EvernoteClipper.exe"
  call :sleep
 
  @rem 関数シーケンスの終了
exit /B
 
:::
:: 処理と処理の間に休憩を入れる
:sleep
  @rem 3秒待つ(`/nobreak`でキャンセル待ちをoff)
  timeout /t 3 /nobreak > null
 
  @rem 関数シーケンスの終了
exit /B

バッチファイルの使い方をざっくりと

コマンドの実行順

基本的に上から順に実行され、最後に指定したウィンドウが最前面の状態で終了する。
今回はアプリケーションを複数起動するスクリプトなので、上から順に開かれていく。

そのため、性能の良いのPCなら「すぐ使いたいもの」を先頭に置くと良いかも。
例えば、最初にExcelの勤怠シートを開いて、出勤時間を入力している間に他のアプリも開かれているようにする、とか。

また、PCを起動→ログインだけしておいてコーヒーを淹れに行くようなルーティンがある方であれば、「最初に使いたいもの」を最後の処理にすると良さそう。

ファイルの拡張子

スクリプトが書けたら、.batという拡張子で保存する。
はてなブログの仕様上、当記事ではコードの紹介部分でdosbatchと指定していますが、あまり深く考えないでください。)

これを好きなところに置いておいて、ダブルクリックで開くと処理が実行される。

文字化けに注意!

何も考えずVS Codeで書いて、そのまま実行してみたらビックリ。
文字化けするわ、「そんなコマンドはありません」とか出るわ…

VS Code文字コードUTF-8が基本*1だけど、Windowsコマンドプロンプトcmd.exeShift-JISにする必要がある。

というわけで、バッチファイルを作る時は文字コードを確認してから作業に入るのをお忘れなく!

※例えばVS Codeなら、setting.jsonワークスペースの設定の中であらかじめ指定しておくとラクになります。

"[bat]" : {
  "files.encoding": "shiftjis",
},

スクリプトの書き方

出力を消す

【例】基本の書き方
@rem ウィンドウ出力を消す
@echo off
コマンドを分解
処理の内容を見せない

echo offで、コマンドプロンプトのウィンドウ上にズラズラズラ~っと処理内容やコメントが表示されるのを止める。

echo off
命令文も見せない

また、コマンドの先頭に@とつけることで、命令文そのものの表示も止める。

@echo off

(*・ノェ・)コッソリ { 出力オフにしといてね~

これは、echo offだけでなく他のコマンドでも使える。

アプリケーションやファイルを開く

【例】基本の書き方

例えば、このような処理をしたい場合。

こんな時は、下記のように書く。

@rem (例)"C:\xxx.xxx"のファイルを開く
start "" /max "C:\xxx.xxx"
新規ウィンドウで開くコマンド

startコマンドで、指定したパスのファイルを新しいウィンドウで開く。
今回の場合は、下記のような構文。

start [ウィンドウのタイトル] [オプション] [パス]
引数 使い方
タイトル コマンドプロンプトのウィンドウに表示するタイトル。
""と指定すると、処理が終わった時にコマンドプロンプトのウィンドウも自動で閉じられる。
オプション /maxと指定すると、ウィンドウサイズを最大に指定できる。
パス パスにスペースが含まれている場合、エラーが出て実行できなくなる(後述)。
""で囲むとこのエラーを回避できる。

※他にもオプションがあるようなので、詳しく知りたい方はこちらへ。

変数を使う
変数の定義

変数は、下記のように定義する。

set 変数名=

例えば文字列を代入する場合は下記のように。

set 変数名="文字列"

""は無くても良い。
…のだけど、パスのようなスペースを含む文字列があるときは注意が必要になる。

startコマンドのように引数を複数使えるコマンドを実行する時に、別々の引数として認識されてしまい実行時にエラーが起きるもとになる。

とりあえず、クセとして"文字列"で指定するようにしておく。
そもそも、ファイル名やフォルダ名にスペースを使わないようにした方が良いかも…

変数の呼び出し

呼び出す時は、変数名を%で挟む。

%変数名%

複数の変数を連結する時は、こんな感じに詰めて並べる

%変数名1%%変数名2%

変数の間のスペースも文字列とみなされる
先ほどのパスの話と少し混乱するけど、文字列の連結の場合は間を詰める。

【例】Chromeをユーザーごとに開く

ここまでを踏まえて、例えばGoogle Chromeをユーザー別やWebアプリ別に開く場合は、下記のように書ける。

@rem Chromeのパス
set chromeExePath="C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
 
@rem UserAとしてChromeを開く
set userA="Profile 1"
start "" /max %chromeExePath% --profile-directory=%userA%
 
@rem 別ウィンドウでChatworkのアプリも開く
set chatworkId="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
start "" /max %chromeExePath% --profile-directory=%userA% --app-id=%chatworkId%
call :sleep
 
@rem UserBとしてChromeを開く
set userB="Profile 2"
start "" /max %chromeExePath% --profile-directory=%userB%
ちなみに…

Chromeスクリプトで起動する方法(と失敗談)について、別途記事にしています。

【バッチファイル】何やらSTARTできてないモノが…? - ゆるおたノート

処理を一時停止する

【例】基本の書き方

例えば、いま2つのファイルがあるとして、ファイルA(重め)・ファイルB(軽め)と呼ぶとする。
これらをファイルAファイルBの順に開く時、ファイルAを開いている間はファイルBを開く命令をうまく処理できないらしく、ファイルBは開いてくれないことがある。

その対策として、処理の準備をする意味で命令と命令の間に少しだけ待ち時間を設けることにする。

@rem sleep関数の定義
:sleep
  @rem 3秒待つ(キャンセル待ちはしない)
  timeout /t 3 /nobreak > null
exit /B

今回はこれをsleep関数としておく。

※なお、本来はバッチファイルに「関数」という概念は無く、正しくは「サブルーチン」というらしい。
当記事ではこのまま「関数」と呼ぶことにする。使い方は後述

コマンドを分解

timeoutコマンドで、一旦処理を止める。

@rem
timeout /t 3 /nobreak > null
待ち時間を指定する

/t 3で「3秒間待つ」という意味になる。

@rem 3秒間待つ
timeout /t 3

ただ、この場合、timeoutコマンドの実行中にコマンドプロンプトの画面に触れてしまうと、「キャンセル待ち」の状態になる。
この状態で何かキーを入力すると、「キャンセル」となって処理が中止されてしまう。

強制的に処理を続行させる

画面に触れても処理を止めないためには、/nobreakを追加して下記のように書く。

@rem キー操作に関わらず、3秒間待つ
timeout /t 3 /nobreak
出力をシンプルにする

さらに、> nullは「カウントダウンの表示を消す」という意味になる。

@rem カウントダウンを出さずに3秒間待つ
timeout /t 3 /nobreak > null

出力内容をシンプルにしたい時などに使える。

参考記事

それぞれの出力内容など、詳しくはこちらが参考になると思います。

処理をまとめる
関数の定義

:[関数名]からexit /Bまでを1つのシーケンス(=ひとつづきの処理)として定義する。

@rem ↓関数のラベル
:[関数名]
 
  @rem ~処理~
 
exit /B
関数の終わり方

関数の末尾でexitコマンドに/Bオプションをつけると、「現在実行中のシーケンスを終了して呼び出し元に戻り、次の処理に移る」という命令になる。

exit /B
関数の呼び出し

定義した関数を呼び出す時は、こんな感じ。

call :[関数名]

VBAに似てる。というか、VBA「が」似てるんだろうけど。
(歴史は苦手なので今は深く考えないことにする)

ただし、関数名の頭に:が必要なので忘れないように注意する。

実行の準備

保存

ここまでを.batで保存して、スタートアップフォルダに入れておく。
(ファイル名は任意のものでOK。)

格納場所

スタートアップフォルダの場所はこちら。

@rem ユーザーごと
"C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
 
@rem 全ユーザー共通
"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"

以上。

これで、起動やログインのたびに好きな順番で開いてくれるようになった!

このシリーズについて

バッチファイルの書き方を自分なりに勉強しています。

もし間違いや改善のアイディア等ありましたら、コメント欄やTwitter等でご意見いただけたら嬉しいです。

連載目次

  1. 当記事【バッチファイル】指定した順番にアプリケーションを開くスクリプトを書いてみた - ゆるおたノート

  2. 【バッチファイル】何やらSTARTできてないモノが…? - ゆるおたノート

参考記事


*1:Unix系は試したことないので分からないですが…