none
Windowsサービスから名前付きパイプにアクセスしようとするとUnAuthorizedAccessExceptionが発生する RRS feed

  • 質問

  • いつもお世話になっております。arubi-momoと申します。

    開発環境はWindows10、VisualStudio2017、.Netframework4.6.1、C#です。

    現在、Windowsサービスプログラムと、アプリケーション間のプロセス間通信を行うため、名前付きパイプを使用しています。

    サービス側からアプリケーション側に通知を送るということをしたいため、アプリケーション側に名前付きパイプのサーバー側を置き、サービス側からの接続を待つ、という形でプログラムしています。

    サービス側のプログラムで以下のように、「testpipe」に接続をしているのですが、pipeClient.ConnectのところでUnAuthorizedAccessExceptionが発生します。

    using (NamedPipeClientStream pipeClient = new NamedPipeClientStream("testpipe"))
    {
        pipeClient.Connect();
        try
        {
            using (StreamWriter sw = new StreamWriter(pipeClient))
            {
                sw.WriteLine(strData);
                sw.Flush();
            }
        }
        catch (System.IO.IOException ex)
        {
            MessageBox.Show(ex.Message, "エラー通知");
        }
    }

    サービス側のプログラムをWindowsフォームプロジェクトにして、フォーム同士で通信を行うと、UnAuthorizedAccessExceptionは発生せず、正常に接続ができます。

    ちなみに、サービスプロジェクトでもWindowsフォームプロジェクトでも、app.manifestを設定して管理者権限で実行するようにしています。サービスプログラムに関しては、exeに対してプロパティで「管理者権限で実行する」設定にすることも試してみましたが、ダメでした。

    サービスプログラムからですと、何か特別な設定が必要なのでしょうか。

    ご存知の方がいらっしゃいましたら、ご教示いただければ幸いです。

    何卒、よろしくお願いいたします。

    2017年12月6日 2:20

回答

  • NamedPipeClientStreamのコンストラクタにて、TokenImpersonationLevelを適切に指定する必要があるかと。

    2017年12月6日 4:10
  • サーバ側とクライアント側のPipeDirectionの不一致などが考えられますが。

    とりあえず、Win7 SP1において、以下のような構成で問題なくConnect/Writeできていますね。

    // Windowsサービス: ローカルシステムアカウントで動作

    NamedPipeClientStream(".", name, PipeDirection.Out, PipeOptions.None, TokenImpersonationLevel.Impersonation)

    // デスクトップアプリ: UAC未昇格の管理ユーザアカウントで動作

    NamedPipeServerStream(name, PipeDirection.In)

    • 編集済み Hongliang 2017年12月7日 2:32
    • 回答としてマーク arubi_momo 2017年12月7日 9:51
    2017年12月7日 2:30

すべての返信

  • NamedPipeClientStreamのコンストラクタにて、TokenImpersonationLevelを適切に指定する必要があるかと。

    2017年12月6日 4:10
  • Hongliangさま

    いつもお世話になっております。arubi-momoです。

    ご回答ありがとうございます。解決いたしました。

    NamedPipeClientStreamの生成部分を以下のように変更いたしました。

    using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".",
     "testpipe", PipeDirection.In, PipeOption.None,
    System.Security.Principal.TokenImpersonationLevel.Impersonation))

    ローカル内での通信であるため、サーバー名はなし、TokenImpersonationLevelはImpersonationにしました。

    これでConnectは通るようになりました。

    ご教示いただきとても助かりました。ありがとうございました。

    今後ともどうぞよろしくお願いいたします。


    2017年12月6日 7:54
  • 今回の件は解決したのですが、一点わからないことがあり、続けて質問をさせていただいてもよろしいでしょうか。

    コンストラクタを変更してConnectは通るようになったのですが、その後のStreamWriterのnewの部分でSystem.ArgumentExceptionが出るようになりました。引数のStreamに書き込みができない場合に発生するExceptionとのことで、コンストラクタの引数の設定がどれか間違っているのかと思いました。

    PipeDirectionの方向が違うのだと思い、Out、InOutを試してみましたが、ここを変更してしまうと、UnAuthorizedAccessExceptionの状態に戻ってしまいます。

    今回は、Streamに書き込む情報はなく、通知の文字列を送っていただけであったため、Writeの部分を削ることで目的の動作をするようにはなったのですが、どうしてこのExceptionが発生するのかが理解できませんでした。

    PipeDirectionの設定はMicrosoftのページを見てもよくわからず、WriteするならOutになるものと思っていたのですが、理解が間違っていますでしょうか。勉強不足で大変恐縮ですが、ご教示いただければ幸いです。

    何卒、よろしくお願いいたします。

    2017年12月6日 14:46
  • サーバ側とクライアント側のPipeDirectionの不一致などが考えられますが。

    とりあえず、Win7 SP1において、以下のような構成で問題なくConnect/Writeできていますね。

    // Windowsサービス: ローカルシステムアカウントで動作

    NamedPipeClientStream(".", name, PipeDirection.Out, PipeOptions.None, TokenImpersonationLevel.Impersonation)

    // デスクトップアプリ: UAC未昇格の管理ユーザアカウントで動作

    NamedPipeServerStream(name, PipeDirection.In)

    • 編集済み Hongliang 2017年12月7日 2:32
    • 回答としてマーク arubi_momo 2017年12月7日 9:51
    2017年12月7日 2:30
  • Hongliangさま

    いつもお世話になっております。arubi-momoです。

    ご返信ありがとうございました。

    原因は、アカウントをNETWORK SERVICEとしていたからでした。

    名前付きパイプへの接続には管理者権限が必要なのに、一般User権限で接続しに行っていた、ということですかね。

    アカウントを変更したところ、問題なく動作いたしました。

    サービスの作成や通信処理は権限の設定をしっかり理解しておかなきゃいけないことを学びました。

    ご教示いただき、ありがとうございました。

    今後ともどうぞよろしくお願いいたします。

    2017年12月7日 9:51