1

I have the following VB.NET 4.0 console application that runs 7z.exe in a process and successfully completes with a zipped file:

Public Sub CompressFiles(sZipFileName As String, sDriveLetter As String)

    Dim s7ZipCmdArgs As String = ""
    Dim myProcess As New Process

    Console.WriteLine()
    Console.WriteLine("Scanning files...")

    'Compress files
    s7ZipCmdArgs = " a -r -y -xr!windows\ -xr!$Recycle.Bin\ " + sZipFileName _
        + " " + sDriveLetter + "\*.txt" _
        + " " + sDriveLetter + "\*.doc" _
        + " " + sDriveLetter + "\*.xls" _
        + " " + sDriveLetter + "\*.ppt" _
        + " " + sDriveLetter + "\*.url" _
        + " " + sDriveLetter + "\*.docx" _
        + " " + sDriveLetter + "\*.xlsx" _
        + " " + sDriveLetter + "\*.pptx" _
        + " " + sDriveLetter + "\*.pdf" _
        + " " + sDriveLetter + "\*.wav" _
        + "> C:\test\zipresults.txt"

    myProcess.StartInfo.FileName = "C:\test\7-Zip\7z.exe"
    myProcess.StartInfo.Arguments = s7ZipCmdArgs
    myProcess.StartInfo.WorkingDirectory = "C:\test"
    myProcess.StartInfo.UseShellExecute = False
    myProcess.StartInfo.CreateNoWindow = True
    myProcess.Start()
    myProcess.WaitForExit()
End Sub

The code executes fine except for the redirect to a text file: "> C:\test\zipresults.txt" in the s7ZipCmdArgs string variable. I'm not sure why that's not working, I've tried different sets of double and triple quotes without success. It does work in a batch file using the same string.

My second question is: How do I capture the 7Zip exit code so that I can determine if it completed successfully? It returns the following integers: 0 (No errors), 1 (Non fatal error), 2 (Fatal error), 7 (Command line error), 8 (Memory error), and 255 (User error). I'm not sure how to capture the integer so that I can decode it.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
KenZ
  • 49
  • 10
  • I have tried the redirect ">" with spaces on both sides and next to the file definition without success. – KenZ May 02 '14 at 16:07
  • The myProcess.ExitCode method does contain the exit code for the 7Zip application. Good call. – KenZ May 02 '14 at 16:24
  • It seems that redirecting with `>` does not work from `Process.Start` - I've updated my answer. – Mark May 02 '14 at 16:49
  • After trying similar tasks with 7z I switched to DotNetZip - much easier. – rheitzman May 02 '14 at 18:06
  • The issue I have now is after myProcess.WaitForExit() executes the console output never returns. When I comment out RedirectStandardOutput = True, it works fine. Not sure what I'm missing. As for .NET zip, I was unable to search for all the file types and exclude Windows and the recycle bin. – KenZ May 02 '14 at 18:38
  • I've updated my answer to use the event handler for writing the output to a file - see if that helps. If not, please post your updated code. – Mark May 02 '14 at 18:54
  • The updated code works perfectly. – KenZ May 02 '14 at 19:11
  • Glad it's working! I suppose the previous issue was due to the volume of output being too much for some buffer, which I didn't hit in my test. – Mark May 02 '14 at 19:18
  • I'm not sure where the overflow was occurring, but the code works fine now. I appreciate your help. – KenZ May 02 '14 at 19:42

1 Answers1

3

For the first part, have you tried adding a space before the > in your command args? You could also check out this answer for capturing the output in code.

For the first part, per this answer you can't redirect the standard output using > when using Process.Start(). So, you will need to remove the redirect from the arguments, set StartInfo.RedirectStandardOutput to true, and then write the output to a file in the OutputDataReceived event. Something like this:

Dim pgm = "C:\Program Files\7-Zip\7z.exe"
Dim args = "l C:\Dev\Test.zip"
Dim myProcess = New Process()
With myProcess.StartInfo
    .FileName = pgm
    .Arguments = args
    .WorkingDirectory = "C:\Dev"
    .UseShellExecute = False
    .CreateNoWindow = True
    .RedirectStandardOutput = True
End With
Using out = New StreamWriter("C:\Dev\test.txt")
    AddHandler myProcess.OutputDataReceived,
        Sub(sender, e)
            out.WriteLine(e.Data)
        End Sub
    myProcess.Start()
    myProcess.BeginOutputReadLine()
    myProcess.WaitForExit()
End Using

For the second, myProcess.ExitCode will have the result after the WaitForExit() call.

Community
  • 1
  • 1
Mark
  • 8,140
  • 1
  • 14
  • 29