I had an interesting time with the output of the "svnadmin dump" command. My original implementation looks like this:
189 public static bool ExecuteSvnCommand( string command, string arguments, out string result, out string errors )
190 {
191 bool retval = false;
192 string output = string.Empty;
193 string errorLines = string.Empty;
194 Process svnCommand = null;
195 ProcessStartInfo psi = new ProcessStartInfo( command );
196
197 psi.RedirectStandardOutput = true;
198 psi.RedirectStandardError = true;
199 psi.WindowStyle = ProcessWindowStyle.Hidden;
200 psi.UseShellExecute = false;
201 psi.CreateNoWindow = true;
202
203 try
204 {
205 Process.Start( psi );
206 psi.Arguments = arguments;
207 svnCommand = Process.Start( psi );
208
209 StreamReader myOutput = svnCommand.StandardOutput;
210 StreamReader myErrors = svnCommand.StandardError;
211 svnCommand.WaitForExit();
212
213 if ( svnCommand.HasExited )
214 {
215 output = myOutput.ReadToEnd();
216 errorLines = myErrors.ReadToEnd();
217 }
218
219 // Check for errors
220 if ( errorLines.Trim().Length == 0 )
221 {
222 retval = true;
223 }
224 }
225 catch ( Exception ex )
226 {
227 string msg = ex.Message;
228 errorLines += Environment.NewLine + msg;
229 }
230 finally
231 {
232 if (svnCommand != null)
233 {
234 svnCommand.Close();
235 }
236 }
237
238 result = output;
239 errors = errorLines;
240
241 return retval;
242 }
This code works for all the other commands just fine. The culprit ended up being line 211. I created a new function to handle this. The code is below:
253 public static bool ExecuteWritesToDiskSvnCommand( string command, string arguments, string destinationFile, out string errors )
254 {
255 bool retval = false;
256 string errorLines = string.Empty;
257 Process svnCommand = null;
258 ProcessStartInfo psi = new ProcessStartInfo( command );
259
260 psi.RedirectStandardOutput = true;
261 psi.RedirectStandardError = true;
262 psi.WindowStyle = ProcessWindowStyle.Hidden;
263 psi.UseShellExecute = false;
264 psi.CreateNoWindow = true;
265
266 try
267 {
268 Process.Start( psi );
269 psi.Arguments = arguments;
270 svnCommand = Process.Start( psi );
271
272 StreamReader myOutput = svnCommand.StandardOutput;
273 StreamReader myErrors = svnCommand.StandardError;
274
275 File.AppendAllText( destinationFile, myOutput.ReadToEnd() );
276 svnCommand.WaitForExit();
277 File.AppendAllText( destinationFile, myOutput.ReadToEnd() );
278
279 if ( svnCommand.HasExited )
280 {
281 errorLines = myErrors.ReadToEnd();
282 }
283
284 // Check for errors
285 if ( errorLines.Trim().Length == 0 )
286 {
287 retval = true;
288 }
289 }
290 catch ( Exception ex )
291 {
292 string msg = ex.Message;
293 errorLines += Environment.NewLine + msg;
294 }
295 finally
296 {
297 if ( svnCommand != null )
298 {
299 svnCommand.Close();
300 }
301 }
302
303 errors = errorLines;
304
305 return retval;
306 }
The key to solving this was surrounding the call to WaitForExit() with file operations. Also needed to make sure to write the output to disk. Here are the relevant lines:
275 File.AppendAllText( destinationFile, myOutput.ReadToEnd() );
276 svnCommand.WaitForExit();
277 File.AppendAllText( destinationFile, myOutput.ReadToEnd() );
Notice that I make a call to File.AppendAllText() twice. I have found that the output stream does not write everything during the first call to File.AppendAllText() on some occasions.
This will be obvious to people that are used to doing this in C and C++ and using stdoutpu and stderror. It's been a LONG time since I had to do anything like this.
I had to dig for this information quite deep, as MSDN does not tell you about this, or my Google-Fu was not up to par.
This code can be found in the open sourced library called SVNMangerLib. You can find it here:
SVNManagerLib
I formatted my source code in Visual Studio 2005 using this little gem:
CopySourceAsHtml for Microsoft Visual Studio 2005