C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

全過去ログを検索

<< 0 | 1 | 2 >>
■19173  Re[4]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 18:18:56)
    2008/05/20(Tue) 18:19:31 編集(投稿者)

    No19103 (れい さん) に返信
    > ■No19096 (シャノン さん) に返信
    >>これバグくさいなー。
    >
    > pingの、ですね。

    ping にバグがあるとして、その出力を扱うこっち側のアプリはどうしますか?
    ping は単一の改行のつもりで \r\n を書き出したところ、標準出力がテキストモードだったために \r\r\n になってしまうわけですが、Process.OutputDataReceived も Process.StandardOutput.ReadLine も、\r だけを有効な改行とみなすために、\r\r\n は2つの改行と認識されてしまうわけです。
    これを、「そんなのは ping のバグだから俺の責任じゃない! 知らん!」と言うか、\r\r\n は単一の改行と認識するようにプログラムを組むか。
    後者の場合、Process.StandardOutput.BaseStream からバイトデータとして読み取れば \r\r\n を受け取れるので処理できますが、Process.OutputDataReceived や Process.StandardOutput.ReadLine ではダメなんですよね(意図した空行かバグによる空行か判別できないため)。

    もちろん、ことは ping に限ったことではなく、行末が \r\r\n になってしまうコンソールアプリは少なくないことは想定できます。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19187  Re[5]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/20(Tue) 21:51:31)
    No19173 (シャノン さん) に返信
    > ping にバグがあるとして、その出力を扱うこっち側のアプリはどうしますか?

    基本的に他のバグへの対処と同じでいいかと。

    「入力には寛容に」ですから、
    1 そんなところを気にしなくていいようなプログラムにする
    というのが最初かな?

    で、だめなら
    2 個別に対応する

    でも、シャノンさんの言うように対象が少なくないでしょうから、
    仕方が無いときのみ
    3 全体的に対処できるように組む
    かな。

    でも、この\n->\r\nは不可逆ですから
    本来意図されたデータを絶対的に取得するようにプログラムを組むのは不可能ですね。
    \rは改行以外に含まないと仮定していいならできますが。
    ある程度で妥協するしかないですね。

    StreamReader.ReadLineを使わずに、という手はあまり使いたくないですが、
    情報が削れちゃうので無理ですね。

    Readから独自にReadLineを作るのかな。
    その際、「\r\r\n」->「\r\n」という変換では実装しないです。

    「\r」->「」として「\n」のみを改行として扱う、
    というように作ると思います。
    (HTTPと同じように。)
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19192  Re[6]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 23:23:18)
    No19187 (れい さん) に返信
    > 1 そんなところを気にしなくていいようなプログラムにする
    > というのが最初かな?

    例えば今回の事例では?

    > でも、この\n->\r\nは不可逆ですから
    > 本来意図されたデータを絶対的に取得するようにプログラムを組むのは不可能ですね。
    > \rは改行以外に含まないと仮定していいならできますが。
    > ある程度で妥協するしかないですね。

    俺なら、\r\r\n と来たら、それは \r\n と出したかったものだと解釈しちゃいますけどね。

    > 「\r」->「」として「\n」のみを改行として扱う、
    > というように作ると思います。
    > (HTTPと同じように。)

    HTTP は \r\n ですよ?
    HTML / XML は \n ですけど。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19200  Re[7]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/21(Wed) 00:03:55)
    2008/05/21(Wed) 00:06:26 編集(投稿者)

    No19192 (シャノン さん) に返信
    > 例えば今回の事例では?

    今回はデータを表示するだけです。
    意味は人間が解釈するわけですから、余計な空白があっても何の問題もありません。
    なので「何もしない」です。

    (人間は入力に寛容ですねぇ)

    > 俺なら、\r\r\n と来たら、それは \r\n と出したかったものだと解釈しちゃいますけどね。

    まぁそれもアリです。
    積極的に否定はしません。

    > HTTP は \r\n ですよ?
    > HTML / XML は \n ですけど。

    おおっと。また大切な説明が足りないですね。

    RFC2616 19.3 Tolerant Applications
    において、受信側では\rを無視して\nを改行とみなす実装が推奨されています。
    (特に根拠は書いてないのが問題ですが。)

    そんなわけで、
    「\r\r\n」を「\r\n」に置換するではなく、
    全ての「\r」を無視する、という選択を私なら取ると思います。

    そのほうがプログラムも楽で速いですし。

    #「早い」を「速い」に修正。
    #プログラムが「はやい」場合は「速い」ですよね?
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19202  Re[8]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/21(Wed) 00:39:24)
    No19200 (れい さん) に返信
    > 今回はデータを表示するだけです。
    > 意味は人間が解釈するわけですから、余計な空白があっても何の問題もありません。
    > なので「何もしない」です。
    >
    > (人間は入力に寛容ですねぇ)

    なるほど。
    それで問題がないならそれもいいでしょうね。

    > RFC2616 19.3 Tolerant Applications
    > において、受信側では\rを無視して\nを改行とみなす実装が推奨されています。
    > (特に根拠は書いてないのが問題ですが。)
    >
    > そんなわけで、
    > 「\r\r\n」を「\r\n」に置換するではなく、
    > 全ての「\r」を無視する、という選択を私なら取ると思います。

    ふーむ。なるほど。
    どうにも、「理想的な方法」というのは思いつきませんね。
    どの方法も一長一短でしょうね。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19204  Re[9]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/21(Wed) 01:40:53)
    No19202 (シャノン さん) に返信
    > ふーむ。なるほど。
    > どうにも、「理想的な方法」というのは思いつきませんね。
    > どの方法も一長一短でしょうね。

    そうですね。
    絶対に元に戻せない変形が行われているわけですから。
    そのときに応じて適切なものを選ばざるを得ない。
    なるべく広範につかえてプログラムが楽なものが良いですが、
    状況次第、価値観次第。

    そういう時は他の方法の「あら」を探して批判するのがよいです。
    よいと信じてる方法の欠点はなかなか思いつかないものですから。

    なので「\r\r\n->\r\n」を批判すると…

    もし万が一借りに、2回改行コード変換が入っちゃったとすると
    「\r\r\r\n」みたいな改行コードになりますがそれに対応できませんよ!

    FTPでダウンロードしてそれをパイプでテキストに落としたりとか。(無い
    3回はいっちゃう場合もありえますよ?(無い

    「s/\r?\n/\r\n」にするなら対応できます。
    でもそれなら「s/\r*\n/\r\n」でいいでしょう?

    もういっそ「s/\r//」でいいじゃん、というわけですが。

    「s/\r//」の問題点はないですかね?

    旧Macで改行がなくなっちゃうというのがありますね。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19086  Re[1]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 10:55:26)
    No19072 (鶏唐揚 さん) に返信
    
    .NET Framework 1.1 でもできる範囲のコードで。
    
    class AsyncArgument
    {
        public Process process;
        public Stream stream;
        public byte[] buffer;
    }
    
    private static void Ping2()
    {
        using (Process p = new Process())
        {
            p.StartInfo.FileName = "ping.exe";
            p.StartInfo.Arguments = "127.0.0.1";
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
    
            p.Start();
    
            byte[] outputBuffer = new byte[1024];
            AsyncArgument aa = new AsyncArgument();
            aa.process = p;
            aa.stream = p.StandardOutput.BaseStream;
            aa.buffer = outputBuffer;
    
            aa.stream.BeginRead(outputBuffer, 0, 1024, StandardOutputCallback, aa);
            p.WaitForExit();
        }
    
        Console.WriteLine();
        Console.WriteLine("Complete");
    }
    
    static void StandardOutputCallback(IAsyncResult result)
    {
        AsyncArgument aa = result.AsyncState as AsyncArgument;
        int count = aa.stream.EndRead(result);
    
        string output = Console.OutputEncoding.GetString(aa.buffer, 0, count);
        if (!string.IsNullOrEmpty(output))
        {
            Console.WriteLine(output);
        }
    
        if (!aa.process.HasExited)
        {
            aa.stream.BeginRead(aa.buffer, 0, 1024, StandardOutputCallback, aa);
        }
    }
    
    しかし出力は細切れになってしまう。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19087  Re[2]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 11:02:45)
    No19086 (シャノン さん) に返信
    > ■No19072 (鶏唐揚 さん) に返信
    >
    > .NET Framework 1.1 でもできる範囲のコードで。
    > しかし出力は細切れになってしまう。

    > string output = Console.OutputEncoding.GetString(aa.buffer, 0, count);
    > if (!string.IsNullOrEmpty(output))
    > {
    > Console.WriteLine(output);
    > }

    ここを Console.Write にしたらうまくいったよー!
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19090  Re[2]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/20(Tue) 11:11:23)
    2008/05/20(Tue) 11:22:56 編集(投稿者)
    2008/05/20(Tue) 11:13:27 編集(投稿者)

    No19086 (シャノン さん) に返信
    > ■No19072 (鶏唐揚 さん) に返信
    >
    > .NET Framework 1.1 でもできる範囲のコードで。

    いやそのコードはマルチスレッドですから:D

    > しかし出力は細切れになってしまう。

    素直にStreamReaderとWaitHandle使いましょうよ


    まぁこの辺はいくらでも何とでもなりますよ>鶏唐揚さん
    シャノンさんの最初のコードのように、Processに内蔵のイベントつかってもいいですし、
    StreamReaderを非同期でよんでもいいですし、
    Streamを非同期で読んでもいいですし、
    部分的にマルチスレッドにしてもいいですし。
    自分の実装に合ったものを選べばよいでしょう。

    追記。

    > 1KBごとに取得・表示を行っているので改行いれたら細切れになってたということですか

    違います。
    Readはいくつ読むのか不定というだけです。

    さらに追記。

    シャノン産のコード。

    string output = Console.OutputEncoding.GetString(aa.buffer, 0, count);

    ここはダメですねぇ。
    GetDecoderしてDecoder取っておかないと、文字が化けちゃいます。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19088  Re[3]: Processの標準出力をリアルタイム取得
