iwasiblog

イワシブログ - Activity log of an iwasi -

PowerShell起動時にPSReadLineが無効になる(備忘録)

ある時からPowerShell起動時に以下の警告が出るようになった.
PSReadLineが無効だとコマンド履歴やシンタックスハイライトが使えず不便である.

警告: PowerShell により、スクリーン リーダーを使用している可能性があること、および互換性のために PSReadLine が無効になっている可能性が検出されました。再度有効にするには、'Import-Module PSReadLine' を実行してください。

日本語でググっても情報が見つからなかったので英語で調べたら以下の解決法が出てきた.

https://serverfault.com/questions/1014754/cause-of-warning-powershell-detected-that-you-might-be-using-a-screen-reader-an

リンク先の2番目の解答にあるスクリプトを実行したところ,次回から警告は出なくなった.
何らかのタイミングでレジストリ内のスクリーンリーダーのフラグが立ったままになってしまっているということのようだ.

スクリプト本体を以下に引用する.

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

public static class ScreenReaderFixUtil
{
    public static bool IsScreenReaderActive()
    {
        var ptr = IntPtr.Zero;
        try
        {
            ptr = Marshal.AllocHGlobal(sizeof(int));
            int hr = Interop.SystemParametersInfo(
                Interop.SPI_GETSCREENREADER,
                sizeof(int),
                ptr,
                0);

            if (hr == 0)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

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

    public static void SetScreenReaderActiveStatus(bool isActive)
    {
        int hr = Interop.SystemParametersInfo(
            Interop.SPI_SETSCREENREADER,
            isActive ? 1u : 0u,
            IntPtr.Zero,
            Interop.SPIF_SENDCHANGE);

        if (hr == 0)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
    }

    private static class Interop
    {
        public const int SPIF_SENDCHANGE = 0x0002;

        public const int SPI_GETSCREENREADER = 0x0046;

        public const int SPI_SETSCREENREADER = 0x0047;

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

if ([ScreenReaderFixUtil]::IsScreenReaderActive()) {
    [ScreenReaderFixUtil]::SetScreenReaderActiveStatus($false)
}