管理者モードのコマンドプロンプトでプロンプトを変える。

コマンドプロンプトの色を変える。では、有無を言わさず自分が開くコマンドプロンプトのプロンプトを変えてしまう方法を書きました。

ところで自分が使用するNetBSDやLinuxやCygwin上では zsh を使用していて、suでrootになったときにはプロンプトを赤色に変更しています。通常のプロンプトはネイビーというかブルー系です。これは、うっかりミスをできるだけ防ぐように、という工夫です。

これを管理者モードのコマンドプロンプトでも実現できないか、と考えるわけです。

ところで、Windows 10のコマンドプロンプト、通常は CMD.EXE ですが、zshやあるいはMS-DOSのように起動時に自動的に実行される設定ファイルというのはありません。zshでは.zshrcを、MS-DOS (command.com)ではAUTOEXEC.BATを自動的に実行するようになっていますが、CMD.EXEではそれがないため、別途設定してやる必要があります。

管理者モードでコマンドプロンプトの色や表示内容を変えたいと考えるとき、CMD.EXE起動時に自動実行されるファイルがあればそのなかで処理をすればいいと考えます。なので、ここでのキモは二つ。
  1. CMD.EXE起動時に設定用のファイルを自動実行する方法を調べる
  2. 自動実行される設定用ファイルの処理中に「管理者モードかどうかを判定する」方法を調べる
ということになります。

CMD.EXEは "/k" オプションを使ってバッチファイルを引数に与えると、バッチファイルの処理終了後もコンソールを閉じない状態でプロンプトを表示します。ただ、この方法だとCMD.EXEを起動する全てのショートカットに設定しなくてはならないので、ちょっと大変です。

もう一つ、レジストリに自動実行されるコマンドを登録しておくという方法があります。コマンドプロンプトを開いて、help cmd とすると説明が書いてありますが、\HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun に指定されたコマンドを実行します。

===
コマンド ラインで /D が指定されなかった場合は、CMD.EXE の開始時に次の REG_SZ
または REG_EXPAND_SZ レジストリ変数が検索されます。次のレジストリ変数の両方
またはどちらかが存在する場合、それらを最初に実行します。

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun

および/または

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
===

これはすでに自分のPCではHKLMのほうで、\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor\AutoRundoskey /macrofile=%userprofile%\cmd.rc を指定しています。
ちなみにcmd.rcの中身は、
CD=CD /D $*
H=doskey /history
HISTORY=doskey /history
ALIASES=doskey /macros
としています。

次に管理者モードかどうかを判定する方法ですが、これも検索してみるといくつかあるようです。

ひとつは環境変数の違いで、管理者モードではない通常のコマンドプロンプトでは SESSIONNAME=Console という環境変数が設定されているようです。
また、openfilesというコマンドは実行に管理者権限が必要なので、通常のコマンドプロンプトで実行するとエラーを返すからそれを利用する方法 (%errorlevel% で判定する) もあります。
同様に NET コマンドにも管理者権限が必要なものがあり、NET SESSIONNET CONFIG SERVERNET FILEなどは %errorlevel% を返します。
また whoami /groups の出力で "Mandatory Label\Medium Mandatory Level" というのが設定されていたら通常のコマンドプロンプト、"Mandatory Label\High Mandatory Level" が設定されていたら管理者権限があるモード、という判定もできるようです。

このうちバッチファイルで簡単に使えそうなのは %errorlevel% を返す方法です。
以下のような記述で対応可能です。

openfiles > NUL 2>&1
IF %ERRORLEVEL% == 0 (
  REM 管理者モードの処理
) ELSE (
  REM 通常モードの処理
)

最初の SESSIONNAME環境変数は本来リモートデスクトップでログオンしているのかどうかということを示す環境変数であるため本来の用途とは違いますし、管理者モードで本当になにも設定されないのかどうかは不明です。
一応そのための条件判定は、
IF "%SESSIONNAME%" NEQ "Console"
で可能です。

これらをうまく組み合わせれば、管理者モードのコマンドプロンプトではプロンプトを別のものに設定できるはずです。

最終的には以下のような cmdrc.bat バッチファイルを作成して、\HKLM\Software\Microsoft\Command Processor\AutoRunに登録しました。
@echo off
doskey /macrofile=%userprofile%\cmd.rc

openfiles > NUL 2>&1

if %ERRORLEVEL% == 0 (
  rem 管理者モードの処理
  rem CRIMSON
  set PROMPT=$e[38;2;220;20;60m$p# $e[m
) else (
  rem 通常モードの処理
  rem Royalblue
  set PROMPT=$e[38;2;65;105;225m$p$$ $e[m
)

regeditを開いて上記キーの位置まで移動し、右側のペインで右クリックして「新規」→「文字列」でAutoRunを作成、AutoRunをダブルクリックで開いて文字列に %USERPROFILE%\cmdrc.bat と入力するだけです。

0 件のコメント:

コメントを投稿

Windowsでシンボリックリンクを試してみる。

きっかけは、1つのファイルを別の名前で起動したら違う動きになるようなスクリプトを書く、でした。  busybox なんかでは、同じ実行形式ファイルの名前を、lsにすればlsと同じ、cpとすればcpと同じ動作をするようにしてますが、Pythonスクリプトでそれと同じように argv...