ゆるおたノート

Tomorrow is another day.

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

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

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

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

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

:Main
  @rem ▼前処理
  @rem ウィンドウ出力を消す
  @echo off

  @rem ▼アプリを順次起動
  call :openApps

@rem ▼コマンドプロンプトを閉じて終了
exit

@rem ━━━━━━━━━━ 関数シーケンス ━━━━━━━━━━

@rem パスにスペースがあるとエラーが出て実行できないので、
@rem タイトルに""と指定し、パスも""で囲むこと。
@rem ─【例】─────────────
@rem start "" /max "C:\xxx.xxx"
@rem call :sleep
@rem ──────────────────
@rem 【参照】
@rem http://piyopiyocs.blog115.fc2.com/blog-entry-884.html
: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

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が基本だけど、Windowsコマンドプロンプトcmd.exeShift-JISにする必要がある。
Unix系は試したことないので分からないです…

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

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

"files.encoding": "shiftjis"

今回のスクリプト

出力を消す

@rem ウィンドウ出力を消す
@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%

(詳しくは別途記事にします)

処理を一時停止する

例えば、いま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 ↓関数のラベル
:[関数名]

  ~処理~

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"

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

参照