□投稿者/ 鶏唐揚 -(2008/05/20(Tue) 11:06:38)
    No19087 (シャノン さん) に返信
    > ■No19086 (シャノン さん) に返信
    >>■No19072 (鶏唐揚 さん) に返信
    >>
    >>.NET Framework 1.1 でもできる範囲のコードで。
    >>しかし出力は細切れになってしまう。
    >
    >> string output = Console.OutputEncoding.GetString(aa.buffer, 0, count);
    >> if (!string.IsNullOrEmpty(output))
    >> {
    >> Console.WriteLine(output);
    >> }
    >
    > ここを Console.Write にしたらうまくいったよー!
    1KBごとに取得・表示を行っているので改行いれたら細切れになってたということですか

    #現在上記3手法のコードを解析中…
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19092  Re[4]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 11:29:08)
    No19088 (鶏唐揚 さん) に返信
    > 1KBごとに取得・表示を行っているので改行いれたら細切れになってたということですか

    いや、バッファサイズをどうやっても WriteLine を使うと細切れになるんだけどね。
    俺の2つ目の方法では、ちゃんと改行コードもバッファに取得できるんです。
    だから自分で改行コードを付加する WriteLine を使う必要は無い。Write で改行コードごと書き出せばちゃんと改行してくれる。

    俺の1つ目の方法では、e.Data に改行コードが入ってこないんですよ。
    だから Console.Write にするとすべてのデータが一行になってしまう。
    そこで WriteLine を使っていたわけ。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19095  Re[3]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 11:35:57)
    No19090 (れい さん) に返信
    >>.NET Framework 1.1 でもできる範囲のコードで。
    > 
    > いやそのコードはマルチスレッドですから:D
    
    new Thread() してなければ OK だっ!
    
    >>しかし出力は細切れになってしまう。
    > 
    > 素直にStreamReaderとWaitHandle使いましょうよ
    
    それでもいいのか。
    StreamReader を使うというのは良くわからんが。
    
    というわけで第三弾。
    
    using (Process p = new Process())
    {
        p.StartInfo.FileName = "ping.exe";
        p.StartInfo.Arguments = "127.0.0.1";
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.UseShellExecute = false;
    
        p.Start();
    
        while (! p.HasExited)
        {
            byte[] outputBuffer = new byte[1024];
    
            IAsyncResult result = p.StandardOutput.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, null, null);
            result.AsyncWaitHandle.WaitOne();
            int count = p.StandardOutput.BaseStream.EndRead(result);
    
            string output = p.StandardOutput.CurrentEncoding.GetString(outputBuffer, 0, count);
            Console.Write(output);
        }
    }
    
    Console.WriteLine();
    Console.WriteLine("Complete");
    
    > string output = Console.OutputEncoding.GetString(aa.buffer, 0, count);
    > 
    > ここはダメですねぇ。
    > GetDecoderしてDecoder取っておかないと、文字が化けちゃいます。
    
    え、そうなの?
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19131  Re[4]: Processの標準出力をリアルタイム取得
□投稿者/ ネタ好き -(2008/05/20(Tue) 14:15:54)
    >pingが意図的に\rを出している、つまり仕様である可能性ももちろんありますが。
    >その場合理由が見えません。
    ほんとおかしな挙動ですよね。データの終了を判定するためにあるのかな?
    でも何パケット送るかはpingプログラムは周知しているはずですから意味が無いような・・・
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19134  Re[5]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 14:22:48)
    No19131 (ネタ好き さん) に返信
    > >pingが意図的に\rを出している、つまり仕様である可能性ももちろんありますが。
    > >その場合理由が見えません。
    > ほんとおかしな挙動ですよね。データの終了を判定するためにあるのかな?
    > でも何パケット送るかはpingプログラムは周知しているはずですから意味が無いような・・・

    いや、ネットワークの話じゃなくて。
    コンソールに結果を出力するときの行末コードの話です。
    ping が \r\n を出しているんでしょうね。

    ちなみに、.NET Framework の Console.Out はバイナリモードのようです。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19141  Re[6]: Processの標準出力をリアルタイム取得
