none
プログラム間でデータをやりとりしたい(プロセス間通信) RRS feed

  • 質問

  • VS2017のMicrosoft Visual C#を使用しています

    あるプログラムが内部に持っているデータを別のプログラムに渡したい場合があります(同一PC内)

    調べてみると.Net.RemotingとWCFがよく使用されている感じでした

    後者の方が新しいのでこちらでトライしてみようと思いましたが、ネットの情報だけでは理解できず行き詰まっております(前者もうまくいかず)

    やりたいことは、プログラムAからプログラムBにデータ要求を出すと、プログラムBがプログラムAにデータを引き渡すという感じのものです(プログラムは何れもWindowsデスクトッププログラム)

    データは文字列(stringまたはstring[])になります

    従来1ウィンドウ当たり1ソースの単純なプログラムしか作成していませんでしたので、ネットで見たコードをどこに記載すれば良いのかも見当つかない状況です

    調べた範囲では、

    ・WCFの方が新しい

    ・httpやtcpなど手段が選択できるが同一PC内限定なら名前付きパイプが良い

    ・一定時間通信が途絶えると接続が切断される

    ・プログラムが異常終了するとPC再起動が必要になる場合がある

    といった程度です

    この機能をコンパクトに実装したく、DLLやアプリケーション構成ファイルは使用せずに仕上げたいのが希望です

    初心者向けの解説のあるサイトがありましたら是非紹介よろしくお願いします

    2019年10月27日 12:25

すべての返信

  • newon1さん、こんにちは。フォーラムオペレーターのクモです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ご質問の件につきまして、答えさせていただきます。
    同じ装置で別のプログラムと通信するには、NetNamedPipeBinding によって作成されたWCF サービスを利用したほうがいいと思います。
    WCFサービスは、TCP プロトコルよりも優れたパフォーマンスを持って、IPCプロトコルでもっと簡単に作業することができます。
    次はNetNamedPipeBinding のURLフォームです。
    Net.pipe://localhost/mypipe
    完全に実行できる公式の例をご参照ください。
    https://docs.microsoft.com/ja-jp/dotnet/framework/wcf/samples/netnamedpipebinding

    また、NetNamedPipeBinding は絶対に安全なバインディングタイプであるため、別の装置からのリクエストを受け入れることはできません。


    どうぞよろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年10月31日 7:04
    モデレータ
  • 説明ありがとうございます

    今回の用途ではNetNamedPipeBinding によるWCF サービスが最適であることを理解しました

    ただ、「完全に実行できる公式の例」がよくわかりません

    IPCプロトコルを使用することになると思いますが、公式の例ではインターネットインフォメーションサービス(IIS)が

    必要みたいな感じでこれでいいのか疑問です

    使用を想定している環境にはIISが存在していません

    また、ネット情報を見ていると同一PC内でのやりとりにエンドポイントの公開は不要みたいな記述もあって、この辺りの

    対応方法も不明です

    そもそもサンプルに書かれたXMLをどこに記述するのかも理解できていません

    もう少し初心者向けの解説がありましたら是非紹介をお願いします

    2019年11月2日 14:00
  • newon1さん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    IISとコンソール アプリケーション (winform、wpf などの自己ホスト型) は、NetNamedbinding によって作成されたサービスをホストすることができます。
    IPC プロトコルは、トランスポート層で動作する基になるプロトコルです。サービスのホスト方法に関係なく、IPC プロトコルの下でで実行されています。
    IIS で他のプロトコルを有効にする方法のガイドラインを次に示します。
    https://www.c-sharpcorner.com/article/enable-other-protocols-tcp-pipe-msmq-etc-in-iis/

    サービス、クライアント プロキシ、またはチャネル ファクトリの呼び出し方法に関係なく、クライアント側でサービス コントラクトを共有する必要があります。
    それらの方法をご存じでしょうか?
    とにかく、ページにダウンロードサンプルがあります。ダウンロードして直接実行してみてください。
    簡単な例を紹介させていただきます。
    サーバー(コンソールアプリケーション)

    class Program
        {
            static void Main(string[] args)
            {
                Uri uri = new Uri("net.pipe://localhost/mypipe");
                NetNamedPipeBinding binding = new NetNamedPipeBinding();
                binding.Security.Mode = NetNamedPipeSecurityMode.None;
    
                using (WebServiceHost sh = new WebServiceHost(typeof(MyService), uri))
                {
                    sh.AddServiceEndpoint(typeof(IService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        smb = new ServiceMetadataBehavior()
                        {
                            
                        };
                        sh.Description.Behaviors.Add(smb);
                    }
    
                    Binding mexbinding = MetadataExchangeBindings.CreateMexNamedPipeBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
    
                    sh.Opened += delegate
                    {
                        Console.WriteLine("Service is ready");
                    };
                    sh.Closed += delegate
                    {
                        Console.WriteLine("Service is clsoed");
                    };
                    sh.Open();
                    Console.ReadLine();
                    //pause
                    sh.Close();
                    Console.ReadLine();
                }
    
            }
        }
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            string SayHello();
        }
        public class MyService : IService
        {
            public string SayHello()
            {
                return $"Hello Stranger,{DateTime.Now.ToLongTimeString()}";
            }
        }

    クライアント側 (コンソール アプリケーション、サービス参照を追加してクライアント プロキシを生み出す)

    ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
                try
                {
                    var result = client.SayHello();
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
    
                    throw;
                }

    アプリケーション構成(クライアント側)

    <system.serviceModel>
            <bindings>
                <netNamedPipeBinding>
                    <binding name="NetNamedPipeBinding_IService">
                        <security mode="None" />
                    </binding>
                </netNamedPipeBinding>
            </bindings>
            <client>
                <endpoint address="net.pipe://localhost/mypipe" binding="netNamedPipeBinding"
                    bindingConfiguration="NetNamedPipeBinding_IService" contract="ServiceReference2.IService"
                    name="NetNamedPipeBinding_IService" />
            </client>
    </system.serviceModel>

    サービス参照を追加してサービスを呼び出します。
    https://docs.microsoft.com/ja-jp/dotnet/framework/wcf/accessing-services-using-a-wcf-client
    何かお手伝いできることがありましたら、お気軽にお知らせください。

    どうぞよろしくお願いいたします。


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年11月5日 2:19
    モデレータ