2

If I running this function (with out try..catch):

executezipFullBackup -PathFileLocation "Z:\" -PathSaveBackup "E:\" -NameOfBackup "MyNASStorage"

PoweShell give me this error:

sz : 
At C:\PowerShellF\zipFunction.ps1:6 char:9
+         sz a -t7z "$PathSaveBackup\$NameOfBackup" "$PathFileLocation"  #backup
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

ERROR:
Duplicate filename on disk:
BackupTest\private\103.tmp\usr\bin\mail
BackupTest\private\103.tmp\usr\bin\Mail

And that error is OK for me, because I know what is wrong on this step.

But my problem is, if I put this script in try..catch, I dont get this error. Example:

$ErrorActionPreference = "Stop";      #this is for Try Catch
try {
    zipFullBackup -PathFileLocation "$PathFileLocation" -PathSaveBackup "$PathSaveBackup" -NameOfBackup "$NameOfBackup"          
} catch {
    $MyError = ($Error[0] | Out-String);
    Write-Host "$MyError"
}

I get error like this:

sz : 
At C:\PowerShellF\zipFunction.ps1:6 char:9
+         sz a -t7z "$PathSaveBackup\$NameOfBackup" "$PathFileLocation" #backup
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

This error is not enough for me, because I don't see ERROR! I don't see this:

ERROR:
Duplicate filename on disk:
BackupTest\private\103.tmp\usr\bin\mail
BackupTest\private\103.tmp\usr\bin\Mail

How can I get try..catch to display this error?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Marev
  • 31
  • 1
  • 3

2 Answers2

0

That error message is not part of a PowerShell error/exception, but a message 7zip itself prints to STDOUT. Therefore it can't be caught with a try..catch block, not even if you set $ErrorActionPreference = 'Stop'.

What you can do is collect the command output in a variable, though:

$msg = zipFullBackup ...
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Even though it is not a powershell error/exeption, it does stop the program and does enter the "Catch" part. If you exclude the try catch block, the program crashes with more information, than you can get out of the $Error variable. The OPs question was how to get that information. – Ratzor Mar 20 '16 at 15:28
  • How would a command print more information to the console after it did a throw? Something does not seem to make sense here. – Kory Gill Mar 20 '16 at 17:25
  • Without the try catch block, when the program crashes, it displays some information. The question is how to get that information without crashing the program....meaning in the catch – Ratzor Mar 20 '16 at 17:58
  • 1
    @Ratzor Please make sure you actually understand an answer before downvoting it (you may find [this article](https://mnaoumov.wordpress.com/2015/01/11/execution-of-external-commands-in-powershell-done-right/) educational). The output starting with the line `ERROR:` is created by the 7-zip executable itself and is printed to STDOUT. It can be captured as described in my answer. It does not automagically get included in a PowerShell error object and is thus not subject to `try..catch`. – Ansgar Wiechers Mar 20 '16 at 22:41
  • 1
    @KoryGill Output on different streams is not guaranteed to be printed in the order it's generated. – Ansgar Wiechers Mar 20 '16 at 22:46
  • @AnsgarWiechers, yeah, assumed something like that but really did not have anything to back this up, and did not have time to code up a sample exe to satisfy my own curiosity. Other than the answer you gave, not much you can do other than maybe try to capture the various output streams (2>&1 type stuff), etc. – Kory Gill Mar 20 '16 at 23:24
  • @AnsgarWiechers i do understand your answer, and i do know it won't work. ```zipFullBackup``` is a function, and it won't save anything to a variable if it isn't returning anything. That function is making the call to the external program. In the line where the call is made a change would be needed to save errors to a variable and then return it. Your answer doesn't give any information about how to do that, which is the main question here. – Ratzor Mar 21 '16 at 13:44
  • @Ratzor I don't think you fully comprehend my answer. Again, the 7-zip executable writes the "error" message to STDOUT. PowerShell functions (yes, I am aware that `zipFullBackup` most likely is a function) [return](https://technet.microsoft.com/library/hh847760.aspx) all non-captured output on the success output stream (AKA STDOUT). So unless the function does any magic that the OP didn't tell us about, all non-captured output inside the function is returned to the caller and can thus be captured in a variable as described in my answer. – Ansgar Wiechers Mar 21 '16 at 13:54
0

The solution for your question is to add the 7zip option -bse1

& cmd.exe /c 'C:\"Program Files"\7-Zip\7z.exe a "c:\DestinationFolder\NameOnZipFiles" c:\FolderToZip\* -bse1

But a better solution for this is to take out the 7zip %errorlevel% from batch, because 7zip is not a PowerShell command. To do so, use the following code in powershell. Yes the errorlevel variable needs to be written with !errorlevel!

[int]$7zipError=& cmd.exe /v /c 'C:\"Program Files"\7-Zip\7z.exe a -mx0 "c:\DestinationFolder\NameOnZipFiles" c:\FolderToZip\*  -bso0 -bsp0 -bse0 &echo:!errorlevel!'

if ($7zipError -gt 0)
{
Write-Host "Errorlevel: $($errorlevel)"
#0          No error
#1          Warning (Non fatal error(s)). For example, one or more files were locked by some other application, so they were not compressed.
#2          Fatal error
#7          Command line error
#8          Not enough memory for operation
#255        User stopped the process
} 

If you want to know more and why you need to use “cmd.exe /v” I have written more about this in PowerShell, only "> $out" catch full error of failed 7Zip extract, why?

John Kopparhed
  • 171
  • 1
  • 4