Jump to content

ZIP UDF (zipfldr.dll library)


wraithdu
 Share

Recommended Posts

  • 3 weeks later...

#include <_Zip.au3>

$sZipFile = FileOpenDialog("Select archive", "", "Archives ZIP (*.zip)")
If @error Then Exit
; If StringRight($sZipFile, 4) <> '.zip' Then $sZipFile &= '.zip'
If StringRight($sZipFile, 4) <> '.zip1' Then $sZipFile &= '.zip2'

$sAddFile = FileOpenDialog("Select the file to add", "", "All the files (*.*)")
If @error Then Exit

$iRes = _Zip_AddItem($sZipFile, $sAddFile)
If @error Then
    MsgBox(64, "_Zip_AddItem", "@error = " & @error)
Else
    MsgBox(64, "_Zip_AddItem", "The file is added to the archive: " & $iRes)
EndIf

Line 134 (File "C:AutoIt3Include_Zip.au3"):

Until IsObj($oNS.ParseName($sNameOnly))

Until IsObj(^ ERROR

Error: Error in expression.

WinXP, AutoIt3 - 3.3.8.1

Link to comment
Share on other sites

_Zip_examples_En.7z

If the file does not exist, this causes a crash. The file extension does not change anything. I expect an error with number 7. Perhaps it is necessary to add FileExists.

_Zip_AddItem
@error = 7 - Destination ZIP file does not exist ???
@error = 7 - The file has no extension ZIP

_Zip_ItemExists

If Not IsObj($oNS) Then Return 0 ???
If Not IsObj($oNS) Then Return SetError(4, 0, 0)

_Zip_DeleteItem

Unable to remove. Where the line that deletes?

#include <_Zip.au3>

$sZipFile = FileOpenDialog("Select the archive", "", "ZIP Archives (*.zip)", 3)
If @error Then Exit

$iRes = _Zip_DeleteItem($sZipFile, 'file.txt')
If @error Then
    MsgBox(64, "_Zip_DeleteItem", "@error = " & @error) ; = 7
Else
    MsgBox(64, "_Zip_DeleteItem", "Delete? : " & $iRes)
EndIf
Edited by AZJIO
Link to comment
Share on other sites

New version in OP.

I fixed the missing @error return from the _Zip_ItemExists function, which in turn fixes the _Zip_AddItem @error return (and probably the crash).

The line that actually performs the interactive deletion is

$oVerb.DoIt()

I could see this not working if your OS language is not English, since it has to find the correct shell verb by name (string comparison). Any ideas to make that work for other languages?

Edited by wraithdu
Link to comment
Share on other sites

  • 4 months later...

Hi!

First off. Great UDF. However im having a small issue.

I have a program that i use to monitor alot of servers. Every night the program checks a specific place for a new version of the program. A kind of autoupdater. If there is a new version, it extracts a zip file to a temp folder and installs the new version.

The problem is that one of the serverns got stuck in the exctract prosess and never finsihed it (and thereby didnt restart my program). So I tried running the program manually (my program run as a service). and i got an error saying somthing about a problem with a "where statement" at line 264 (or somwhere near that). I checked my code and the first line of code in my program us 426 (i dont have any where statements). So my conclution is that the error uccured in the UDF somewhere.

The problem is that after ive tried running the program 4-5 times, it suddenly worked passed without issue. None of my other 22 servers have had this issue so far. It might be a one time-thing. But i dont like when my programs just stopp running in the middle of the night :P

I know that this is not enough information to do any kind of troubleshooting so im asking for assitance in identifiying the problem. Another problem is that i dont have the edtor on the server. Just the compiled EXE.

If it happens again i will pust the exact error message i got.

I only use: _Zip_UnzipAll to just unzip the files.

Link to comment
Share on other sites

Well that's particularly odd, since AutoIt has no Where clause anywhere in the language.

Also, that UnzipAll function does not have any loops or wait statements, so it cannot deadlock on its own. If something froze or locked up, then it might be part of your service code. AutoIt is not a good language for a service. It is not multithreaded and not thread safe (there's more to it, with reentrance as well, but I'm not a good person to try and explain it). Bottom line, AutoIt 'services' are destined to be unreliable.

Link to comment
Share on other sites

Well that's particularly odd, since AutoIt has no Where clause anywhere in the language.

Also, that UnzipAll function does not have any loops or wait statements, so it cannot deadlock on its own. If something froze or locked up, then it might be part of your service code. AutoIt is not a good language for a service. It is not multithreaded and not thread safe (there's more to it, with reentrance as well, but I'm not a good person to try and explain it). Bottom line, AutoIt 'services' are destined to be unreliable.

Im not 100% sure about the exact error message. I will get back to you when/if it happends again.

The "service" in this case is just the program running in the background and gets triggered by a service. The "service" is stoped right befor the update and the started again after the updates completes. The updater crashes when it tries to unzip the files. So there is nothing wrong with the "service" but the updater.

I know that didnt have mucth info about the problem, but i will get back when/if it happends again :)

