Zipper Bug

Started by MrLeadFoot, May 13, 2016, 08:42:44 PM

Previous topic - Next topic

MrLeadFoot

Used 2016a compiler to create a 32-bit .exe to ensure compatibility across multiple OSes, setup as follows:

To make it easy to test, created d:\ZipTest\ZipTest.ini, set up like so:

[ZIP]
Options=g
ZipFileName=d:\ZipTest\ZipTest.zip

Script contains:

Options=IniReadPvt("Zip","Options","","d:\ZipTest\ZipTest.ini")
ZipFileName=IniReadPvt("Zip","ZipFileName","","d:\ZipTest\ZipTest.ini")
File is derived from a loop within the script, to get files one by one so we could implement a progress bar using the aStatusBar function.

zZipFiles(Options,ZipFileName,File,"")

On a WinXP SP3 machine, the zip function randomly generates an "8004 unknown error". In other words, sometimes it works, sometimes it doesn't, and not much changes in terms of number or size of files being archived, or size of the archive itself. This same script, compiled with the previous zip version (34i) works flawlessly. FWIW, we have not experienced the error on Win7 machines, but we can't tell for sure if it will/will not happen because it's a truly random error. What sucks is that the ability to generate larger .zip files is one of the primary reasons we upgraded.

Thinking that there might be an issue since the 44i version supposedly has an "optional" password parameter, we did the following to see if including the optional password parameter might be needed (even though the Help says it's optional). Thus, we added a "password" key to the .ini file, and modified the script as follows:

.ini file:

[ZIP]
Options=g
ZipFileName=d:\ZipTest\ZipTest.zip
Password=

Script:

Options=IniReadPvt("Zip","Options","","d:\ZipTest\ZipTest.ini")
ZipFileName=IniReadPvt("Zip","ZipFileName","","d:\ZipTest\ZipTest.ini")
Password=IniReadPvt("Zip","Password","","d:\ZipTest\ZipTest.ini")
File is derived from a loop within the script, to get files one by one so we could implement a progress bar using aStatusBar function.

zZipFiles(Options,ZipFileName,File,"",Password)

This introduced yet another (possibly related?) problem. Turns out zZipFiles can't handle a blank password and the script crashes with a different error. But, if we insert a password into the .ini, like this:

Password=dingo

and run the script, the script runs just fine. Checking the Help did not help, because it does not specifically describe the password parameter, nor does it state that if you use the password parameter you MUST supply a password, or the function will fail (which is what happens). It simply leaves it up to the reader to interpret. In either case, there's obviously a problem, or two, with the new zZipFiles function. You either have to have a password to feed the function, or your syntax better not be setup to expect one, because if it is, and a password is not supplied, it WILL crash 100% of the time.

We can't always expect users to supply a password, so this presents a problem. We actually had to make a kludgy workaround for the second bug, and provide WB with two differently syntax-ed statements, one WITH the password parameter and one WITHOUT, as follows:

If Password==""
   zZipFiles(Options,ZipFileName,File,"")
Else
   zZipFiles(Options,ZipFileName,File,"",Password)
EndIf

We really shouldn't have to do something this unwieldly. The zZipFiles function should really be able to handle a null string in the password parameter.

And, we also still need to address the original "8004 unkown error" we are encountering on the WinXP machine.

Is it possible that both problems are related? If not, can you shed any light on both these issues? Thank you.

td

First, when a parameter is describe as 'optional' in the help file, it means that you can skip the parameter completely.  Passing an empty string in the parameter's position is not skipping it.  It is passing a value and when you do use any value including an empty string (""), the parameter will be validated.   An empty string is not a valid password so  you will get a 139 error.   This is and always has been the meaning of optional parameter in WIL documentation, is by design and will not change.

The 8004 error is the result of a system error.  The extender will attempt to obtain the error's system supplied text and append it to the text displayed by the error message box. However,  based on the information provide so far and since there are no outstanding issue with the extender, it is impossible to even guess at what is causing your system error.   It could be anything;  a bad spot on a disk, low process memory, some kind of stack corruption or any one of a number of other system related issues .

 





"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Should have also mentioned that if you can provide more information, can narrow down the cause or find and provide a reliable way to reproduce the problem, we are more than willing to look into it.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

Thank you for taking the time to reply.

The point I am making about the syntax issue is that the behavior is inconsistent with other WB functions, which DO support blank strings. For example Message, Pause, AskItem, IntControl, etc. all accept ("") as valid parameters. Why should zZipFiles be any different? Can you imagine how confusing it would be if some functions required periods (.) between parameters instead of commas (,)? The anomaly of zZipFiles not supporting ("") forces developers to have to worry about ("") in every function, and test to see if it's going to cause a problem or not. Think about it, if all functions' syntax were consistent, we could more quickly write scripts without having to stop and check everything, not to mention the Help doesn't say which functions support or don't support blank strings. That, in turn, causes more work for you guys, too, in that you have to field questions. If zZipFiles did support blank strings like the other functions do, this question would never have come up. If, for some reason, you can't figure out how to make it consistent with the other WB functions, its inconsistency should be documented in the Help.

While not the ideal scenario, if we knew that ("") is not supported only on those functions that have optional parameters, that sure would make things a lot easier on us, but again that should be notated in the Help. So, my questions now are, is ("") not supported in all functions with optional parameters, or is it only with zZipFiles? Or, are there other functions with this "gotcha" that we have to watch out for, and how can we know which ones they are without having to first test every function we want to use before implementing them into a script?

As far as the 8004 error is concerned, I want to be clear that we've been using this script for a VERY, VERY long time with an earlier compiler, and have NEVER encountered a problem. This has only begun to occur since compiling the same exact script with 2016a. Although from your perspective there doesn't appear to be any "outstanding issues" with the function or compiler, obviously there is. After all, issues don't become "issues" until people report them, which is what I am doing. Perhaps you could simply make note of this report, so when you see it happening with other people, you'll realize something really is wrong somewhere. Of course, there's also the fact that people don't always report issues.

td

Quote from: MrLeadFoot on May 14, 2016, 08:14:13 AM
Thank you for taking the time to reply.

The point I am making about the syntax issue is that the behavior is inconsistent with other WB functions, which DO support blank strings. For example Message, Pause, AskItem, IntControl, etc. all accept ("") as valid parameters. Why should zZipFiles be any different? Can you imagine how confusing it would be if some functions required periods (.) between parameters instead of commas (,)? The anomaly of zZipFiles not supporting ("") forces developers to have to worry about ("") in every function, and test to see if it's going to cause a problem or not. Think about it, if all functions' syntax were consistent, we could more quickly write scripts without having to stop and check everything, not to mention the Help doesn't say which functions support or don't support blank strings. That, in turn, causes more work for you guys, too, in that you have to field questions. If zZipFiles did support blank strings like the other functions do, this question would never have come up. If, for some reason, you can't figure out how to make it consistent with the other WB functions, its inconsistency should be documented in the Help.

While not the ideal scenario, if we knew that ("") is not supported only on those functions that have optional parameters, that sure would make things a lot easier on us, but again that should be notated in the Help. So, my questions now are, is ("") not supported in all functions with optional parameters, or is it only with zZipFiles? Or, are there other functions with this "gotcha" that we have to watch out for, and how can we know which ones they are without having to first test every function we want to use before implementing them into a script?

Other functions allow a blank string because it can use the value so it is a valid value.  The zZipFiles function cannot use a blank password and should generate an error.  There is nothing inconsistent about it.  In fact, as a developer you should be worried about any user supplied data.  This is particularly true of passwords.  Validation of user supplied data is more or less part of software development 101.

Note that the IntControl function is inconsistent with other WinBatch functions because it was first implemented before WIL and WinBatch allowed [optional] parameters.

Quote
As far as the 8004 error is concerned, I want to be clear that we've been using this script for a VERY, VERY long time with an earlier compiler, and have NEVER encountered a problem. This has only begun to occur since compiling the same exact script with 2016a. Although from your perspective there doesn't appear to be any "outstanding issues" with the function or compiler, obviously there is. After all, issues don't become "issues" until people report them, which is what I am doing. Perhaps you could simply make note of this report, so when you see it happening with other people, you'll realize something really is wrong somewhere. Of course, there's also the fact that people don't always report issues.

The new and old extenders have completely different implementation.  The core functionality of the extender is provided by a third party and was almost completely rewritten by them.  That the old version did work in the past and now the new doesn't, doesn't provide much if any guidance.  A lot of things can change.  The current incarnation of the extender has been around for quite awhile and there have been no reports of unexplained system errors from the zZipFiles function.  WinBatch users would have let us known about, it if the encountered this problem.   They are a breed apart in that they are very good about letting use know about our mistakes.  This topic is a prime example.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

Deciding whether or not you want to password protect a zip archive is entirely up to the user, so validation is not applicable here, in the true sense of "validation". They either want one or not. So, in its current incarnation, I'm guessing that the If statement we're using is the only way to allow users to not have passwords, which works, but is a little weird to have to do, you have to admit.

Regarding the zip extender randomly throwing an 8004, we ARE WB users, and we ARE reporting it. While the function's guts may have changed, the syntax (other than that weird password option) has not. We're basically passing the same values to the function. I don't know what else to tell you. I outlined what we're doing in the script. As with most WB functions, it's pretty simple, and you can't really screw it up. You either pass the proper information to a WB function, and it works, or you pass bad info and you get an error 100 percent of the time. In this particular case, we are indeed passing valid info with the correct syntax, as is evident by the fact that it does work... Sometimes. If it helps, I can tell you that whenever it 8004s on us, we run it again, and it works.

Everything I gave you above is what you can use to simulate the setup. Obviously if the loop to determine the file variable was faulty, we would have a different "you screwed up" message. But, we don't get that. All were doing is making a zip file with one file in it, then appending to that zip file with another file, and so forth, simply so that we can use aStatusBar to present a progress bar. I documented an abbreviated form of that script to simplify it for you so as to not clutter things up. The issue is not with the rest of the code, it is simply with the zip function. At least that's what the 8004 errors says. But, now that I think about it, errors are written by humans, so who knows? Tell me what it is that you would like me to send you that will help you see this problem. I can also video the computer screen every time we run the script so you can see the behavior if you like. I can assure you that we are not making this up. ;-)

