この記事の概要を簡単まとめ!
- バッチファイル作成の上級編
- cmdで電源プランを操作できる”powercfg.exe”
- これまでの内容と新しいコマンドをフルに活用したバッチファイル
- サブルーチン化でバッチファイルの可読性も確保
- 解説で「こういう処理をしている」が分かるようになる
- 「GUIでやるより簡単」を目指して
バッチファイルシリーズもこれで第3回となる。これまではコマンドの解説と簡単なコマンド使用例を記述し、自分で改造可能なものを最終的な完成品として仕上げていた。しかしこれまでのバッチファイル解説は、初心者が入りやすいよう、難易度が低めのものから行ってきた。したがって、バッチファイル全体としては、難しい機能は殆ど使用していない。
それも、今回取り上げるpowercfg.exeまで抵抗なく入れるようにしたためである。バッチファイルで書きたい本命はこれであり、それまで書いてきたものは、導入のための土台である。とはいえ、これまでやってきたことは決して無意味ということではなく、これまでやってきたことの積み重ねで本命に挑むのである。
その結果、上級編に相応しいまでの難易度になった今回だが、そうであっても何の問題もなく使えるよう、この記事で指南していく。最後まで見ていくといい。
ひとっ飛びできる目次
バッチファイル作成と解説:上級編
はじめに:第1回・第2回記事の紹介
第1回を初級編・第2回を中級編としているため、これらを読んでいることが流れ的に前提となる。そのため、読んでいない人は下記リンクから読める。大きくなりすぎて邪魔なので、カードは格納している。
第1回:【コマンド入力】CMDとバッチファイルでショートカット 入門編
第2回:【bat中級編】分岐と選択でまとまるバッチファイルの作成
system32下のアプリケーション
cmd.exeは、システム環境変数PATHで、ディレクトリの移動をしなくてもファイルを呼び出すことができる。このため様々なアプリケーションを、cmdはコマンドで起動することができるのである。
中でもcmdの標準ディレクトリである、C:\Windows\System32にはcmdでのみ扱えるアプリケーションが多数存在する。今回取り上げるのは電源プランを操作する”powercfg.exe“である。それ以外にも、Windowsサービスを(非常に強い権限で)操作する”sc.exe”、IPアドレスやアダプターの状態を調べる”ipconfig.exe”、ディスクエラーの調査・修復を行う”chkdsk.exe”などがある。これらのアプリケーションは殆どの場合GUIが存在しないため、cmdから扱うのみとなっている。
これらのアプリケーションは、cmdから単独で使用しても何も起こらない。多くの場合オプションを使用し、そのアプリケーション固有のコマンドを使用する必要がある。このコマンドに関してはWindows標準アプリケーションである関係から、Microsoft Docsに各アプリケーションのリファレンスが存在する。基本はこのリファレンスを参考に使用するため、全てを記憶しておく必要はあまりない。その点では便利である。
ソースコードの前に:powercfgと追加で使用するコマンド解説
今回も最後にpowercfgを使用して、cmdから電源プランを変更するバッチファイルのソースコードを掲載する。だが、必要かつまだ解説していないコマンドがあるため、それを解説した後、本題のpowercfgの解説及びソースコード解説を行う。なお、前回と同様に前回までの内容については、既に知っているものとして進行する。
cmd標準のコマンド
ここでは、この後で紹介するバッチファイルのソースコードで使用する新しいコマンドと、前回解説した中で使用していないオプションについての解説が中心となる。とはいっても、解説と共にいつものように使用方法を示したソースコードを記述する。
cmd/バッチファイル:call
callコマンドは、他のバッチファイルや同一バッチファイル内のサブルーチン1)ある特定の処理について、1つのパッケージのようにまとめておき、別のプログラムからそれを呼び出して実行できるようにしたもの。cmd/バッチファイルにおいてのサブルーチンは、goto文で使用したラベルを利用する。通常はラベルからexit /b [Errorlevel]までが1つのサブルーチンとなる。を呼び出すためのコマンドである2)参照:Call – DOS コマンド一覧 – Programming Field。今回の場合はサブルーチンを呼び出すために使用する。まずは使用例を掲載する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@echo off rem callコマンドでサブルーチンを呼び出す使用例 rem 基本書式は call :<ラベル名> <引数> goto文と違い、callの場合は呼び出し時に':'も必要 rem この例では文字が入力されたかどうかを判定する、簡単なものとなっている setlocal set /p str01="任意の文字列を入力してください>"%str01% rem callでサブルーチンを呼び出す。このときstr01をstrCheckの引数として渡している call :strCheck "%str01%" rem call以降の処理はcall先の処理が終了してから行われる。ここではErrorlevelによってechoの内容を変更している if Errorlevel 1 (echo 文字列は入力されませんでした。) else (echo 文字列が入力されました。) endlocal rem ここの終了処理はバッチファイルの終了処理である exit /b 0 rem ここからサブルーチン :strCheck rem 引数の参照。引数は引数の数に応じて%1,%2,...となる。今回は%1のみ rem 引数は%1で""も含めて引数を展開、%~1で""を除いて引数を展開する set str11=%~1 rem str11を確認し、文字が入っていればErrorlevelを0、入っていなければErrorlevelを1でサブルーチンを終了する rem if notは否定であり、if /i "%str11%" NEQ "" と同様の意味である if /i not "%str11%"=="" (exit /b 0) else (exit /b 1) rem いずれのエラーレベルでも、exit /b [Errorlevel]でサブルーチンを終了する。終了すると8行目に戻る |
callコマンドは読んで字の如く、「呼び出す」のである。今回はサブルーチンを呼び出すのに使用している。サブルーチンを呼び出す場合の基本構文は、call :<ラベル名> <引数> である。引数は最大9個まで渡すことができる。10個以上の場合は特別な設定が必要だが、使う必要がないのでここでは割愛する。
callコマンドでサブルーチンが呼び出されると、それまでの処理は一時中断され、サブルーチンの処理が開始される。サブルーチンでも処理は順序処理で行わる。サブルーチンの終了はexit /b [Errorlevel]をするか、ファイルの終端に到達することである。通常はexit /b [Errorlevel]で終了する。
また、サブルーチンはそこで条件処理などをさせて、その結果によって動作を変更するかどうかを決めるのにも使用する(所謂戻り値)。上記の例では文字列が入力されていれば0、そうでないなら1を返している。これが環境変数Errorlevelに格納される。ifはErrorlevelを条件分岐で使用できるため、これを使って10行目で条件分岐に使用している。この動作を、最後に解説するpowercfgのソースコードで使用する。
補足:callの引数と戻り値について
callの引数は、callで引数を渡した順に%1から%9で参照できる。今回の例では%1のみである。また参照する際、%と数字の間にチルダ<~>を入れない場合、ダブルクォーテーションも含めて参照し、チルダを入れた場合、ダブルクォーテーションを含まずに参照する。文字列を引数として渡した場合、チルダを入れて参照することが多い。
また、サブルーチンの戻り値に関しては、exit /b [Errorlevel]で任意の値を環境変数Errorlevelの戻り値に指定できる。この値は0を正常終了、それ以外を何らかのエラーによる終了としている。そのため、サブルーチン内での条件分岐の結果でErrorlevelを変え、その値によって処理を変えるのが一般的である。
cmd/バッチファイル:for
forと聞くと、多くの人がforループという名称で、繰り返しの処理に使用するものと想像する。これはcmdでも同じである。本来の用途はファイルの操作だが、繰り返し処理にも当然使用することができる3)参照:For – DOS コマンド一覧 – Programming Field。
ただし、今回紹介する機能に関しては、はっきり言って通常ではない使い方の度を越しているため、紹介が非常に難しい。したがって、今回使用することにのみ絞って解説することにする。面倒は嫌いなので仕方ない。
1 2 3 4 5 6 7 8 9 10 11 |
@echo off rem forコマンドの例。ただし、使用方法が特殊。通常の用途はリファレンスを参照のこと setlocal rem testStrにスペース入りで文字列を代入。cmdではスペースは区切り文字となる set testStr=a1 b2 c3 d4 e5 rem 今回の例では、スペース区切りで3番目の文字列を取り出すfor文となっている。トークンオプションは""で囲うこと for /f "tokens=3 usebackq" %%i in (`echo %testStr%`) do ( echo 3番目の文字列: %%i ) endlocal exit /b 0 |
今回のforコマンドは、for /fの場合である。/fを使用すると、トークンを指定できるようになる4)ここでのトークンとは、スペースで区切られた文字列のことを示す。例の場合、a1 b2 c3 d4 e5がそれぞれトークンとなる。 参照:[バッチ] for と 「/f “tokens=〇”」 を使って、スペース区切りの文字列の必要列だけ取り出す – Qiita。そこで、今回使用するのはtokens, usebackqである。tokensはトークン番号の指定を行う。つまり、[n]番目のトークン(文字列)を取得するように指定できる。そしてusebackqはcmdで使用できるコマンドを出力の対象とすることができるのである。
本来はテキストファイルを読み込むようにできているforコマンドだが、usebackqでコマンドが使えるようになる。よって、変数に格納した文字列から特定のトークンを取り出したい!となったとき、このオプションで変数をechoで展開し、その結果に対して適用すれば、特定のトークンを取り出せる、と言う構造となっている。なお、コマンドを認識させるにはアクサングラーブ<`>5)アクサンクラーブは、shift+@で出せる記号である。なおusebackqでの()内は、アクサンクラーブでコマンド、クォーテーション<‘>で文字列、ダブルクォーテーション<“>でファイル名を扱える。でコマンドを囲う必要がある。また、コマンドの結果を別のコマンドへ渡す、パイプ6)コマンドの結果を次のコマンドに渡す、記号コマンドの1つ。も使用できる。その場合、コマンドとコマンドの間に ^| と記述する必要がある。
この設定により、echo %testStr%の結果に対して、3番目のトークンを取得するよう命令を出すことができる。もっともこの例ではforで行う意味はあまりないが、この方法を最後に解説するバッチファイルで使用しているための解説である。
今回新しく使用する、cmd標準コマンドの解説は以上である。
powercfg.exeとオプション
ここからはpowercfg.exeの解説に移る。powercfg.exe, 単純にpowercfgは、電源プランの操作が主である。それ以外にもバッテリー診断やスリープ・休止モードの管理なども行える。このあたりの操作はGUIでは難しく、powercfgでなければ殆どの場合操作できないものである。
ここでの解説も、今回使用するものだけに絞って行う。なお、その他のpowercfgのオプションに関しては、Microsoft Docsのリファレンスを参考にするといい7)参照:Powercfg のコマンド ライン オプション | Microsoft Docs。
今回使用するコマンド(1つにまとめている)
今回使用するコマンドについて、下記の使用例でまとめている。また、コマンドを実際に使用した画像をソースコードの下に示す。
1 2 3 4 5 6 7 8 9 |
rem powercfg解説(今回使用分のみ) rem 現在アクティブな電源プランの取得 powercfg /getactivescheme rem 全ての電源プランをリスト表示する powercfg /list rem 電源プランをアクティブにする。アクティブにしたいプランをGUIDで指定する。GUIDは /list で確認できる powercfg /setactive [scheme_GUID] |
各オプションについて軽く解説する。/getactibeschemeは現在の電源プランを表示する。/listは全ての電源プランを表示するものである。このとき、電源設定のGUIDも同時に表示される。GUIDはpowercfgで電源プランを操作する際に重要な値であり、powercfgでは度々使用される。そして/setactiveは変更したいプランのGUIDを入力することで、その電源プランをアクティブにするオプションとなっている。
/listの出力結果を見ると分かるのが、GUIDは3番目のトークンである。先程解説したfor /fのトークン番号指定を行うことで、GUIDを取り出すことが可能になる。ただしそのままでは列ごと取り出してしまうため、GUIDを1つだけ取り出すにはまだ一工夫必要になる。これはそのときに解説する。
powercfgではもっと細かく設定も可能であるが、今回は電源プランを変更するのが目的のため、必要最低限に留めている。これで、今回使用するコマンドの解説は完了である。次項で、本題のバッチファイルの作成とその解説を行う。
上級編:powercfgで電源プランを変更するバッチファイル
相変わらず解説が長すぎて申し訳ない。こうしないと途中で脱落してしまう人がいるためである。それでは、powercfgで電源プランを変更するバッチファイルを作成する。ソースコードは下記に示す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
@echo off setlocal echo. & echo 電源プランを変更します。 :loopbackMain rem 入力用文字を初期化 set GUID_str4= echo. & echo 現在の電源プラン設定: rem 現在の電源プランの情報を取得 powercfg /getactivescheme echo. & echo 電源プラン一覧 rem 電源プランのリストを全て表示 powercfg /list echo. & set /p GUID_str4="変更したい電源プランのGUIDを先頭から4文字で指定してください。 >"%GUID_str4% rem サブルーチンとして文字列の長さをチェックする。4文字で通過、3文字以下、5文字以上は再度loopbackMainまで戻る call :str_lenCheck "%GUID_str4%" rem Errorlevel判定:1であれば最初に戻る if Errorlevel 1 (goto loopbackMain) rem サブルーチンとしてGUIDが存在するかチェックする。存在する場合電源プランを変更、存在しない場合は再度loopbackMainまで戻る call :str_existCheck "%GUID_str4%" rem Errorlevel判定:2であれば最初に戻る if Errorlevel 2 (goto loopbackMain) rem 全て問題なしであればこのバッチファイルを終了 endlocal exit /b 0 rem サブルーチン置き場 :str_lenCheck rem チェック用変数に代入する set strCheck=%~1 rem 判定用変数を初期化しておく set strlen=0 :loop_CK if /i not "%strCheck%"=="" ( rem strCheckの文字数を1つ削る。行頭の1文字を消す動作をしている set strCheck=%strCheck:~1% rem 文字列のカウントアップ。/aで右辺の演算式を処理し、その結果を代入する set /a strlen=%strlen%+1 goto :loop_CK ) rem 4文字でなかった場合はサブルーチンを終了してMainに戻る if /i not %strlen% equ 4 ( echo 4文字ではありません。最初に戻ります。 & echo. rem サブルーチンは異常終了扱いなのでErrorlevel=1とする exit /b 1 ) exit /b 0& rem サブルーチン正常終了 :str_existCheck rem チェック用変数に代入する set strExistCheck=%~1 rem tokens=3はpowercfg /listの3列目のみを抜き出す設定。usebackqは()が任意に使用できる rem ()内でコマンド解釈させたい場合は``が必要、その中でパイプを使用する場合は^|で使用する rem GUIDの先頭から4文字を、リストと照合する。一致した場合は変数を代入、電源プランを変更し、サブルーチンを終了 rem 一致しない場合、サブルーチンを終了してMainに戻る。Errorlevelを2にする for /f "tokens=3 usebackq" %%i in (`powercfg /list ^| find "%strExistCheck%"`) do ( rem 一致する場合はそのGUIDを代入する。findは一致しない場合何も表示しないため、空文字が入力される set changeScheme=%%i ) rem 一致した場合と一致しなかった場合の処理。batのifの特性上falseから先に判定する rem 一致しなかった=空文字:Mainに戻る if /i "%changeScheme%"=="" ( echo 入力された文字列と一致するGUIDはありませんでした。最初に戻ります。 & echo. rem サブルーチンは異常終了扱いのためErrorlevel=2とする exit /b 2 ) rem 一致したものがある=空文字でない:変数の中身のGUIDをセットする。前のifが通らなかった場合はこっちを通る powercfg /setactive %changeScheme% echo 電源プランの変更に成功しました。 rem サブルーチン正常終了 exit /b 0 |
このバッチファイルの流れとしては次の通りである。
- powercfg /getactivescheme で現在の電源プランを表示する
- powercfg /list で全ての電源プランを表示する
- set /p で変更したい電源プランのGUIDを先頭から4文字入力させる
- サブルーチン1:4文字チェック。現段階では4文字丁度で設定。それ以外は最初に戻る
- サブルーチン2:GUID存在チェック。存在する場合電源プランを変更、存在しない場合は最初に戻る
- バッチファイルを終了する
基本的な動作は解説した通りである。解説用にコマンドの前後にコメントを残しているため、これを読めば動作の大半がわかるようになっている。また、実際に使用したイメージは以下である。

追加解説:特殊な使い方
38行目の右辺の変数の展開時の特殊な使い方、59行目のfindコマンドについては、別途解説する。
38行目では、右辺の変数の展開時に”:~1″と記述している。これは展開位置をずらすオプションである。cmdでも文字列の先頭を0文字目とするため、先頭の文字を削る場合”:~1″を記述することで、1文字目から文末まで展開する。38行目では、展開した文字列を自分の変数に再度格納し、1文字削っているのである。これが最終的にnullになるまで行う。
59行目のfor文の()内で、powercfg /listの結果をパイプでfindコマンドに渡している。このfindコマンドは指定した文字列を検索するコマンドである。ここでの指定した文字列は変更したい電源プランのGUIDの先頭から4文字のことである。このコマンドは本来はファイルに対して使用するが、パイプによりpowercfg /listの結果に対してfindしている。つまり、powercfg /listの結果を擬似的にファイルと見ているのである。
このときfindでは一致した「行」を抜き出している。つまり、「電源設定の GUID: [GUID] (電源プラン名)」を抜き出しているのである。さらにこの結果に対してfor /fで3番目のトークンを取得するように設定しているので、最終的にGUIDのみを抜き出すことができるのである。
全体の解説は以上である。もし、これを読んでわからないことなどがあった場合、コメント欄での質問を受け付けている。また、このバッチファイル自体にも改良の余地があるため、更新する可能性もある。
「GUIでやるより簡単」を目指して
今回は上級編として、powercfgとそれに至るまでの、新規に使用するコマンドの解説を行った。上級編といいつつも実際の難易度はプロ級のような気がしないでもないが、powercfgをより簡単に利用できるようなバッチファイルができたとは、自信を持って言える。流石にここまでやってしまうと、やりすぎなのかもしれないが。
しかし、電源プランの変更は、実は面倒であったりする。というのも、ツールバー上から電源プランを選択する場合、2個しか選択肢がない(現在のプランと別のプラン)ために、いちいち新たにウィンドウを開いて選択しに行かなければならない。それに、ウィンドウを表示するためのリンクが小さいこともあり、どうにも操作しづらいように感じる。私からすれば、ウィンドウを移動することがどうしても煩わしいのである。
その点トッポってすげぇよな、最後までチョコたっぷりだもん。バッチファイルを自分で作り、それをcmdで動作させれば、cmdの画面1つで電源プランが選択できてしまうのである。もちろんウィンドウはcmdのみであり、複雑な画面移動はない。今回は手入力が少しあるのでそこで多少時間は掛かるが、それはバッチファイルの作り方次第でいくらでも改良可能である。それこそ極めれば、たった1文字、或いはエンターの1押しだけで変更可能になる。それは、GUIでやるより簡単、と言える。
他にも、GUIでやるのが面倒なことというのは多々ある。例えば、Windows7以前の環境変数である。Windows7以前の環境変数の編集は、GUIは非常に見難い構成となっており、以前に環境変数を追加したかどうかもわからないほどである。その場合には、見やすく処理した上で、追加ないし削除処理できるバッチファイルを作ってしまった方が楽である。現在のOSは殆どがWindows10ではあるものの、互換性からアップグレードしていない場合、有用性は十分にある。なお、作るかどうかは未定である。
一応、今回をもってバッチファイルシリーズは終了となるが、バッチファイルで何かしたいアイデアが浮かべば、気まぐれに書いていく予定である。ただしその場合でも、リファレンスの詳細はなるべく載せるつもりである。途中で読むのが面倒にならないための処置であるが、これを書く私が面倒であったりする矛盾がある。ともあれ、書きたいときに書くことにしているので問題はないだろう。
以上、バッチファイル上級編 -powercfgで電源プラン操作- であった。それでは、次回の記事で会おう。
リンクス岐部(LINKS-KIBE) at 21:00 May. 20th, 2020
スポンサーリンク
脚注
本文へ1 | ある特定の処理について、1つのパッケージのようにまとめておき、別のプログラムからそれを呼び出して実行できるようにしたもの。cmd/バッチファイルにおいてのサブルーチンは、goto文で使用したラベルを利用する。通常はラベルからexit /b [Errorlevel]までが1つのサブルーチンとなる。 |
---|---|
本文へ2 | 参照:Call – DOS コマンド一覧 – Programming Field |
本文へ3 | 参照:For – DOS コマンド一覧 – Programming Field |
本文へ4 | ここでのトークンとは、スペースで区切られた文字列のことを示す。例の場合、a1 b2 c3 d4 e5がそれぞれトークンとなる。 参照:[バッチ] for と 「/f “tokens=〇”」 を使って、スペース区切りの文字列の必要列だけ取り出す – Qiita |
本文へ5 | アクサンクラーブは、shift+@で出せる記号である。なおusebackqでの()内は、アクサンクラーブでコマンド、クォーテーション<‘>で文字列、ダブルクォーテーション<“>でファイル名を扱える。 |
本文へ6 | コマンドの結果を次のコマンドに渡す、記号コマンドの1つ。 |
本文へ7 | 参照:Powercfg のコマンド ライン オプション | Microsoft Docs |