Windows: こんなオプションがあったんだ、というコマンド。「sort /unique」ほか。

Windows のコマンドプロンプトで使えるコマンドから、こんなオプションがあったんだ、と驚いたものを紹介します。

動作確認環境

  • Windows 11 Home 22H2

sort /unique /case

MS-DOS の時代からある sort コマンド。文字列を行単位で並び替える(ソートする)コマンドですが、いつの間にか /unique オプションが追加され、重複文字列の削除ができるようになっていました。

たとえば次のファイルに対して、

Japan
Tokyo
Akihabara
JAPAN
Tokyo
Akihabara

単に sort すると ABC 順に並び変わるだけですが、

C:\tmp> sort a.txt
Akihabara
Akihabara
JAPAN
Japan
Tokyo
Tokyo

/unique オプションを付けるとさらに重複文字列が削除されます。

C:\tmp> sort /unique a.txt
Akihabara
JAPAN
Tokyo

このとき、「JAPAN」と「Japan」は同じ文字列とみなされ、ひとつにまとめられます。

大文字・小文字を区別したいときは (case-sensitive)、/case オプションを付加します。

C:\tmp> sort /unique /case a.txt
Akihabara
Japan
JAPAN
Tokyo

certutil -error

windows.h などに定義されているエラーコード。2 が「ファイルが見つからない」、5 が「アクセス拒否」は覚えていると思いますが (?)、122 は何だっけ、といったときに certutil -error が使えます。

C:\tmp> certutil -error 122
0x7a (WIN32/HTTP: 122 ERROR_INSUFFICIENT_BUFFER) -- 122 (122)
エラー メッセージ テキスト: システム コールに渡されるデータ領域が小さすぎます。
CertUtil: -error コマンドは正常に完了しました。

122 は「バッファ不足」ですね。

ほかにもいくつか試してみます。

C:\tmp> certutil -error 3
0x3 (WIN32: 3 ERROR_PATH_NOT_FOUND) -- 3 (3)
エラー メッセージ テキスト: 指定されたパスが見つかりません。
CertUtil: -error コマンドは正常に完了しました。

C:\tmp> certutil -error 6
0x6 (WIN32: 6 ERROR_INVALID_HANDLE) -- 6 (6)
エラー メッセージ テキスト: ハンドルが無効です。
CertUtil: -error コマンドは正常に完了しました。

C:\tmp> certutil -error 0xC0000005
0xc0000005 (NT: 0xc0000005 STATUS_ACCESS_VIOLATION) -- 3221225477 (-1073741819)
エラー メッセージ テキスト: 0x%p の命令が 0x%p のメモリを参照しました。メモリが %s になることはできませんでした。
CertUtil: -error コマンドは正常に完了しました。

C:\tmp> certutil -error 0xc0000142
0xc0000142 (NT: 0xc0000142 STATUS_DLL_INIT_FAILED) -- 3221225794 (-1073741502)
エラー メッセージ テキスト: {DLL 初期化の失敗}
ダイナミック リンク ライブラリ %hs の初期化に失敗しました。プロセスは異常終了します。
CertUtil: -error コマンドは正常に完了しました。

末尾に表示される「CertUtil: -error コマンドは正常に完了しました。」が邪魔だったら、findstr /v /i /b “CertUtil:” で消すといいでしょう(/v は指定の文字列に一致しない行のみを出力、/i は大文字・小文字を区別しない、/b は行頭から検索、の意味です)。

C:\tmp> certutil -error 0xC0000005 | findstr /v /i /b "CertUtil:"
0xc0000005 (NT: 0xc0000005 STATUS_ACCESS_VIOLATION) -- 3221225477 (-1073741819)
エラー メッセージ テキスト: 0x%p の命令が 0x%p のメモリを参照しました。メモリが %s になることはできませんでした。

いつも net helmsg <エラーコード> を使っていましたが、こちらは「0xC0000000」系 (ntstatus.h) も表示されるのがいいですね。

tasklist /m

プロセスがロードしている DLL を調べる際、Sysinternals ユーティリティの Process Explorer を使ったり WinDbg でプロセスにアタッチしたりしていましたが、標準の tasklist が使えました。

C:\tmp> tasklist /m

イメージ名                     PID モジュール
========================= ======== ============================================
......
explorer.exe                 16664 ntdll.dll, KERNEL32.DLL, KERNELBASE.dll,    
                                   msvcp_win.dll, ucrtbase.dll, combase.dll,   
                                   RPCRT4.dll, AEPIC.dll, OLEAUT32.dll,        
                                   TWINAPI.dll, msvcrt.dll, shcore.dll,        
                                   sechost.dll, advapi32.dll, USERENV.dll,     
                                   ......
                                   NSI.dll, dusmapi.dll, WS2_32.dll,           
                                   ondemandconnroutehelper.dll, mswsock.dll,   
                                   firewallapi.dll, fwbase.dll, WINNSI.DLL, DN 
