【緊急】コマンドの結果を変数に格納して結果に応じて処理を変えたい
Q&A
Closed
解決したいこと
外部から起動したコンソールアプリにいくつかのコマンドA,B,C,Dを投入して、コマンド show status pp2を投入するときだけ、その結果がエラー時に再度コマンド show status pp2を投入できるようにしたい
→現状:標準出力のリダイレクトを使って、投入結果を文字列の変数に格納、それをif文で結果に応じて処理する(にしようとしてる)
発生している問題・エラー
変数に結果が入らない。空っぽのまま
下記のコードを実行すると show status pp2コマンドを投入し、結果が表示されたあとに
Object reference not set to an instance of an object というメッセージが表示されます
VisualStudio Community 2022 17.4.2を使用しています
該当するソースコード
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Microsoft.VisualBasic.ApplicationServices;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;
using System.Reflection.PortableExecutable;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolBar;
using System.Text;
namespace hoge
{
public partial class Form1 : Form
{
string output = ""; //コマンドDの結果を読み取るのに使う
//----------省略----------------------------
void TTprocess//コンソールアプリの起動・コマンド投入
{
int i;
int iMax = 1;//失敗したときのまつ時間(分)
int j = 0;//ダメだった時の繰り返す添え字
int jMax = 3;
var proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "";//省略
proc.StartInfo.RedirectStandardOutput = true;// 標準出力をリダイレクト
proc.StartInfo.UseShellExecute = false;
proc.OutputDataReceived += this.DataReceived;
proc.StartInfo.RedirectStandardError= true;//エラー出力のリダイレクト
Microsoft.VisualBasic.Interaction.AppActivate("省略");
System.Threading.Thread.Sleep(3000);
proc.Start();
proc.WaitForInputIdle();
do
{
SendKeys.Send("show status pp2");
proc.BeginOutputReadLine(); // 標準出力の読み取り(非同期)
//proc.WaitForExit();
System.Threading.Thread.Sleep(3000);
//TEST用
//MessageBox.Show("output =" + output);
//this.TopMost = true;
//ここまでTEST用
if (output.Contains("一度も") == false)//成功した
{
//----成功時の処理を行う(省略)-------------------------
proc.CancelOutputRead();//標準出力の読み取り(非同期)停止
break;
}
else//失敗した
{
//成功しなかったときの処理がここにくる
//---------------省略------------------
for (i = 0; i < iMax; i++)
{
System.Threading.Thread.Sleep(60000);//成功しなかったら60秒まつ
}
}
j = j + 1;
if (j == jMax)
{
MessageBox.Show("試行回数3回になりました");
this.TopMost = true;
break;
}
proc.CancelOutputRead();//標準出力の読み取り(非同期)停止
} while (j < jMax);
Console.WriteLine($"process exit code: {proc.ExitCode}");//終了コードを出力する
}// void TTprocess()のカッコ閉じ
void DataReceived(object sender, DataReceivedEventArgs e)//イベントハンドラ
{
output = e.Data;
// Console.WriteLine(output);
//output = e.Data;
}
void func2()
{
//TTprocess()で起動したアプリへ別のコマンドを投入していく
//コマンドE,F...
}
void ProcessEnd()//コンソールアプリとツールの終了
{
System.Diagnostics.Process[] aaa = System.Diagnostics.Process.GetProcessesByName("aaa(省略)");
if (0 < aaa.Length)
{
//見つかった時は、アクティブにしてアプリを終了
Microsoft.VisualBasic.Interaction.AppActivate("省略");
System.Threading.Thread.Sleep(1500);
SendKeys.Send("%q");
}
else
{
//なんもしない
}
//このアプリケーションそのものを終了
Console.Beep(1245, 300);
Console.Beep(1319, 300);
Console.Beep(1397, 300);
Console.Beep(1480, 1000);
System.Threading.Thread.Sleep(1000);
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)//コンソールアプリを起動・コマンド投入するボタン
{
TTprocess();
}
private void button11_Click(object sender, EventArgs e)//終了ボタン
{
ProcessEnd();
}
}
}
自分で試したこと
調べたけと自分の知識がたりなくてよくわかりませんでした。
閲覧したサイト
https://takap-tech.com/entry/2017/07/08/151756
https://cammy.co.jp/technical/c_redirect/
https://atmarkit.itmedia.co.jp/ait/articles/0710/11/news123.html
https://www.fenet.jp/dotnet/column/language/9639/
https://biotech-lab.org/articles/10000
https://www.ipentec.com/document/csharp-get-standard-output-async
https://qiita.com/acple@github/items/8f63aacb13de9954c5da
https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/async/