td

Everything in your description of how to reproduce the problem is already a part of the regular regression and ad hoc testing for this function.  And while we appreciate the offer watching a video that does not help us.  We will check into this as time permits and any additional information comes to our attention.   If at some point in the future we do find a 'bug' in the the extender, it will be addressed,  a new version upload to our download page and a notice posted to this forum.

We thank you for reporting this problem to us.   We truly appreciate users taking the time to tell us about issues with WinBatch and related software. 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

OK, not sure if you care any more, seeing as you're shutting down your company soon, but I have determined what the problem is with the zZipperFiles function. If you recall, we are zipping files one by one using the "g" option so that we can throw up a progress bar via aStatusBar.

Turns out the script crashes when zZipFiles encounters, of all things, a WBDCD34i.DLL file! Figures. Now, just to be clear, the executable that contains the zZipFiles function was compiled using 2016a, thus is running a completely different .DLL. Further, the WBDCD34i.DLL being zipped resides in a subfolder that we recurse into, and is not in use (in fact, protocol is to run this script/.exe. immediately a fresh start of the computer), so for all intents and purposes zZipFiles should have no problem zipping that WBDCD34i.DLL file, yet it obviously does. In the subfolder where WBDCD34i.DLL resides are only 4 files, 3 executables and the WBDCD34i.DLL. The script zips each file in alphabetical order, and zips the 2 files ahead of WBDCD34i.DLL in the alphabetical order just fine, then crashes when it encounters WBDCD34i.DLL.

