Stefan
Stefan

Reputation: 382

PowerShell, only "> $out" catch full error of failed 7Zip extract, why?

I tried all suggestion on how to catch errors of 7Zip as explained in:

and played with try / catch.

Second contains only

Cannot find drive. A drive with the name ' 7-Zip 18.05 (x64) ' does not exist.

in Error[0]

If I write the console output

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:
1 file, 51273 bytes (51 KiB)

Extracting archive: \\...\850\DAY01
--
7z.exe : ERROR: Data Error : DAY01.RAW
At C:\Users\MyUser\Code\7Zip.ps1:6 char:1
+ & $7ZIP_FullPath x $IN_FullPath -o$OUT_Directory -y
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (ERROR: Data Error : DAY01.RAW:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Path = \\...\850\DAY01
Type = gzip
Headers Size = 20


Sub items Errors: 1

Archives with Errors: 1

Sub items Errors: 1

in a variable, the variable will contain only

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:
1 file, 51273 bytes (51 KiB)

Extracting archive: \\...\850\DAY01
--    
Path = \\...\850\DAY01
Type = gzip
Headers Size = 20


Sub items Errors: 1

Archives with Errors: 1

Sub items Errors: 1

It looks like, that

7z.exe : ERROR: Data Error : DAY01.RAW
    At C:\Users\MyUser\Code\7Zip.ps1:6 char:1
    + & $7ZIP_FullPath x $IN_FullPath -o$OUT_Directory -y
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (ERROR: Data Error : DAY01.RAW:String) [], RemoteException
        + FullyQualifiedErrorId : NativeCommandError

is created by PowerShell (what explaiuns 7z.exe : ERROR:..) and can only be captured if I use $out:

& $7ZIP_FullPath x $IN_FullPath -o$OUT_Directory -y > $out

It looks like $out triggers something but what?

Upvotes: 0

Views: 1204

Answers (2)

John Kopparhed
John Kopparhed

Reputation: 171

7zip is not a PowerShell command so you can’t use the ordinary try{}catch{} with the -ErrorAction Stop

But 7zip has the ability to send out the %errorlevel% values in batch. Which is a better way to find an error

So According to the documentation these are the possible exit codes (%ERRORLEVEL% values): Code Meaning

==== =======

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

==== =======

In cmd or in a .bat file, there is no problem to run the 7zip command, and on the second line take out the %errorlevel% value, but in powershell you can’t really do that.

If you write the following code in powershell

To Zip:

& cmd.exe /c 'C:\"Program Files"\7-Zip\7z.exe a –mx1 "c:\DestinationFolder\NameOnZipFiles" c:\FolderToZip\*&echo:%errorlevel%'

To Unzip:

& cmd.exe /C 'C:\"Program Files"\7-Zip\7z.exe x "c:\SourceFolder" -o"D:\DestinationFolder" -y&echo:%errorlevel%' 

You will notice that the %errorlevel% will always be 0, even if the command fails. That’s because the %errorlevel% you get is the errorlevel before the command has run.

So to fix that problem you will have to enable the “DelayedExpansion” in cmd with “cmd.exe /v /c the “%” will also have to be changed to “!” to use the delayed function.

So the correct command needs to be written like this to get the correct errorlevel

To Zip:

& cmd.exe /v /c 'C:\"Program Files"\7-Zip\7z.exe a –mx1  "c:\DestinationFolder\NameOnZipFiles" c:\FolderToZip\*&echo:!errorlevel!'

To Unzip:

& cmd.exe /v /C 'C:\"Program Files"\7-Zip\7z.exe x "c:\SourceFolder" -o"D:\DestinationFolder" -y&echo:!errorlevel!' 

More info about the “DelayedExpansion” in cmd https://ss64.com/nt/delayedexpansion.html

Also If you only want to display the errorlevel after command has run, add the following 7zip options “-bso0 -bsp0 -bse0”

To Zip:

& cmd.exe /v /c 'C:\"Program Files"\7-Zip\7z.exe a –mx1 "c:\DestinationFolder\NameOnZipFiles" c:\FolderToZip\* -bso0 -bsp0 -bse0&echo:!errorlevel!'

To Unzip:

& cmd.exe /v /C 'C:\"Program Files"\7-Zip\7z.exe x "c:\SourceFolder" -o"D:\DestinationFolder" –y -bso0 -bsp0 -bse0&echo:!errorlevel!' 

But in your case, if your only after having the error text in the same variable just add the 7zip option -bse1

$out=& $7ZIP_FullPath x $IN_FullPath -o$OUT_Directory -y -bse1

Upvotes: 1

Stefan
Stefan

Reputation: 382

@daniel comments got me on the right track but still, I can not explain fully why only this solution is working.

$7ZIPExtractResult= & $7ZIP_FullPath x $IN_FullPath -o$OUT_Directory -y *>&1

Redirects the specified stream to the Success stream.

My guess is, that only that way it can be stored in a variable. I found help in What does 2>&1 Mean in PowerShell - Stack Overflow and about_Redirection - PowerShell | Microsoft Docs.

In addition, the variable $7ZIPExtractResult is a System.Object[], so I have to do convert an array to a string doing 7ZIPExtractResultAsString = "$7ZIPExtractResult", expecting that is always possible and not throwing a different error.

It is still unknown to me why this error is not caught by

try {
}
catch {
}

Upvotes: 0

Related Questions