【C#】.NET8のNamedPipeServerStream.SetAccessControlが動作しない問題の回避方法

はじめに

.NET でパイプを使用したプロセス間通信は NamedPipeServerStream を使用します。また、Windows 上で権限レベルが異なるユーザー間(例えばサービス - 一般ユーザー間)でプロセス間通信をする場合は、追加パッケージ System.IO.Pipes.AccessControl を導入し、SetAccessControl を以下のように指定します。

例えば以下のように実装すると、すべてのユーザーからアクセス可能なパイプが作成できます。

// すべてのユーザーからアクセス可能とする
PipeSecurity pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(
    new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                       PipeAccessRights.FullControl,
                       AccessControlType.Allow));

var pipe = 
    new NamedPipeServerStream("pip-ename", 
        PipeDirection.InOut, 1, 
            PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

// ★以前はコンストラクターで引数を指定できていたが
//   .NETのマルチプラットフォーム化でオーバーロードが削除されたため
//   拡張パッケージによる追加メソッドで指定する
p.SetAccessControl(pipeSecurity);

が、しかし、この実装は VisualStudio を管理者権限で起動して実行しても必ずエラーが発生し正常に動作しません。

// 管理者権限で実行しても SetAccessControl の行でエラーが発生する
System.UnauthorizedAccessException: 'Attempted to perform an unauthorized operation.'

このエラーの対象方法について紹介となります。

確認環境

  • .NET8
  • VisualStudio2022
  • Windows11

解決方法

解決方法は簡単で、SetAccessControl の代わりに NamedPipeServerStreamAcl.Create メソッドを使用してインスタンスを作成します。

実装例は以下の通りです。

PipeSecurity pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(
    new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                       PipeAccessRights.FullControl,
                       AccessControlType.Allow));

// 代わりに以下のようにインスタンスを作成する
var p = NamedPipeServerStreamAcl
    .Create("asdf",
            PipeDirection.InOut,
            1,
            PipeTransmissionMode.Byte,
            PipeOptions.Asynchronous,
            1024 * 10, 1024 * 10,
            pipeSecurity);

これでエラーが発生しなくなります。

以上です。