2017-12-28 34 views
0

私は、別の言語のGUIスクリプトをVS2017のC#に変換する作業をしています。ここの人々からの助けを借りて、私はその道の95%ですが、いくつかの障害に遭遇しました。私が最善のやり方で物事をしているかどうか分からない。私は以下のコードの関連部分だけを含めています。十分に提供していないかどうか教えてください:powershellスクリプトの出力をキャプチャする

コードの大部分は、 VMware環境への仮想マシンの数この数は、一度に数十台、または数百台のVMに容易に広がります。各VMの情報はフォームで指定され、その後、リストビューで収集されます。リストビューが一杯になると、それはCSVにエクスポートされます。これまですべてがうまくいきました。

次に、実際にpowershell/powerCLIスクリプトを起動して(作業中でも)、出力をキャプチャしています。ログファイルは、顧客が使用する特定のリーダアプリケーションで開かれ、リアルタイムで更新され、キャプチャされた出力がログに送られます。技術者はコードからの出力を1行で確認することが重要であり、問​​題があれば反応することができます。

私はテストとして、このような何かを開始しました:

string sPSScript = "C:\\Users\\Admin\\Desktop\\TestC#.ps1"; 
string logFile = "C:\\Users\\Admin\\Desktop\\My.log"; 
string logReader = "C:\\Users\\Admin\\Documents\\CMTrace.exe"; 
string standard_output; 

System.Diagnostics.Process PSScript = new System.Diagnostics.Process(); 
PSScript.StartInfo.FileName = 
Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + 
"\\WindowsPowerShell\\v1.0\\powershell.exe"; 
PSScript.StartInfo.Arguments = "-command . '" + sPSScript + "' " + 
vCenter.Text; 
PSScript.StartInfo.RedirectStandardOutput = true; 
PSScript.StartInfo.UseShellExecute = false; 
PSScript.Start(); 
System.Diagnostics.Process LogFile = new System.Diagnostics.Process(); 
LogFile.StartInfo.FileName = logReader; 
LogFile.StartInfo.Arguments = logFile; 
LogFile.Start();  while ((standard_output = 
PSScript.StandardOutput.ReadLine()) != null) 
    { 
     if (standard_output != "") 
     { 
      using (StreamWriter file = new StreamWriter(logFile, append: true)) 
      { 
       file.WriteLine(standard_output); 
      } 
     } 
    } 

を予想通り、これはリアルタイムでログファイルに書き込まれますが、それはログリーダーアプリケーションの100個のインスタンスを作成します。私は理由を理解しています。なぜなら、すべてのパスで新しいStreamWriterオブジェクトを宣言しているからですが、これについてどうすればよいかわかりません。

私はこのように、ループの外にファイルを作成してみました:

StreamWriter file = new StreamWriter(logFile, append: true) { }; 
System.Diagnostics.Process LogFile = new System.Diagnostics.Process(); 
LogFile.StartInfo.FileName = logReader; 
LogFile.StartInfo.Arguments = logFile; 

System.Diagnostics.Process PSScript = new System.Diagnostics.Process(); 
    PSScript.StartInfo.FileName = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + "\\WindowsPowerShell\\v1.0\\powershell.exe"; 
    PSScript.StartInfo.Arguments = "-command . '" + sPSScript + "' " + vCenter.Text; 
    PSScript.StartInfo.RedirectStandardOutput = true; 
    PSScript.StartInfo.UseShellExecute = false; 

    LogFile.Start(); 
    PSScript.Start(); 
    System.Threading.Thread.Sleep(1500); 

    while ((standard_output = PSScript.StandardOutput.ReadLine()) != null) 
    { 
    if (standard_output != "") 
    { 
     file.WriteLine(standard_output); 
    } 
    } 

これは、複数のインスタンスを作成しませんが、前のコードがないとして、それはまた、リアルタイムでログファイルを更新しません。スクリプトが実行されると更新され、部分的にのみ更新されます。スクリプトは〜1000行の出力を生成し、私は一貫してログファイルに書き込まれるのは約840だけです。

私はこのような何かをやって考えた:

FileStream logFS; 
logFS = new FileStream(logFile, FileMode.Append); 

が、バイト配列を期待していることは、ファイルに書き込むために私に利用できる唯一のオプションが表示されます。

私はこれで単純なものが紛れていると確信していますが、ログファイルを作成して読者に開き、powershellスクリプトの標準出力で更新するのが最も簡単な方法。

答えて

1

なぜ前のコードでリアルタイムで書き込みを行ったのですか?

これはusingでラップしているためです。そして

ディスクへの書き込みに .Flushを呼び出し、そのつもりコール処分をブロック usingの終わりにあなたの2番目のコードブロックは WriteLineを呼び出しますが、 Flush呼び出されることはありませんので、バッファがいっぱいになるたびにディスクに書き込みます。 WriteLineの後に .Flushコールを追加すると、リアルタイムログが記録されます

+0

これはお手伝いしました。問題の一部は、ログアプリケーションが画面を再描画できるよりも速く書いているようです。私は出力を見ることができるように、それぞれの書き込みの後に眠る必要がありました。 – JLogan3o13