🔖

PowerShell の『screen reader が有効なので PSReadLine を無効化した』警告を消す方法まとめ

に公開

なぜ警告が出るの?

  • PowerShell は起動時に 「スクリーンリーダーが有効かどうか」
    SystemParametersInfo(SPI_GETSCREENREADER) で問い合わせる
  • 何らかの原因で OS 全体のフラグが ON になると

    Warning: PowerShell detected that you might be using a screen reader …
    と表示され、PSReadLine モジュールが読み込まれない

  • 結果として 履歴呼び出し・補完・シンタックスハイライト が使えなくなる

対応方法(2 通り)

難易度 方法 特徴
レジストリを直接書き換え 1 行で完結
⭐⭐ スクリプトを実行(判定して自動修正) 再利用・自動化しやすい

以下で順に解説します。


1. レジストリを直接書き換える

Set-ItemProperty -Path 'HKCU:\Control Panel\Accessibility'
                 -Name Blind -Type DWord -Value 0

これで解決しない場合は続けて以下を行ってください。

2. 自動判定 & 修正スクリプト

2-1. FixScreenReader.ps1 を作成

Add-Type -TypeDefinition @'
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

public static class ScreenReaderFixUtil
{
    public static bool IsScreenReaderActive()
    {
        IntPtr ptr = Marshal.AllocHGlobal(sizeof(int));
        try
        {
            if (Interop.SystemParametersInfo(
                  Interop.SPI_GETSCREENREADER, sizeof(int), ptr, 0) == 0)
                throw new Win32Exception(Marshal.GetLastWin32Error());

            return Marshal.ReadInt32(ptr) != 0;
        }
        finally { Marshal.FreeHGlobal(ptr); }
    }

    public static void SetScreenReaderActiveStatus(bool isActive)
    {
        if (Interop.SystemParametersInfo(
                Interop.SPI_SETSCREENREADER,
                isActive ? 1u : 0u, IntPtr.Zero,
                Interop.SPIF_SENDCHANGE) == 0)
            throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    private static class Interop
    {
        public const int SPI_GETSCREENREADER = 0x46;
        public const int SPI_SETSCREENREADER = 0x47;
        public const int SPIF_SENDCHANGE     = 0x0002;

        [DllImport("user32", SetLastError = true)]
        public static extern int SystemParametersInfo(
            uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
    }
}
'@

if ([ScreenReaderFixUtil]::IsScreenReaderActive()) {
    [ScreenReaderFixUtil]::SetScreenReaderActiveStatus($false)
    Write-Host "ScreenReader flag was ON -> turned OFF." -ForegroundColor Green
} else {
    Write-Host "ScreenReader flag is already OFF; nothing to do." -ForegroundColor Yellow
}

2-2. 実行

powershell -NoProfile -ExecutionPolicy Bypass -File .\FixScreenReader.ps1

緑のメッセージが出ればフラグを無効化できています
以後 PowerShell を再起動して警告が出なければ完了

Discussion