□投稿者/ 鶏唐揚 -(2008/05/20(Tue) 14:34:10)
    いつのまにか伸びていた…

    様々なコード案ありがとうございます。
    仕事と平行でチラチラ見てるので全然解析できてませんが、
    採用するしないにかかわらず全部見ていきたいと思います

    #たぶんこの中から選ぶか組み合わせたり改造したりして実装するので
     ここで解決させていただきます。
     Ping行末についての議論は続けてくださっても構いません。
     今回の件に少なからず関係しているのでw
記事No.19072 のレス / END /過去ログ37より / 関連記事表示
削除チェック/

■19147  Re[6]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/20(Tue) 15:13:16)
    バイナリ/テキストの話はCやC++の標準ライブラリの話です。
    なので、

    No19134 (シャノン さん) に返信
    > コンソールに結果を出力するときの行末コードの話です。
    > ping が \r\n を出しているんでしょうね。

    pingのコードが\r\nを使っているので、
    Executableが\r\r\nを出してしまっているのだと思います。

    > ちなみに、.NET Framework の Console.Out はバイナリモードのようです。

    .Netのストリームはバイナリ/テキストの区別はないでしょう。
    文字コードとか、もっと大変なことがいっぱいありますから。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19149  Re[7]: Processの標準出力をリアルタイム取得
