Announcement

Collapse
No announcement yet.

Zip/Unzip Files

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bernhard Fomm
    replied
    Is there an SLL for zipping in 2017?
    The SLL must be compatible with Windows 7,8,10 and may cost something.

    Leave a comment:


  • Michael Mattias
    replied
    Can someone help and do the trick and replace "SLEEP" with "WaitForSingleObject" in the example or is there another solution?
    PB SLEEP and WinAPI WaitForSingleObject() do different things. You cannot "replace" either with the other. (Which would certainly make it a 'trick' !)

    Sometimes you see both here and in the PB help "SLEEP" being used at the start of additional threads of execution. SLEEP as used in these cases can be considered a "cheap and dirty" way to accomplish "waiting for initialization" but the better (IMO) way to do that is to use a Windows event and suspend the calling thread using WFSO until the thread function has explicitly signaled initialization is complete.

    There really are two ways to hold execution pending "something" being completed in another thread of execution (which can include threads owned by another process):

    Method One can be expressed in pseudo-code thus:

    Code:
         DO
            Check something to see if "other thing is done"
                This can be testing a global variable or maybe a disk file
            IF Thing IS DONE
                 EXIT DO
           ELSE      ' it's NOT done yet
                 delay and retry later... typically using SLEEP
                 SLEEP some anpount of number
           END IF
        LOOP
         '  Program resumes knowing "thing is done."
    Method Two is the one I suggest; it's a little simpler in pseudo-code AND more efficiently uses system resources: .
    :
    Code:
    ' do things here
     'Wait until "other thing is done"
    
    iret =  WaitForSingleObject (handle_to_event, timeout_period)
    
    ' program resumes knowing "thing is done."
    A whole bunch of my demos in the source code forum show 'Method Two' in action.


    MCM

    Leave a comment:


  • Freddy Fauler
    replied
    Hi Mikael,

    this solution helps. Thank you.

    Regards
    Freddy

    Leave a comment:


  • Bob Carver
    replied
    Originally posted by Mikael T View Post
    It would be nice to know if anybody has figured out how to use JOIN, as suggested.
    This is impossible. Nobody, not even Microsoft, can currently wait on the compression thread to exit.

    See below for where MS's code creates the thread (this is from current Win10, but this part of the code hasn't changed since XP). If you check up on SHCreateThread on MSDN, you'll see it returns neither the thread handle nor its id, which means threre's no easy way for anybody to wait for it. This is fine for explorer since that's generally always running, but anybody else has to has to hack around it and use some other metric to determine when its finished.
    (Sorry for the big picture, sizes other than fullsize don't seem to work). I seem to remember, though its been years since I looked, the low level interfaces (IStream, IStorage) would compress as they went file-by-file rather than all at once, but up to Win7 had a bug where they tried to open a non-existant temp file and so always failed.
    Non logged in people can find the picture here
    Attached Files
    Last edited by Bob Carver; 15 Apr 2017, 02:45 PM.

    Leave a comment:


  • Mikael T
    replied
    Hi Freddy,

    I used the code Gary Beene had modified in post #18 on page 1.
    The only thing I did was to add a check after each CopyHere so that it was done before it started to copy the next file.


    Code:
    ----- 'From William Burns and Gary Beene on page 1. -----
    
    'now we start the copy in to the new zip file
    vOptions = 20
    oTargetFolder.CopyHere(oItem, vOptions)
    
    IF ERR THEN
       MSGBOX "Got an Error during the CopyHere method. Error:" & STR$(ERR)
       GOTO TerminateZip
    END IF
    
    
    '----- This is the part I added, it waits until the requested file is copied. -----
    
    DO UNTIL oTargetFolder.Items.Count > FileCount        'FileCount starts at 0.
       SLEEP 100
    LOOP
    I also removed the Line with "Sleep 6000", it is not needed any more.

    It would be nice to know if anybody has figured out how to use JOIN, as suggested.

    Leave a comment:


  • Freddy Fauler
    replied
    Hi, I'm a hobby programmer.

    Can someone help and do the trick and replace "SLEEP" with "WaitForSingleObject" in the example or is there another solution?

    Leave a comment:


  • Jim Dunn
    replied
    So then the JOIN can't help us... : (

    Leave a comment:


  • William Burns
    replied
    Adjusting the sleep based on file size is a good idea. Of course HD speed and CPU etc play in to it too. But that is still much better than the static sleep I used.

    Leave a comment:


  • Andrea Mariani
    replied
    Yes, I too resorted the easy way:
    I grab the lenght of the file and sleep 1 second per MB.

    Code:
        IF doZip THEN
            DestFile = DIR$ (FilePathStr + destfile TO Udt)
            DIR$ CLOSE
            IF LEN(DestFile) THEN
                incsize = MAK(QUAD, Udt.FileSizeLow , Udt.FileSizeHigh)
                IF CreateZipFile( FilePathStr + destfile, FilePathStr + zipfile ) THEN
                    KILL FilePathStr + destfile
                END IF
            END IF
        END IF
    ...
    SLEEP incsize /1024

    Leave a comment:


  • William Burns
    replied
    Andrea, if you get the wait methods to work that Bob and others have suggested, please let me know how you did it. Because when I was creating the code, I tried but it appears that the "thread" that you need to wait for is launched by the shell folder system and I could not find an easy way to find the thread handle except enumerating every thread to search for it. That is why I resorted to using the sleep method.

    Leave a comment:


  • Jim Dunn
    replied
    (moved)
    Last edited by Jim Dunn; 24 Sep 2012, 04:31 PM. Reason: Discussion at http://www.powerbasic.com/support/pbforums/showthread.php?t=51433

    Leave a comment:


  • Jim Dunn
    replied
    Originally posted by Bob Zale View Post
    You have one... Just review the docs:

    METHOD JOIN(ThreadObjectVar AS InterfaceName, TimeOutVal AS Long) <7>

    Waits for the thread referenced by ThreadObjectVar to complete before execution of this thread continues. TimeOutVal specifies the maximum length of time to wait, in MilliSeconds. If TimeOutVal is zero (0), the time to wait is infinite.

    Regards,
    Bob Zale
    Ah, but figuring out "ThreadObjectVar" from
    Code:
    oTargetFolder.CopyHere(oItem, vOptions)
    Please throw us a bone??

    Leave a comment:


  • Bob Zale
    replied
    PowerBASIC 10.0 for Windows has a lot of great new features (like JOIN), and it does not require Win7. It is fully compatible with all 32-bit and 64-bit versions of Windows. Win95 through Win7.

    Best regards,

    Bob Zale

    Leave a comment:


  • Andrea Mariani
    replied
    Wrong quote - delete
    Last edited by Andrea Mariani; 23 Sep 2012, 06:10 PM.

    Leave a comment:


  • Michael Boho
    replied
    Bob,
    You beat me to the punch!
    I was going to recommend:

    CreateProcessA
    WaitForSingleObject
    GetExitCodeProcess
    CloseHandle(hThread)
    CloseHandle(hProcess)


    Not needed with your suggestion.

    Leave a comment:


  • Bob Zale
    replied
    Originally posted by Jim Dunn View Post
    Yeah, we need a "wait for process to end" function... : (
    You have one... Just review the docs:


    METHOD JOIN(ThreadObjectVar AS InterfaceName, TimeOutVal AS Long) <7>

    Waits for the thread referenced by ThreadObjectVar to complete before execution of this thread continues. TimeOutVal specifies the maximum length of time to wait, in MilliSeconds. If TimeOutVal is zero (0), the time to wait is infinite.

    Regards,

    Bob Zale

    Leave a comment:


  • Jim Dunn
    replied
    Yeah, we need a "wait for process to end" function... : (

    Leave a comment:


  • Andrea Mariani
    replied
    Now I am confused....

    Without the SLEEP, it does not work.

    With the SLEEP, it does.

    Sleep 10, it does not work.
    Sleep 20, it does.

    The program generates a 1MB text file, whick I ZIP end exit the program - but if it starts a new thread, the new thread should continue, even if the parent thread terminates, no?

    Leave a comment:


  • Andrea Mariani
    replied
    Thank you John Dunn,

    Thanks to you I discovered the error:
    Code:
    sFile = PATHNAME$(NAMEX, fList(i))                '-----------modified for PBWin10 -----
    Need to be:
    Code:
    sFile = UCODE$(PATHNAME$(NAMEX, fList(i)))                '-----------modified for PBWin10 -----

    Leave a comment:


  • Jim Dunn
    replied
    I found this sample code by William Burns in my "Windows ZIP" folder... is supposed to zip just 1 file:

    Code:
    '==================================================
    '  CreateZipFile - creates a zip file
    '==================================================
    Function CreateZipFile(byval sFrom as string, byval sTo as string) as long
       local hFile          as dword
       'Object Variables
       DIM oShellClass      AS IShellDispatch
       DIM oSourceFolder    AS Folder
       DIM oTargetFolder    AS Folder
       DIM oItem            AS FolderItem
       'variants
       DIM vSourceFolder    AS VARIANT
       DIM vTargetFolder    AS VARIANT
       DIM vOptions         AS VARIANT
       DIM vFile            AS VARIANT
       dim sFile            as string
    
       'First we create a empty ZIP file using a standard zip file header
       try
          hFile = freefile
          open sTo for output as #hFile
          print #hFile, Chr$(80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
          close #hFile
       catch
          ? "Error creating Zip file: " & sTo & "  Error:" & Error$(err)
          exit function
       end try
    
    
       ' Get an instance of our Windows Shell
       oShellClass = ANYCOM $PROGID_SHELL32_SHELL
    
       ' Did we get the object? If not, terminate this app
       IF ISFALSE ISOBJECT(oShellClass) OR ERR THEN
          ? "Could not get the Windows Shell object.  Error:" & str$(err)
          EXIT FUNCTION
       END IF
    
    
       'assign the source folder we want to zip up
       vSourceFolder = rtrim$(PATHNAME$(PATH, sFrom),"\")
       oSourceFolder = oShellClass.NameSpace(vSourceFolder)
    
       IF ISFALSE ISOBJECT(oSourceFolder) OR ERR THEN
          ? "Could not get the Source folder object.  Error:" & str$(err)
          goto TerminateZip
       END IF
    
    
       'assign the target folder we want to create (in this case it is a zip file)
       vTargetFolder = sTo
       oTargetFolder = oShellClass.NameSpace(vTargetFolder)
    
       IF ISFALSE ISOBJECT(oTargetFolder) OR ERR THEN
          ? "Could not get the Target folder object.  " & sTo & " Error:" & str$(err)
          goto TerminateZip
       END IF
    
    
       'get the file name we are copying
       sFile = ucode$(PATHNAME$(NAME, sFrom) & PATHNAME$(EXTN, sFrom))
    
       'assign the file item
       oItem = oSourceFolder.ParseName(sFile)
    
       IF ISFALSE ISOBJECT(oItem) THEN
          ? "Could not get the Item object. " & sFile & " Error:" & str$(err)
          goto TerminateZip
       END IF
    
       'now we start the copy in to the new zip file
       vOptions = 20
       oTargetFolder.CopyHere(oItem, vOptions)
    
       IF ERR THEN
          ? "Got an Error during the CopyHere method.  Error:" & str$(err)
          goto TerminateZip
       END IF
    
       'NOTE:  the above copyhere method starts a seperate thread to do the copy
       'so the command could return before the copy is finished, so we need to
       'allow time to complete.   Thus the next Sleep command.
       sleep 6000   'increase for larger folders
    
       '? sTo + " was successfully created."
       function = %TRUE
    
       TerminateZip:
    
       ' Close all of the Interfaces
    	vFile					= EMPTY
       vSourceFolder     = EMPTY
       vTargetFolder     = EMPTY
       vOptions          = EMPTY
       oItem             = NOTHING
       oTargetFolder     = NOTHING
       oSourceFolder     = NOTHING
       oShellClass       = NOTHING
    end function
    
    function pbmain
    	If CreateZipFile("C:\Path\MyData.mdb", "C:\Path\MyData.zip") Then
    end function

    Leave a comment:

Working...
X