C# 将System.Diagnostics.ProcessStartInfo标准输出读取为字节而不是字符
我正在尝试使用C#ProcessStartInfo自动化svnadmin转储 我在命令行上的做法是这样的C# 将System.Diagnostics.ProcessStartInfo标准输出读取为字节而不是字符,c#,.net,svn,C#,.net,Svn,我正在尝试使用C#ProcessStartInfo自动化svnadmin转储 我在命令行上的做法是这样的 svnadmin dump c:\Repositories\hackyhacky>c:\backup\hackyhacky.svn\u dump 工作处理并成功转储,我可以通过将其恢复到另一个存储库来验证这一点 svnadmin加载c:\Repositories\restore\u test
svnadmin dump c:\Repositories\hackyhacky>c:\backup\hackyhacky.svn\u dump
工作处理并成功转储,我可以通过将其恢复到另一个存储库来验证这一点
svnadmin加载c:\Repositories\restore\u test
它成功地恢复了-耶
现在。。。我需要使用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_转储中
但是当我现在运行load命令行时
svnadmin加载c:\Repositories\restore\u test
我得到一个校验和错误奇怪的错误
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
svnadmin加载c:\Repositories\restore\u测试
我猜这与我如何重定向和读取标准输出有关
有人知道在C#中模拟命令行文件管道行为的正确方法吗
非常感谢您的帮助
-简历
更新
我曾尝试使用BinaryWriter和standardOutputByteBuffer写入文件,但这也不起作用。关于不正确的头格式或其他内容,我遇到了一个不同的错误。我要尝试的第一件事是将字符数组(而不是字节数组)写入文件
只要输出只是简单的文本,这就应该可以工作。但是,如果输出更复杂,则还有其他编码问题:您将文件写入UTF-8,而命令行输出的默认值(我相信)是Windows-1252。好吧!如果你不能打败他们,加入他们 我发现了一篇文章,作者在StartInfo进程中直接将管道连接到一个文件,并声称它是有效的 正如另一位绅士的帖子所描述的那样,它对我不起作用 他先用管道编写一个批处理文件,然后执行它
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();
用他的话说:
真的很可怕,但它有
工作的好处
坦率地说,我有点恼火,这花了我这么长时间,所以批处理文件解决方案工作得很好,所以我将继续使用它。我一直在尝试做这件事,只是偶然发现了sourceforge项目使用的另一个问题: 解决这个问题的关键是使用 文件操作。还需要确保将输出写入磁盘。 以下是相关线路: AppendAllText(destinationFile,myOutput.ReadToEnd()); svnCommand.WaitForExit();File.AppendAllText(destinationFile, myOutput.ReadToEnd()) 请注意,我两次调用File.AppendAllText()。我找到了 输出流在第一次调用期间不会写入所有内容 在某些情况下,要将.AppendAllText()归档
谢谢Stephen,我正在使用当前代码编写char数组。我试着将字符转换成字节,并将其写入。这两种方法都不起作用,会产生不同的错误
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;
}