1

単純な Console.WriteLine および Console.ReadLine メソッドを使用してパイプアウト/パイプインできることはわかっていますが、そのようにして、プロセス間で文字列を渡しています (オブジェクトを再作成するには解析する必要があります)。

私が疑問に思っているのは、運命のプロセスで簡単に取得できるように、自分の型をパイプできるかどうかです。私が期待しているのは、次のようなことをすることです:

myProgram | get-member

出力は、MyNameSpace.MyType とそのメンバーのリストのようなものになります (現在、typeName System.String が表示されます)。

これはコンソール アプリで可能ですか、それともコマンドレットを使用してのみ達成できますか?

4

2 に答える 2

3

これを行う最も簡単な方法は、シリアル化を使用して、あるオブジェクトから別のオブジェクトに送信するオブジェクトをパイプ可能な形式に変換して、あるオブジェクトから別のオブジェクトに送信することです。ただし、これを行うにはいくつかの制約があります。

まず、やり取りする型の実装は、それらを処理する可能性のあるすべてのアプリで利用できる必要があります。(すべてのコマンドレットが同じプロセス内で実行されるため、これは PowerShell の問題ではありません。)したがって、これを行う最も簡単な方法は、すべてのコンソール アプリによって参照されるクラス ライブラリ内でパイプ処理する型を作成することです。たとえば、このクラスをサンプルの共有ライブラリに入れました。

[Serializable]
public class TestClass
{
    public string Test { get; set; }

    public string TestAgain { get; set; }

    public string Cheese { get; set; }
}

[Serializable] 属性は、単純なクラスには十分なシリアライズ可能としてマークします。より複雑なクラスについては、さらに必要になる場合があります。MSDN を参照してください。

次に、パイプ元のプログラムで、XML にシリアル化し、次のようにコンソールに書き込みます。

using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;

using Shared;

namespace Out
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the object.
            TestClass test = new TestClass();
            test.Test = "Monkey";
            test.TestAgain = "Hat";
            test.Cheese = "Fish";

            // Serialize it.
            XmlSerializer serializer = new XmlSerializer(typeof (TestClass));
            StringBuilder sb = new StringBuilder();
            using (var writer = new StringWriter(sb))
                serializer.Serialize(writer, test);

            // And write it to console.
            Console.WriteLine(sb.ToString());
        }
    }
}

実行すると、XML でエンコードされたインスタンスのプロパティが出力されます。したがって、次のようになります。

<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http
://www.w3.org/2001/XMLSchema">
  <Test>Monkey</Test>
  <TestAgain>Hat</TestAgain>
  <Cheese>Fish</Cheese>
</TestClass>

次に、受信アプリケーションでプロセスを逆にして、コンソールから読み取ります。

using System;
using System.IO;
using System.Xml.Serialization;

using Shared;

namespace In
{
    class Program
    {
        static void Main(string[] args)
        {
            // Read the input XML; until complete.
            string input = Console.In.ReadToEnd();

            TestClass passedIn;

            // Deserialize it.
            var serializer = new XmlSerializer(typeof (TestClass));
            using (var reader = new StringReader(input))
                passedIn = (TestClass) serializer.Deserialize(reader);

            // Do something with the object.
            Console.WriteLine("Test:      {0}", passedIn.Test);
            Console.WriteLine("TestAgain: {0}", passedIn.TestAgain);
            Console.WriteLine("Cheese:    {0}", passedIn.Cheese);
        }
    }
}

そして出来上がり!

C:\Working\PipeExample\In\bin\Debug>..\..\..\Out\bin\Debug\Out.exe | in
Test:      Monkey
TestAgain: Hat
Cheese:    Fish

もちろん、受信アプリケーションが期待するタイプを認識している、または受け取ったものをすべて処理できることを確認するために、追加のコードが必要になります。送信側のアプリケーションが、いつパイプと通信しているか、いつ人間と通信しているかを確実に認識できるようにする方法。.NET 4.5 では、 Console.IsOutputRedirected() メソッドがそれを行います ( http://msdn.microsoft.com/en-us/library/system.console.isoutputredirected%28v=VS.110%29.aspx ) 。ですが、以前のバージョンでは、この情報をプログラムで取得する簡単な方法はありませんでした。

しかし、これが核心であり、XmlSerializer とその周辺のドキュメントを見れば、残りの部分がわかるはずです。

于 2013-01-25T04:56:06.743 に答える
1

コンソール プログラムではなく、独自のコマンドレットを作成してみませんか?

PowerShell モジュールは、C# で記述されたコマンドレットで構成されたバイナリ モジュール (DLL アセンブリ) にすることができます。Windows PowerShell SDK のインストールを参照してください。

于 2013-01-25T04:46:28.640 に答える