......
msedge.exe                    3380 ntdll.dll, KERNEL32.DLL, KERNELBASE.dll,    
                                   msedge_elf.dll, OLEAUT32.dll,               
                                   msvcp_win.dll, ucrtbase.dll, combase.dll,   
                                   RPCRT4.dll, bcryptprimitives.dll,           
                                   ADVAPI32.dll, msvcrt.dll, sechost.dll,      
                                   USER32.dll, win32u.dll, GDI32.dll,          
                                   gdi32full.dll, IMM32.DLL, uxtheme.dll,      
                                   MSCTF.dll                                   
......
cmd.exe                      18632 ntdll.dll, KERNEL32.DLL, KERNELBASE.dll,    
                                   ucrtbase.dll, cmdext.dll, msvcrt.dll,       
                                   ADVAPI32.dll, sechost.dll, RPCRT4.dll       
......

/m の後ろに DLL 名を書くと、フィルタリングもできます。
以下は、「wow」(Windows on Windows) で始まる DLL をロードしているプロセスの一覧です。

C:\> tasklist /m wow*

イメージ名                     PID モジュール
========================= ======== ============================================
IpOverUsbSvc.exe              5068 wow64.dll, wow64base.dll, wow64win.dll,
                                   wow64con.dll, wow64cpu.dll
LMS.exe                       5100 wow64.dll, wow64base.dll, wow64win.dll,
                                   wow64con.dll, wow64cpu.dll
WMIRegistrationService.ex     5328 wow64.dll, wow64base.dll, wow64win.dll,
                                   wow64con.dll, wow64cpu.dll
GoogleCrashHandler.exe        9356 wow64.dll, wow64base.dll, wow64win.dll,
                                   wow64con.dll, wow64cpu.dll
imecfmui.exe                 17712 wow64.dll, wow64base.dll, wow64win.dll,
                                   wow64con.dll, wow64cpu.dll

なお、標準ユーザー権限のコマンドプロンプトでは、SYSTEM や LOCAL SERVICE など高い権限のアカウントで動作しているプロセスの DLL 情報は取得できないので注意です。

%=exitcode%

最後に、これはオプションではなく環境変数ですが、外部コマンドの終了コードを取得する際、いつもの %errorlevel% ではなく %=exitcode% を使うと 16 進数で取得できます。

たとえば 0x1234abcd を返すプログラムを作成して実行した場合、

C:\tmp> type test.c
int main(void)
{
    return 0x1234abcd;  ★ 終了コードを 0x1234abcd とする。
}

C:\tmp> cl test.c
......

C:\tmp> test.exe

%errorlevel% で終了コードを取ると 305441741 が返りますが、%=exitcode% で取ると 1234ABCD が返ります。

C:\tmp> echo %errorlevel%
305441741  ★ 0x1234ABCD は 10 進数で 305441741

C:\tmp> echo %=exitcode%
1234ABCD

コマンドライン上での「10 進数 → 16 進数」変換にも使えます。

C:\> cmd /c exit 1000  ★ 終了コード 1000 をセット

C:\> echo %errorlevel%
1000

C:\> echo %=exitcode%
000003E8  ★ 1000 は 16 進数で 0x3E8

ワンライナーにしてみました。%=exitcode% ではなく !=exitcode! としているのは、環境変数の遅延展開のためです。

C:\> cmd /c exit 2000 & cmd /v:on /c echo !=exitcode!
000007D0  ★ 2000 は 16 進数で 0x7D0

C:\> cmd /c exit -10 & cmd /v:on /c echo !=exitcode!
FFFFFFF6  ★ 負数 -10 も 0xFFFFFFF6 に変換可

なお、逆の「16 進数 → 10 進数」変換は set /a でできます。

C:\>set /a 0x7D0
2000

C:\> set /a 0xFFFFFFF6
-10

おわりに

以上、個人的に最近知った Windows コマンドのオプションでした。

参考文献

[1] StackExchange, Is there a Windows equivalent to the Unix uniq?
https://superuser.com/questions/1316317/is-there-a-windows-equivalent-to-the-unix-uniq

[2] DosTips.com, [How to] dec to hex and hex to dec conversion bat.
https://www.dostips.com/forum/viewtopic.php?t=2261