Link to comment
Share on other sites

Alright. It happend again and the exact error message is:
Line 268 (path to exe file)
Error: Object refferenced outside a "with" statement.

This time it happend on a WIndows Server 2008. The other one was a Server 2008 R2.

Any idees?

Edited by Tjalve
Link to comment
Share on other sites

I tried to debug the function by adding several filewriteline. And it seems tkat it get stuck here:

FileWriteLine(@ScriptDir & "\zip.txt","start")
    If FileExists($sDestPath & "\" & $oNS.Items().Item($oNS.Items().Count - 1).Name) Then
        FileWriteLine(@ScriptDir & "\zip.txt","SUCCSESS")
        ; success... most likely
        ; checks for existence of last item from source in destination
        Return 1
    Else
        ; failure
        FileWriteLine(@ScriptDir & "\zip.txt","FAILD")
        Return SetError(7, 0, 0)
    EndIf

In the log file i find: start, but not SUCCESS nor FAILD. Any idees?

Link to comment
Share on other sites

No ideas at the moment. The extraction is done by the windows shell. Do you have a COM error handler installed as part of your program anywhere? If not, then replace the UDF's empty error handler with this, and see if it provides any more info.

Func _Zip_COMErrorFunc($oError)
    FileWriteLine(@ScriptDir & "\zip.txt", @ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_Zip_COMErrorFunc
Link to comment
Share on other sites

Hello again.

It seems that the problem is the INetGet function. It doesnt download the whole file, and i get stuck with a 140kb zip file (should be around 1mb) and when the program tries to unzip it, it crashes (the entire script crashes, no com error). So my apolgies. I will post a new thread with the issue instead.

Pehaps one could perfect the functions so it doesnt crash the script even if the zip is corupt?

Link to comment
Share on other sites

All of the operations are handled by COM, and I've included an empty COM error handler (the one I suggested you replace above for more info). That is the correct way to prevent a COM error from crashing the script. If that is still happening, then it could possibly be a bug in AutoIt or a bug in the zipfldr COM library.

If you can create a reproducible script, ie some short code and a corrupt zip file that will cause the crash, then we can begin looking at it.

Link to comment
Share on other sites

Hi,

First thanks all for all your fine and usefull posts, UDF's and all stuff I'm learning from you guys.

In the Zip UDF I ran into a strange error. If I have in my Windows Explorer the option "Hide known file extensions" turned on, so I see "Logo" instead of "Logo.png" the "unzipall" method does not work. Turning the "hide known extension" feature off will start working the Unzipall method again. I looked into it and it seems that the extension will also be missing in the line:

$sDestPath & "" & $oNS.Items().Item($oNS.Items().Count - 1).Name.

So I looked how to adjust it and I changed the function into the code below. Sorry, English is not my native language ...

Func _Zip_UnzipAll($sZipFile, $sDestPath, $iFlag = 20)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Or Not _IsFullPath($sDestPath) Then Return SetError(3, 0, 0)
    ; get temp dir created by Windows
    Local $sTempDir = _Zip_TempDirName($sZipFile)
    Local $oNS = _Zip_GetNameSpace($sZipFile)
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    $sDestPath = _Zip_PathStripSlash($sDestPath)
    If Not FileExists($sDestPath) Then
        DirCreate($sDestPath)
        If @error Then Return SetError(5, 0, 0)
    EndIf
    Local $oNS2 = _Zip_GetNameSpace($sDestPath)
    If Not IsObj($oNS2) Then Return SetError(6, 0, 0)
    $oNS2.CopyHere($oNS.Items(), $iFlag)
    ; remove temp dir created by WIndows
    DirRemove($sTempDir, 1)

;In case of suppression of known extensions in explorer, the extension is also missing in the original file, workaround found with _PathSplit
    Local $Drive,$Dir,$FileName,$Extension
    _PathSplit($oNS.Items().Item($oNS.Items().Count - 1).Path,$Drive,$Dir,$FileName,$Extension)

;If FileExists($sDestPath & "\" & $oNS.Items().Item($oNS.Items().Count - 1).Name) Then
    If FileExists($sDestPath & "\" & $FileName &  $Extension) Then
        ; success... most likely
        ; checks for existence of last item from source in destination
        Return 1
    Else
        ; failure
        Return SetError(7, 0, 0)
    EndIf
EndFunc   ;==>_Zip_UnzipAll
Edited by prutser
Link to comment
Share on other sites

  • 2 weeks later...
  • 1 month later...

thanks for the awesome udf wraithdu!

i am having trouble trying to get rid of the progress box.  it looks like by default its supposed to suppress the box but i dont think it does. and if i add the flags to do so, it still doesnt work.  maybe its more visible because im doing a large directory?

thanks in advance

Edited by gcue
Link to comment
Share on other sites

  • 2 weeks later...

Hi. Im having some issues with the _zip_unzipall function.

I have aprogram that runs as a service. This program spawns a script that downloads a zip file from the internet and then extracts the files and then restarts the service.

The problem is that sometimes the _zip_unzipall function seams to crash, witch makes the updater crash and the services never restarts.

Another problem is that i get Error code 7 (extract failed) even if the extract seems to work anyway.

Since the program that runs the file is a service, i dont get any error messages. So i inserted a few filewriteline in the _zip_unzipall function. Just to see how long it befor crashing. This is the output from the run that crashed:

Starting _Zip_DllChk
Starting _IsFullPath
Starting _Zip_TempDirName: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Starting _Zip_GetNameSpace: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Done _Zip_GetNameSpace: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Starting _Zip_PathStripSlash: C:Program Files (x86)stuff
Starting _Zip_GetNameSpace: C:Program Files (x86)stuff
 
This is the same from a run when its working:
Starting _Zip_DllChk
Starting _IsFullPath
Starting _Zip_TempDirName: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Starting _Zip_GetNameSpace: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Done _Zip_GetNameSpace: C:Program Files (x86)stuffupdates0.3.2.0stuff.zip
Starting _Zip_PathStripSlash: C:Program Files (x86)stuff
Starting _Zip_GetNameSpace: C:Program Files (x86)stuff
Tar bort Tempmapp: C:UsersQV_SER~1AppDataLocalTempTemporary Directory 1 for stuff.zip
Resultat: ERROR

 

This is the code in the UDF
 

Func _Zip_UnzipAll($sZipFile, $sDestPath, $iFlag = 20)
    global $logfile = FileOpen(@UserProfileDir & "\unzip.log",2)
    FileWriteLine($logfile,@YEAR & @MON & @MDAY & " - " & @HOUR & @MIN)
    FileWriteLine($logfile,"Starting _Zip_DllChk")
    If Not _Zip_DllChk() Then
        FileClose($logfile)
        Return SetError(@error, 0, 0)
    EndIf
    FileWriteLine($logfile,"Starting _IsFullPath")
    If Not _IsFullPath($sZipFile) Or Not _IsFullPath($sDestPath) Then
        FileClose($logfile)
        Return SetError(3, 0, 0)
    EndIf
    ; get temp dir created by Windows
    FileWriteLine($logfile,"Starting _Zip_TempDirName: " & $sZipFile)
    Local $sTempDir = _Zip_TempDirName($sZipFile)
    FileWriteLine($logfile,"Starting _Zip_GetNameSpace: " & $sZipFile)
    Local $oNS = _Zip_GetNameSpace($sZipFile)
    FileWriteLine($logfile,"Done _Zip_GetNameSpace: " & $sZipFile)
    If Not IsObj($oNS) Then
        FileClose($logfile)
        Return SetError(4, 0, 0)
    EndIf
    FileWriteLine($logfile,"Starting _Zip_PathStripSlash: " & $sDestPath)
    $sDestPath = _Zip_PathStripSlash($sDestPath)
    If Not FileExists($sDestPath) Then
        DirCreate($sDestPath)
        If @error Then
            FileClose($logfile)
            Return SetError(5, 0, 0)
        EndIf
    EndIf
    FileWriteLine($logfile,"Starting _Zip_GetNameSpace: " & $sDestPath)
    Local $oNS2 = _Zip_GetNameSpace($sDestPath)
    If Not IsObj($oNS2) Then
        FileClose($logfile)
        Return SetError(6, 0, 0)
    EndIf
    $oNS2.CopyHere($oNS.Items(), $iFlag)
    FileWriteLine($logfile,"Tar bort Tempmapp: " & $sTempDir)
    ; remove temp dir created by WIndows
    DirRemove($sTempDir, 1)
    If FileExists($sDestPath & "\" & $oNS.Items().Item($oNS.Items().Count - 1).Name) Then
        ; success... most likely
        ; checks for existence of last item from source in destination
        FileWriteLine($logfile,"Resultat: OK")
        FileClose($logfile)
        Return 1
    Else
        ; failure
        FileWriteLine($logfile,"Resultat: ERROR")
        FileClose($logfile)
        Return SetError(7, 0, 0)
    EndIf
EndFunc   ;==>_Zip_UnzipAll
Link to comment
Share on other sites

It seems the crash happens in the .CopyHere method. Did you add a more verbose COM error handler like I suggested above?

For the error return, it tries to determine if it succeeded by checking the existence of the last item of the archive in the destination folder. Can you manually confirm this item exists in the error condition? Maybe add some debug output using

$sDestPath & "" & $oNS.Items().Item($oNS.Items().Count - 1).Name

to see what it is checking for and if it exists.

Link to comment
Share on other sites

I have now done som more reaserch, And it seems to work if im logged on tp the machice. If om not, it will say error of 2 (liberary nor found).

So the service that spawns this script cannot find the library. But it doesnt happen on every server... 

I also tried the COM error handler, buit it fails bacuase i already had a COM error handler for another one aperently?

I have now checked all my three servers that have this problem. And all of them fail with @error  = 2.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...