Чтение System.Diagnostics.ProcessStartInfo StandardOutput в виде байтов вместо символов - PullRequest
3 голосов
/ 15 августа 2010

Я пытаюсь автоматизировать дамп svnadmin с помощью C # ProcessStartInfo.

То, как я это делал в командной строке, выглядит примерно так:

svnadmin dump c:\Repositories\hackyhacky > c:\backup\hackyhacky.svn_dump

Работает с лечением и успешно создает дамп, и я могу убедиться в этом, восстановив его в другом хранилище, например

svnadmin load c:\Repositories\restore_test < c:\backup\hackyhacky.svn_dump

Который успешно восстанавливает - ууу!

Теперь ... Мне нужно скопировать трубопровод командной строки в другой файл, используя C #, но по какой-то причине

var startInfo = new ProcessStartInfo(Path.Combine(SvnPath, "svnadmin"),"dump c:\Repositories\hackyhacky")
 {CreateNoWindow = true, RedirectStandardOutput = true,RedirectStandardError = true,UseShellExecute = false};
process.StartInfo = startInfo;
process.Start();
StreamReader reader = process.StandardOutput;
char[] standardOutputCharBuffer = new char[4096];
byte[] standardOutputByteBuffer;
int readChars = 0;
long totalReadBytes = 0;

// read from the StandardOutput, and write directly into another file

using (StreamWriter writer = new StreamWriter(@"C:\backup\hackyhacky.svn_dump", false)) {
    while (!reader.EndOfStream) {
       // read some chars from the standard out
       readChars = reader.Read(standardOutputCharBuffer, 0, standardOutputCharBuffer.Length);

       // convert the chars into bytes
       standardOutputByteBuffer = reader.CurrentEncoding.GetBytes(standardOutputCharBuffer);

       // write the bytes out into the file
       writer.Write(standardOutputCharBuffer.Take(readChars).ToArray());

       // increment the total read
       totalReadBytes += standardOutputByteBuffer.Length;
    }                    
}

Сбрасывает тот же репо в hackyhacky.svn_dump.

Но теперь, когда я запускаю командную строку загрузки,

svnadmin load c:\Repositories\restore_test < c:\backup\hackyhacky.svn_dump

Я получаю странную ошибку контрольной суммы!

svnadmin load c:\Repositories\restore_test < c:\backup\hackyhacky.svn_dump
< Started new transaction, based on original revision 1
     * adding path : Dependencies ... done.
     * adding path : Dependencies/BlogML.dll ...svnadmin: Checksum mismatch, fil
e '/Dependencies/BlogML.dll':
   expected:  d39863a4c14cf053d01f636002842bf9
     actual:  d19831be151d33650b3312a288aecadd

Полагаю, это связано с тем, как я перенаправляю и читаю StandardOutput.

Кто-нибудь знает, как правильно имитировать поведение конвейера файла командной строки в C #?

Любая помощь очень ценится.

-cv

UPDATE

Я пытался использовать BinaryWriter и использовать стандартныйOutputByteBuffer для записи в файл, но это тоже не работает. Я получаю другую ошибку о неправильном формате заголовка или чем-то подобном.

Ответы [ 3 ]

1 голос
/ 15 августа 2010

Хорошо! Если вы не можете победить их, присоединяйтесь к ним ....

Я нашел сообщение, в котором автор передает файл непосредственно в Process StartInfo и утверждает, что он работает.

http://weblogs.asp.net/israelio/archive/2004/08/31/223447.aspx

Это не сработало для меня, как описано в посте другого джентльмена

http://webcache.googleusercontent.com/search?q=cache:http://www.deadbeef.com/index.php/redirecting_the_output_of_a_program_to_a

Сначала он пишет командный файл с помощью трубопровода, а затем выполняет его ...

amWriter bat = File.CreateText("foo.bat"); 
bat.WriteLine("@echo off"); 
bat.WriteLine("foo.exe -arg >" + dumpDir + "\\foo_arg.txt"); 
bat.Close(); 
Process task = new Process(); 
task.StartInfo.UseShellExecute = false; 
task.StartInfo.FileName = "foo.bat"; 
task.StartInfo.Arguments = ""; 
task.Start(); 
task.WaitForExit();

По его словам:

Действительно ужасно, но у него есть Преимущество работы!

Чтобы быть совершенно откровенным, я немного раздражен, это заняло у меня столько времени, что и решение для пакетного файла работает хорошо, поэтому я буду придерживаться его.

0 голосов
/ 30 августа 2012

Я пытался сделать то же самое, и просто наткнулся на другое решение проблемы, используемой Гектором Сосой svnmanagerlib sourceforge project:

Ключом к решению этой проблемы было окружение вызова WaitForExit () файловые операции. Также необходимо убедиться, что записать вывод на диск. Вот соответствующие строки:

File.AppendAllText (destinationFile, myOutput.ReadToEnd ()); svnCommand.WaitForExit (); File.AppendAllText (destinationFile, myOutput.ReadToEnd ());

Обратите внимание, что я дважды вызываю File.AppendAllText (). я нашел что поток вывода не пишет все во время первого вызова в File.AppendAllText () в некоторых случаях.

public static bool ExecuteWritesToDiskSvnCommand(string command, string arguments, string destinationFile, out string errors)
        {
            bool retval = false;
            string errorLines = string.Empty;
            Process svnCommand = null;
            ProcessStartInfo psi = new ProcessStartInfo(command);

            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = false;
            psi.CreateNoWindow = true;

            try
            {
                Process.Start(psi);
                psi.Arguments = arguments;
                svnCommand = Process.Start(psi);

                StreamReader myOutput = svnCommand.StandardOutput;
                StreamReader myErrors = svnCommand.StandardError;

                File.AppendAllText(destinationFile, myOutput.ReadToEnd());
                svnCommand.WaitForExit();
                File.AppendAllText(destinationFile, myOutput.ReadToEnd());

                if (svnCommand.HasExited)
                {
                    errorLines = myErrors.ReadToEnd();
                }

                // Check for errors
                if (errorLines.Trim().Length == 0)
                {
                    retval = true;
                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                errorLines += Environment.NewLine + msg;
            }
            finally
            {
                if (svnCommand != null)
                {
                    svnCommand.Close();
                }
            }

            errors = errorLines;

            return retval;
        }
0 голосов
/ 15 августа 2010

Первое, что я бы попробовал, это записать в файл массив символов, а не байтовый массив.

Это должно работать, пока на выходе будет простой текст.Однако есть и другие проблемы с кодировкой, если вывод более сложный: вы записываете файл как UTF-8, тогда как по умолчанию для вывода из командной строки (я считаю) используется Windows-1252.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...