阅读System.Diagnostics.ProcessStartInfo标准输出为字节,而不是字符

问题描述:

我想使用C#ProcessStartInfo自动化svnadmin转储。阅读System.Diagnostics.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和使用standardOutputByteBuffer写入文件试过,但也不管用。我收到关于错误标题格式或其他内容的错误。

好吧!如果你不能击败他们,加入他们....

我发现一个职位,作者管道直接在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(); 

用他的话说:

真正可怕的,但它具有 优势的工作!

坦白地说,我有点恼火,这让我只要有它,所以批处理文件解决方案效果很好,所以我会坚持下去。

我会尝试的第一件事是将字符数组写入文件中,而不是字节数组。

只要输出只是简单的文本,就应该工作。但是,如果输出更复杂,还有其他编码问题:您将文件编写为UTF-8,而命令行输出(我相信)的默认值为Windows-1252。

+0

谢谢斯蒂芬,我在当前的代码中写有char数组。我试着将字符切换成字节并写入。这两种方法都不起作用,并产生不同的错误 – CVertex 2010-08-15 09:48:52

我一直在努力做这事,只是偶然在另一solutionHector Sosa'ssvnmanagerlib SourceForge项目中使用的问题:

的关键,解决这个被周边调用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; 
     }