阅读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
它没有为我工作,在另一个绅士的帖子
他与管道第一写一个批处理文件描述,然后执行它...
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。
我一直在努力做这事,只是偶然在另一solution由Hector 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;
}
谢谢斯蒂芬,我在当前的代码中写有char数组。我试着将字符切换成字节并写入。这两种方法都不起作用,并产生不同的错误 – CVertex 2010-08-15 09:48:52