□投稿者/ シャノン -(2008/05/20(Tue) 15:34:25)
    No19147 (れい さん) に返信
    > バイナリ/テキストの話はCやC++の標準ライブラリの話です。
    > なので、
    >
    > ■No19134 (シャノン さん) に返信
    >>コンソールに結果を出力するときの行末コードの話です。
    >>ping が \r\n を出しているんでしょうね。
    >
    > pingのコードが\r\nを使っているので、
    > Executableが\r\r\nを出してしまっているのだと思います。
    >
    >>ちなみに、.NET Framework の Console.Out はバイナリモードのようです。
    >
    > .Netのストリームはバイナリ/テキストの区別はないでしょう。
    > 文字コードとか、もっと大変なことがいっぱいありますから。

    なんだか揚げ足取られているように感じてしまうナァ…
    .NET の Console は \n -> \r\n 変換をせずにそのまま出しますよ、ということでバイナリモードと呼びました。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19159  Re[8]: Processの標準出力をリアルタイム取得
□投稿者/ れい -(2008/05/20(Tue) 16:26:15)
    No19149 (シャノン さん) に返信
    > なんだか揚げ足取られているように感じてしまうナァ…
    > .NET の Console は \n -> \r\n 変換をせずにそのまま出しますよ、ということでバイナリモードと呼びました。

    あう。
    すみませんでした。

    シャノンさんに言ってるというよりは、
    読んでる他の人にわかりやすいよう補足したつもりでした。

    流し読みをするとテキストモードというのが存在していると勘違いする人がいるかなぁと思ったので。

    正確に伝わらないことを危惧して補足した結果揚げ足取りに見えてしまう、
    というのは今までもきっとありますね。

    非難する気もからかう気も全く無いので、
    揚げ足取りに見えるということは
    1 細かい点にうるさくて
    2 発言が非難がましい
    のでしょうね。

    私は理解力が低く、正確で細かくないと間違ってしまうので
    細かいところにうるさいのは仕方ないとして。
    それに細かい点の指摘はただの指摘ですから。

    細かいことを言うときは特に表現に気をつけないといけないということですね。

    難しいなぁ。
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19153  Re[7]: Processの標準出力をリアルタイム取得
□投稿者/ 渋木宏明(ひどり) -(2008/05/20(Tue) 15:54:38)
>
    >  Ping行末についての議論は続けてくださっても構いません。
    >  今回の件に少なからず関係しているのでw

    ちなみに、プログラムから Ping 相当の操作が行いたい、ってことなら、ping.exe の実行結果をキャプチャする以外にも方法はありますよ?
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

■19154  Re[8]: Processの標準出力をリアルタイム取得
□投稿者/ ネタ好き -(2008/05/20(Tue) 15:57:18)
    No19153 (渋木宏明(ひどり) さん) に返信
    >> Ping行末についての議論は続けてくださっても構いません。
    >> 今回の件に少なからず関係しているのでw
    >
    > ちなみに、プログラムから Ping 相当の操作が行いたい、ってことなら、ping.exe の実行結果をキャプチャする以外にも方法はありますよ?

    System.Net.NetworkInformation.Pingクラスの事かな?
    もしくは自分でPingを実装するとか?
記事No.19072 のレス /過去ログ37より / 関連記事表示
削除チェック/

<前の20件 | 次の20件>

<< 0 | 1 | 2 >>

パスワード/

- Child Tree -