The interesting thing is that once is crashes and we run the script again, it runs just fine.

Does this shed any insight as to what might be going on, and how we might be able to resolve this?

td

All of us at WWW have been a bit busy of late...   But it will get looked into when  time permits.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot


td

Happened to notice that you used the term 'crash' again.  Your script is not 'crashing' in any conventional sense.   It is displaying a WinBatch error message box.  If it were 'crashing', you would see a system generated message and the WinBatch process would be terminate by the system.   However, since you are receiving a WinBatch error you can use WinBatch error handling to trap the error and retry the file without human intervention.  Depending on the root cause of the problem, this approach may provide you with a workaround that does not require an extender update (note that there is no guarantee that your problem can be fixed by an extender update.)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

Thank you for the suggestion. I had considered using ErrorMode and Last Error, but the documentation says that that would only works with minor errors, which the documentation says in the low-thousands range. Fatal errors are in the 3000 range, but I am getting an 8004 error. Wouldn't that constitute a fatal error that in this case that ErrorMode/LastError can't handle?

I will insert the error-trapping in the code anyway, and try it for awhile to see what happens.

Also, in the future (until you shut down, that is), I will refrain from using the term "crash", and instead be more precise in my descriptions.

JTaylor

Take a look at IntControl 72 and 73 for error handling.

Jim

td

Correct, the extender 8004 error is a level  3 error so ErrorMode will not trap it.  You need to use IntControl 73.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

