Из приложения Windows C # мы хотим запустить cipher.exe, чтобы удалить данные из неиспользуемого дискового пространства, в данном случае диск D:
cipher.exe /w:D:\
Когда это делается из командной строки Windows, вывод будет:
To remove as much data as possible, please close all other applications while
running CIPHER /W.
Writing 0x00
...................................................................................................
Writing 0xFF
...................................................................................................
Writing Random Numbers
...................................................................................................
Эти строки с точками заполняются постепенно в течение всей процедуры шифрования. Мы думали, что будем читать эти точки из приложения C #, чтобы отслеживать прогресс и отображать его на индикаторе выполнения. Однако мы заметили, что когда стандартный вывод захвачен или перенаправлен, порядок отличается:
cipher.exe /w:D:\ > out.txt
В результате получается файл со следующим содержимым:
To remove as much data as possible, please close all other applications while
running CIPHER /W.
Writing 0x00
Writing 0xFF
Writing Random Numbers
...................................................................................................
...................................................................................................
...................................................................................................
И поэтому, когда мы пытаемся захватить это из приложения C #, мы не читаем точки до самого конца процесса. Например, при использовании следующего кода:
private void RunCipher()
{
using (Process cipherProcess = new Process())
{
try
{
// Cipher does three phases, one with 00s, one with FFs and one with random bits
// We count dots in the output for each phase to track the progress
// The amount of dots per phase is always 99 (independent of the volume size)
// See the end of this file to find the expected output
cipherProcess.StartInfo.FileName = "cipher.exe";
cipherProcess.StartInfo.Arguments = @"/w:D:\";
cipherProcess.StartInfo.RedirectStandardOutput = true;
cipherProcess.StartInfo.RedirectStandardError = true;
cipherProcess.StartInfo.RedirectStandardInput = true;
cipherProcess.StartInfo.UseShellExecute = false;
cipherProcess.StartInfo.CreateNoWindow = true;
cipherProcess.OutputDataReceived += CipherProcess_OutputDataReceived;
cipherProcess.ErrorDataReceived += CipherProcess_ErrorDataReceived;
cipherProcess.Exited += CipherProcess_Exited;
cipherProcess.Start();
cipherProcess.BeginOutputReadLine();
cipherProcess.BeginErrorReadLine();
cipherProcess.WaitForExit();
}
catch
{
Console.WriteLine("Exception occured");
}
}
Console.WriteLine("Fininshed");
}
private void CipherProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("OutputDataReceived: " + e.Data);
}
private void CipherProcess_Exited(object sender, EventArgs e)
{
Console.WriteLine("Exited");
}
private void CipherProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("ErrorDataReceived: " + e.Data);
}
Вывод этого:
OutputDataReceived: To remove as much data as possible, please close all other applications while
OutputDataReceived: running CIPHER /W.
OutputDataReceived: Writing 0x00
The thread 0x41ac has exited with code 0 (0x0).
The thread 0x408c has exited with code 0 (0x0).
OutputDataReceived: Writing 0xFF
The thread 0x39e4 has exited with code 0 (0x0).
The thread 0x3e30 has exited with code 0 (0x0).
OutputDataReceived: Writing Random Numbers
The thread 0x34ac has exited with code 0 (0x0).
The thread 0x3960 has exited with code 0 (0x0).
OutputDataReceived: ...................................................................................................
OutputDataReceived: ...................................................................................................
OutputDataReceived: ...................................................................................................
ErrorDataReceived:
OutputDataReceived:
Fininshed
Мы также пытались без OutputDataReceived + BeginOutputReadLine и вместо этого использовать process.StandardOutput.Read (), но у него есть та же проблема: сначала он читает все три из вывода «Writing (..)»:
private void RunCipher2()
{
using (Process cipherProcess = new Process())
{
try
{
cipherProcess.StartInfo.FileName = "cipher.exe";
cipherProcess.StartInfo.Arguments = @"/w:D:\";
cipherProcess.StartInfo.RedirectStandardOutput = true;
cipherProcess.StartInfo.RedirectStandardError = true;
cipherProcess.StartInfo.RedirectStandardInput = true;
cipherProcess.StartInfo.UseShellExecute = false;
cipherProcess.StartInfo.CreateNoWindow = true;
cipherProcess.Start();
while (!cipherProcess.StandardOutput.EndOfStream)
{
char nextChar = (char)cipherProcess.StandardOutput.Read();
Console.Write(nextChar);
}
cipherProcess.WaitForExit();
}
catch
{
Console.WriteLine("Exception occured");
}
}
Console.WriteLine("Fininshed");
}
И все же вывод в порядке, которого мы не ожидали:
To remove as much data as possible, please close all other applications while
running CIPHER /W.
Writing 0x00
Writing 0xFF
Writing Random Numbers
...................................................................................................
...................................................................................................
...................................................................................................
Fininshed
Мы уже нашли этот поток, но это решение требует перенаправленного вывода для первой работы: Считать Process StandardOutput до получения новой строки
Что здесь происходит? Есть ли способ сделать эту работу? Или отслеживать прогресс по-другому? Конечно, мы могли бы обнаружить сообщения «Написание» и сообщать о прогрессе в трети ... но кажется, что это должно быть возможно:)