2026/05/15(金)Windows 11でPowerShellを使って画面をオフにする方法

投稿日:

Win32APIをPowerShellから叩くことで実現できる。

確認環境

  • Windows 11 25H2 (OSビルド 26200.8457)

コード

(Add-Type -MemberDefinition @"
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
"@ -Name "Win32API" -PassThru)::SendMessage(0xFFFF, 0x0112, 0xF170, 2)

パラメーターを解説すると0xFFFFHWND_BROADCAST0x0112WM_SYSCOMMAND0xF170SC_MONITORPOWERに相当し、2はモニタ電源を落とす固定値である。

つまり内容としては第一引数のパラメーターがHWND_BROADCASTである場合、最上位のウィンドウにWM_SYSCOMMAND指令が出され、そのパラメーターはSC_MONITORPOWER2であるということで、つまりモニタ電源をオフにするシステムコマンドを最上位のウィンドウに送っている内容になっている。

-Name "Win32API" -PassThruを外したくなるが、外すとエラーで動かなくなるので付ける必要がある。

-PassThruがあることで戻り値が生まれ、-Name "Win32API"をつけることでクラスが生まれるらしい。

参考情報

  • SendMessage function (winuser.h) - Win32 apps | Microsoft Learn
    • > HWND_BROADCAST ((HWND)0xffff)
    • LRESULT SendMessage(
      [in] HWND hWnd,
      [in] UINT Msg,
      [in] WPARAM wParam,
      [in] LPARAM lParam
      );
  • WM_SYSCOMMAND message (Winuser.h) - Win32 apps | Microsoft Learn
    • > #define WM_SYSCOMMAND 0x0112
    • > SC_MONITORPOWER 0xF170
  • GET MONITOR STATE POWER ON OR OFF | Microsoft Learn
    • •-1 (the display is powering on)
      • 2 (the display is being shut off)
  • Add-Type (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Learn
    • -Name

      作成するクラスの名前を指定します。 このパラメーターは、メンバー定義から型を生成するときに必要です。

      型名と名前空間は、セッション内で一意である必要があります。 型をアンロードしたり、変更したりすることはできません。 型のコードを変更するには、名前を変更するか、新しい PowerShell セッションを開始する必要があります。 それ以外の場合、コマンドは失敗します。

    • -PassThru
      追加された型を表す System.Runtime オブジェクトを返します。 既定では、このコマンドレットは出力を生成しません。 OUTPUTAssembly 使用して DLL ファイルを作成し、新しく作成したアセンブリから型を返す場合は、このパラメーターを使用します。

あとがき

これは私物PCと業務PCでモニタを共有しており、排他制御で利用してる時に便利な技だ。

例えばリモートワークで昼休みに私物PCにスイッチする時で、業務PCをスリープや休止にするとWSLの中身が死んだりして面倒だが、画面オフならそういうことが起きないので便利に切り替えできるという訳。

2026/05/08(金)Windows 11で1603エラーが出てJavaをインストールできなかった時にやったこと

確認環境

  • Windows 11 Pro 25H2 (OSビルド 26200.8246)
  • jre-8u491-windows-i586.exe

起きていたこと

全オペレーティング・システム用のJavaのダウンロードからWindows用のインストーラーをダウンロードし、インストールしようとしたところ1603エラーが出てインストールできなかった。

オンライン・オフラインどちらのインストーラーでもインストールに失敗した。

OSを再起動してもインストールできなかった。

既存のJavaインストールはない環境だった。

解決のためにやったこと

  1. イベントビューアを開きWindowsログ>Applicationでインストールログを探した
  2. MsiInstallerを見つけたので中身を見たところ、インストーラ本体(jre-8u491-windows-i586.exe)ではなく、jre1.8.0_491.msiが出ていた
    Windows インストーラー トランザクションを開始しています: C:\Users\hoge\AppData\LocalLow\Oracle\Java\jre1.8.0_491\jre1.8.0_491.msi。クライアント プロセス ID: 3160。
    
  3. インストーラーを蹴った時にウィンドウが消え再び出てくる挙動を見ていたので、恐らく別のインストーラーに切り替えるときに管理者特権などが正しく継承されていないのではないかと疑った
  4. C:\Users\hoge\AppData\LocalLow\Oracle\Java\jre1.8.0_491にアクセスしMSIを拾い上げ、直に実行することでインストールできた
  5. この後、動いてなかったVSCodeのPlantUML拡張が動作することを確認したため、問題なくインストールできたと考えている

2026/04/28(火)nvm-windowsをマニュアルインストールする方法

投稿日:

マニュアルインストールするのに地味にハマったので記録として残しておく。

Windowsのユーザー名が日本語だとインストーラーを使ったインストールでは正常に動作しないため、そういったときに使える。

確認環境

nvm-windows 1.2.2

やり方

  1. GitHubのnvm-windows/releasesからnvm-noinstall.zipを落としてくる
  2. 適当な場所に解凍する。ここではC:\env\apps\nvmとする。
  3. Windowsのパスに次の物を作成する
    • NVM_HOME: C:\env\apps\nvm
    • NVM_SYMLINK: C:\env\apps\nvm\env
      • シンボリックリンク用なので存在しないパスを指定する
  4. PATH%NVM_HOME%%NVM_SYMLINK%の二つを追加する
  5. 次のコマンドを走らせ、上手くいけばOK
    nvm install lts
    nvm on
    nvm use 24
    node -v
    

トラブルシューティング

nvm useしてもnodeにパスが通っておらず動かない

NVM_SYMLINKの設定がおかしい。どうもnvm useをした時に、このパスに指定したバージョンのnode.exeのシンボリックリンクが張ることで切り替えているようなので、ここが正しくないと正常にパスが通らない。

NVM_SYMLINKは存在しないパスを指定する必要がある。適当な文字列を指定しても動かない。

参考

2026/04/16(木)WindowsでSSH接続に使う秘密鍵を任意の場所に置く方法

投稿日:

C:\Users\hoge\.ssh以外の場所に秘密鍵を配置し、その秘密鍵を使ってWindows組み込みのSSHを利用して、SSH接続を行うと以下のようなエラーが出るので、それを回避する方法。

[00:11:24.734] Opening exec server for ssh-remote+hoge.example.com
[00:11:24.934] Initizing new exec server for ssh-remote+hoge.example.com
[00:11:24.934] Using commit id "xxxxx" and quality "stable" for server
[00:11:24.934] Extensions to install:
[00:11:24.939] Install and start server if needed
[00:11:24.963] Opening exec server for ssh-remote+hoge.example.com
[00:11:24.967] Running script with connection command: "C:\WINDOWS\System32\OpenSSH\ssh.exe" -T -D 65374 "hoge.example.com" sh
[00:11:24.968] Generated SSH command: 'type "C:\Users\hoge\AppData\Local\Temp\vscode-linux-multi-line-command-hoge.example.com-281649447.sh" | "C:\WINDOWS\System32\OpenSSH\ssh.exe" -T -D 65374 "hoge.example.com" sh'
[00:11:24.968] Using connect timeout of 17 seconds
[00:11:24.968] Terminal shell path: C:\WINDOWS\System32\cmd.exe
[00:11:25.179] >
[00:11:25.179] Got some output, clearing connection timeout
[00:11:25.199] >
[00:11:26.323] >
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> @         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> Permissions for 'C:\\path\\to\\hoge.sec' are too open.
> It is required that your private key files are NOT accessible by others.
> This private key will be ignored.
> Load key "C:\\path\\to\\hoge.sec": bad permissions
> miyashiro@hoge.example.com: Permission denied (publickey).
> プロセスが、存在しないパイプに書き込もうとしました。
[00:11:26.632] "install" terminal command done
[00:11:26.632] Install terminal quit with output: プロセスが、存在しないパイプに書き込もうとしました。
[00:11:26.632] Received install output: プロセスが、存在しないパイプに書き込もうとしました。
[00:11:26.633] WARN: $PLATFORM is undefined in installation script output.  Errors may be dropped.
[00:11:26.633] Failed to parse remote port from server output
[00:11:26.633] Exec server for ssh-remote+hoge.example.com failed: Error
[00:11:26.633] Existing exec server for ssh-remote+hoge.example.com errored (Error)
[00:11:26.633] Initizing new exec server for ssh-remote+hoge.example.com
[00:11:26.634] Error opening exec server for ssh-remote+hoge.example.com: Error
[00:11:26.634] No hints found in the recent session.

やり方

以下のコマンドで秘密鍵の所有権を自分だけに変更するといけるようになる。

icacls "C:\path\to\hoge.sec" /inheritance:r /grant:r "%USERNAME%:F"

icaclsはファイルの所有権を変更するコマンドで、/inheritance:rで親フォルダからの継承を無効にし、指定したファイルに対する親フォルダから継承した権限を削除し、/grant:r "%USERNAME%:F"でファイルに対する権限を削除し、現ユーザーのフルアクセス権で上書きしている(要するに既存のアクセス権を、現ユーザーのフルアクセス権で置換しているのだと思う)

恐らくLinuxのOpenSSH同様に、WindowsのOpenSSHも鍵をユーザー以外が見れるとだめなのだろう。

2026/04/10(金)便利なコマンド置き場

投稿日:

特定パス配下のサブフォルダのファイル数を計数して、ソートして列挙する

/path/to/hoge
/path/to/fuga
/path/to/piyo

とあるとして

/path/to/hoge 32
/path/to/piyo 22
/path/to/fuga 4

みたいなのが欲しい場合の方法。フォルダはカウントされないので注意。

サブフォルダの中を再帰的に計測する

for d in /path/to/*/; do printf "%s\t%d\n" "$d" "$(find "$d" -type f | wc -l)"; done | sort -t$'\t' -k2 -nr

サブフォルダの直下のみ計測する

for d in /path/to/*/; do printf "%s\t%d\n" "$d" "$(find "$d" -maxdepth 1 -type f | wc -l)"; done | sort -t$'\t' -k2 -nr