I've looked at IC73, but I'm not sure if using it will cause me more problems. The Help leads me to believe that it will direct ANY error to a defined GoSub, or whatever branching I choose, which could cause problems later in the script, such as if a different event caused a different error. Is there a way to turn IC73 "on" and then "off" again, like you can with ErrorMode? In other words, instead of:

ErrorMode(@OFF) ; error trapping added because random 8004 errors are thrown when encountering a WB .DLL file
LastError()
zZipFiles(Options,FileName,FileToProcess,"")
ErrorMode(@CANCEL)
If LastError()==8004 then zZipFiles(Options,FileName,FileToProcess,"")
[Next line]
[Next Line]
[etc.]

maybe something like:

IntControl(73,2,0,0,0) ; with an "On" flag
zZipFiles(Options,FileName,FileToProcess,"")
IntControl(73,2,0,0,0) ; with an "Off" flag
[Next line]
[Next Line]
[etc.]
Exit

:WBErrorHandlerErrorMode
zZipFiles(Options,FileName,FileToProcess,"")
Return

snowsnowsnow

Sounds like you are looking for udsTry().

MrLeadFoot

udsTry()? Not sure what you mean by that.

td

First, I need to make a correction to may previous statement.  The zip extender 8004 is not a level three error. Only errors 8006 and 8007 are level three errors.  Closing in on our retirement and all that...   

Second, from the help file, "If you want the script to continue to handle errors, make sure to re-arm the error handler by calling IntControl 73 at the end of your error handling routine."  In other words, the error handle is disarmed after an error is handled.

Snow++'s udsTry() would work.  Do a search on this forum for an example.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

First, thanks for the clarification.

Second, if 8004 is a minor error, then my first example using ErrorMode/LastError should handle what ails me (this time) just fine, correct?

Third, I was talking about IC73 being a potential problem if the error did NOT raise it's ugly head. If that happens, then IC73 would be armed and waiting to intercept an error that likely would not be related to the zZipFiles function, and end up re-directing the script to the GoSub branch designed to accommodate for the 8004 error, which would not be appropriate for a different error. That's why I was hoping for an off switch for IC73. ;)

MrLeadFoot

BTW, before you guys disappear, is there somewhere that you can post those 8000 series errors, like you did with the 1000, 2000, and 3000 errors, so we have access to the 8000 error list as a resource, like we do now with the 1000-3000 series errors?

td

Quote from: MrLeadFoot on May 19, 2016, 02:20:55 PM
First, thanks for the clarification.

Second, if 8004 is a minor error, then my first example using ErrorMode/LastError should handle what ails me (this time) just fine, correct?

Third, I was talking about IC73 being a potential problem if the error did NOT raise it's ugly head. If that happens, then IC73 would be armed and waiting to intercept an error that likely would not be related to the zZipFiles function, and end up re-directing the script to the GoSub branch designed to accommodate for the 8004 error, which would not be appropriate for a different error. That's why I was hoping for an off switch for IC73. ;)

Second, IntControl 73 is the better option because it captures all errors and provides you with more info than ErrorMode.

Third, disarm it after the call to the function or call the function in a UDF.  Intcontrol 73 called in a UDF only affects the UDF.

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Quote from: MrLeadFoot on May 19, 2016, 02:29:23 PM
BTW, before you guys disappear, is there somewhere that you can post those 8000 series errors, like you did with the 1000, 2000, and 3000 errors, so we have access to the 8000 error list as a resource, like we do now with the 1000-3000 series errors?

Read the text displayed in the error message box.  IntControl 73 provides that text as well.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

But, the error does not specify whether it is minor, moderate, or fatal.

MrLeadFoot

Quote from: td on May 19, 2016, 02:32:55 PMThird, disarm it after the call to the function or call the function in a UDF.  Intcontrol 73 called in a UDF only affects the UDF.
How do you disarm it? Not using a UDF, if that matters.

td

Quote from: MrLeadFoot on May 19, 2016, 02:38:58 PM
But, the error does not specify whether it is minor, moderate, or fatal.

That isn't documented for most extender errors.  If you do the right thing and use IntControl 73 and you won't  have to worry about it.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

Quote from: MrLeadFoot on May 19, 2016, 02:41:45 PM
Quote from: td on May 19, 2016, 02:32:55 PMThird, disarm it after the call to the function or call the function in a UDF.  Intcontrol 73 called in a UDF only affects the UDF.
How do you disarm it? Not using a UDF, if that matters.
I THINK what this is saying, even though it specifies only UDF handling, is use "0" to disarm it?

"0 - (default) UDF error handling is canceled."

MrLeadFoot

Quote from: td on May 19, 2016, 02:45:02 PM
Quote from: MrLeadFoot on May 19, 2016, 02:38:58 PM
But, the error does not specify whether it is minor, moderate, or fatal.

That isn't documented for most extender errors.  If you do the right thing and use IntControl 73 and you won't  have to worry about it.
Forgive me for sounding dense, (I probably am), but in which variable does 73 place the error NUMBER?

td

Quote from: MrLeadFoot on May 19, 2016, 02:46:40 PM
"0 - (default) UDF error handling is canceled."

My help file states, "0 Normal error processing (default)" as one of the possible values for 'p1'.  It works for any of the other previously set IntControl 73 p1 values.  If you call the zZipFiles function from within a UDF with error handling,  error handling with not be in effect for the rest of your script.

Code (winbatch) Select
#DefineFunction ZipFile(Options, ZipFile, FileToZip)
   IntControl(73,1,0,0,0)
   zZipFiles(Options,ZipFile, FileToZip,"")
   return 0 ; Success
:WBErrorHandler
   return LastError() ; Failed
#EndFunction
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Quote from: MrLeadFoot on May 19, 2016, 02:51:19 PM
Forgive me for sounding dense, (I probably am), but in which variable does 73 place the error NUMBER?

That is what the LastError function is for.  See the above example.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on May 19, 2016, 02:13:14 PM
Snow++'s udsTry() would work.  Do a search on this forum for an example.

Actually, I tried searching for it, both here and in the Tech DB, and didn't find anything useful.  Maybe it has been so long since I posted an example using it, that it was before the forum switchover.

Anyway, here's the gist of it.  You want to be able to evaluate an expression and find out if it worked or not.  If it worked, you want, of course, to get whatever value the expression evaluates to.  If it failed, it should return some flag value that is distinct from any valid return value, and which will tell you that it failed.

Here is an example:

Code (winbatch) Select

; This is the function definition...
#DefineSubroutine udsTry(expr,errstr,cancelstr)
IntControl(73,1,1,0,0)
Return %expr%
:wberrorhandler
Return errstr
:cancel
Return cancelstr
#EndSubroutine

; Then, later on, in your code, you want to use the cPostButton() from the Control
; Manager extender, to push a button.  Problem is this may fail, for any number of
; possible reasons, but you want to keep trying it until it works.
; Note that cPostButton() returns 1 on success, so we know that a zero return means
; that it failed.
WHILE !udsTry(`cPostButton(cWndByID(cWndByID(someHandle,someID),anotherID))`,0,0)
    Display(60,TimeDate(),"Error in cPostButton()...Retry in 60 seconds")
ENDWHILE

td

Strange.  I found 3 instances  using 'udsTry' as the search term.  One of those instances being the post above.  But as I believe you have mentioned in the past,  the search functionality of this forum isn't the most robust.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

You're right.  For whatever reason, the first time I searched, I got exactly 3 hits, but they were all from this thread (the one titled "Zipper Bug").  That's why I said "nothing useful".

But now, I get 3 hits, as shown below:


WinBatch / Detecting the ACL problem
Ã,« by snowsnowsnow on February 09, 2016, 06:28:16 am Ã,»
...... ("WWWNT34I.DLL")  #DefineSubroutine udsTry(expr,errstr,cancelstr) IntControl(73, ............  = FileFullName(Param1) Terminate(!udsTry(`wntAccessMod("",Param1,300,2,0)`,0,0), ......

WinBatch / Re: Zipper Bug
Ã,« by td on Today at 06:41:20 am Ã,»
...... . I found 3 instances using 'udsTry' as the search term. One of those instances  ......

WinBatch Script Exchange / This is only a test...
Ã,« by snowsnowsnow on June 04, 2013, 08:07:53 am Ã,»

td

We will run some maintenance scripts on the forum's database when time permits.  That may (or may not) help some.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

MrLeadFoot

Quote from: td on May 19, 2016, 07:55:44 AM
However, since you are receiving a WinBatch error you can use WinBatch error handling to trap the error and retry the file without human intervention.  Depending on the root cause of the problem, this approach may provide you with a workaround that does not require an extender update (note that there is no guarantee that your problem can be fixed by an extender update.)
Just an update - it's been several days now since implementing some error handling, and the script has been working without a hitch. Thank you for the suggestion, I really appreciate it. :D

MrLeadFoot

Update, in case anyone cares:

Zipper bug reared its head again. Bummer.