Announcement

Collapse
No announcement yet.

Zip/Unzip Files

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

  • Zip/Unzip Files

    I went looking for some code that uses the XP/Win7 built-in ZIP API, but found only a few older references to using SHELL API to do the trick.

    Anyone have more recent experience on how to zip/unzip files within PowerBASIC?

    Or, did I perhaps simply not find the right thread?

    This was the older thread I found.
    Last edited by Gary Beene; 9 May 2012, 03:04 PM.

  • #2
    [...] but found only a few older references to using SHELL API to do the trick.
    Must be because that is what Windows uses.
    Forum: http://www.jose.it-berater.org/smfforum/index.php

    Comment


    • #3
      Hi Jose!

      You're so funny!

      Yes, I went off and tried the code at the link, and successfully created a zip file. Way cool!

      It ran in PBWin10, which I was a bit surprised at ... but I haven't used enough object code yet to know if there's some update/simplification possible since the code at the link was tested in PBWin9.

      The discussion thread suggested some timing issues also.

      But a really nice start.

      Comment


      • #4
        And, looking at the code a bit more, I see that it was for zipping an entire folder, not a single file or a list of files. The folder version is useful, but I'd also like to be able to provide a list of files and zip only those, then unzip those files without having to create a containing folder.

        More to learn ... always easier when you have something working to start with.

        Comment


        • #5
          For PB 10 you have to re-generate the interface declarations, since the old one uses STRING instead of WSTRING.
          Forum: http://www.jose.it-berater.org/smfforum/index.php

          Comment


          • #6
            For a single file, pass the name of the file in CopyHere.
            See: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
            Last edited by José Roca; 23 Sep 2012, 11:24 AM.
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #7
              The folder version is useful, but I'd also like to be able to provide a list of files and zip only those,
              If you can generate a list of 'files to be zipped', you can always create a temp directory, store your files there and zip 'em. When done zipping, delete the files and the temp directory.

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                ZLib isn't that difficult to use. I know that's not what you asked for, but you should take a look at it.
                Scott Slater
                Summit Computer Networks, Inc.
                www.summitcn.com

                Comment


                • #9
                  Gary, have you tried changing the code to copy a file instead of a whole folder? It is using the shell interface which is basically copying files to the zip folder so it will work with a single file or a whole folder. I use the following code which is similar to the code I posted and it can zip a single 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
                  I use it like this:
                  Code:
                  If CreateZipFile("C:\Path\MyData.mdb", "C:\Path\MyData.zip") Then
                  Last edited by William Burns; 9 May 2012, 10:21 PM.
                  "I haven't lost my mind... its backed up on tape... I think??" :D

                  Comment


                  • #10
                    Hi William
                    No, I haven't tried it that way. Thanks for the clarification and I'll go give your code above a try out!

                    Comment


                    • #11
                      Hey William,
                      First of all, of course, thanks for the code!

                      Then, I noticed that you used this:
                      Code:
                      sFile = ucode$(PATHNAME$(NAME, sFrom) & PATHNAME$(EXTN, sFrom))
                      Just wondering, why you didn't use the NAMEX key word?

                      But most importantly, the code fails in PBWin10. I had to remove the UCode$ and do this:
                      Code:
                      sFile = PathName$(Namex, sFrom)
                      Then it seems to work just fine.

                      It worked for you as is, in PBWIn10?

                      Comment


                      • #12
                        Interestingly, it failed in PBWin9 also - but pointed to the ENUM in the winshell.inc include file as the problem.

                        That took me back a moment, until I realized that the PBWin9 and PBWin10 COM Browsers generate the include equates differently.

                        The PBWin9 version does this for equates:
                        Code:
                        ' OfflineFolderStatus enumeration
                        %OfflineFolderStatus_OFS_INACTIVE = -1
                        %OfflineFolderStatus_OFS_ONLINE = 0
                        %OfflineFolderStatus_OFS_OFFLINE = 1
                        %OfflineFolderStatus_OFS_SERVERBACK = 2
                        %OfflineFolderStatus_OFS_DIRTYCACHE = 3
                        Whereas PBWin10 version does this:
                        Code:
                        Enum OfflineFolderStatus
                            OFS_INACTIVE = -1
                            OFS_ONLINE = 0
                            OFS_OFFLINE = 1
                            OFS_SERVERBACK = 2
                            OFS_DIRTYCACHE = 3
                        End Enum
                        So an include generated by the PBWin10 COM browser won't run in PBWin9 because ENUM was not available in PBWin9.

                        Comment


                        • #13
                          Originally posted by Gary Beene View Post
                          Hey William,
                          ...
                          It worked for you as is, in PBWIn10?
                          To be honest, even though I bought PBWin 10 a couple months after it was released, I have never switched to it because each time I attempted to port over my applications, I ran in to issues due to things like weird results on virtual listviews because of unicode support, or changes needed in the declares and other issues like that. I know many of the issues have fixes now if I was to spend some time searching the forum and I will probably get to a point I will attempt it again, but I don't have much time to invest in that at the moment and v9 is doing all I need right now anyway.
                          "I haven't lost my mind... its backed up on tape... I think??" :D

                          Comment


                          • #14
                            That's pretty much the same as my experience, William.

                            New Applications using CC6/Win10 and new Windows headers files? ==> no problems.

                            Trying to re-use routines carefully and lovingly crafted, tested and debuggged over many many years? ==> Go fish.
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              Hi William,
                              While using the folder version of your code, I wanted to know how many files were zipped, but could not find a property in winshell.inc to tell me. Do you know if there is such a thing?

                              I can read the number of files in the folder, but I don't think that would necessarily be the same as the number of files zipped.

                              and MCM/William,
                              ditto on the legacy code comment. Careful re-use is required. Legacy code can compile successfully, yet still not give the same results as with the previous compiler. I'm learning more each day on how to re-use my legacy code, but still don't have a step-by-step procedure in my head. But I'm getting there.

                              Comment


                              • #16
                                >ditto on the legacy code comment.

                                !!!

                                As you know from our exchanges over the past several weeks, my code is WAAAY more legacy than yours!

                                I might give you a single quote, but not a ditto.

                                !!!

                                MCM
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Hi MCM,
                                  Yes, I'll admit that you are more ancient/antiquated than I am ... errr ... I mean your PowerBASIC code is older than mine!

                                  Comment


                                  • #18
                                    Hi William,
                                    Thanks again for the code. I'm getting good use from it.

                                    I wanted to modify your code above to work on a list of files, not a single file nor all files in a folder. So I modified your code as I thought appropriate to handle an incoming list of files. Basically I put a loop around the assign source folder/assign targetfolder/copy file code. I marked the lines I changed (just 3 lines plus the For/Next loop).

                                    The code does some funny things:
                                    1. Sometimes it works (yippee!)
                                    2. If the target zip file exists, it is replaced with a zip file containing only the first file in the list.
                                    3. It sometimes fails with "File not found or no permission". I can't get this to happen on demand.

                                    So I've done something wrong. Would you mind taking a look at it to see if there's anything fundamentally wrong with what I did?

                                    It's not clear how the code knows to overwrite, or add, files to the zip file. As written, it seems to overwrite any preexisting zip file. That's what I wanted this time, but I can also see wanting to add a file to an existing zip file as well.

                                    Code:
                                    #Compile Exe
                                    #Dim All
                                    #Debug Error On
                                    #Debug Display On
                                    #Include "win32api.inc"
                                    #Include "winshell.inc"
                                    
                                    Function PBMain() As Long
                                       Dim fList(1) As String
                                       fList(0) = "c:\test\arguments.txt"                     '<--------- use your own  --------
                                       fList(1) = "c:\test\unicode.txt"                       '<--------- use your own  --------
                                    
                                       CreateZipFileFromList fList(), "c:\test\allfiles.zip"  '<--------- use your own  --------
                                    End Function
                                    
                                    '==================================================
                                    '  CreateZipFile - creates a zip file
                                    '==================================================
                                    Function CreateZipFileFromList(fList() 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
                                       Dim i                As Long          '-----------new---------------------------
                                    
                                       '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
                                    
                                    
                                    For i = 0 To UBound(fList)                  '-----------new----------------------
                                    
                                    
                                       'assign the source folder we want to zip up
                                       vSourceFolder = RTrim$(PathName$(Path, fList(i)),"\")    '--------modified------------
                                       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))
                                       sFile = PathName$(Namex, fList(i))                '-----------modified for PBWin10 -----
                                    
                                       '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
                                    
                                    Next i                                      '-----------new----------------------
                                    
                                       '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
                                    Finally, this line:
                                    Code:
                                       vOptions = 20
                                    What does the 20 mean and where did you find that out?

                                    Comment


                                    • #19
                                      >What does the 20 mean and where did you find that out?

                                      Code:
                                      #IF 0
                                      Optional. Specifies options FOR the COPY operation.
                                      THIS value can be zero OR a combination OF the following values.
                                      These values are based upon flags defined FOR use WITH the fFlags MEMBER OF the C++ SHFILEOPSTRUCT structure.
                                      These flags are NOT defined AS such FOR Microsoft® Visual Basic®, Visual Basic Scripting Edition (VBScript),
                                      OR Microsoft JScript®, so you must define them yourself OR use their NUMERIC equivalents
                                      
                                      4 DO NOT DISPLAY a progress DIALOG box.
                                      8 Give the file being operated ON a NEW NAME IN a move, COPY, OR rename operation IF a file WITH the target NAME already exists.
                                      16 Respond WITH "Yes to All" FOR ANY DIALOG BOX that IS displayed.
                                      64 PRESERVE undo information, IF possible.
                                      128 Perform the operation ON files ONLY IF a wildcard file NAME (*.*) IS specified.
                                      256 DISPLAY a progress DIALOG BOX but DO NOT SHOW the file names.
                                      512 DO NOT confirm the creation OF a NEW directory IF the operation requires one TO be created.
                                      1024 DO NOT DISPLAY a USER INTERFACE IF an ERROR occurs.
                                      2048 Version 4.71. DO NOT COPY the security attributes OF the file.
                                      4096 ONLY operate IN the LOCAL directory. Don't operate recursively into subdirectories.
                                      9182 Version 5.0. DO NOT COPY connected files AS a group. ONLY COPY the specified files.
                                      ' I think this is a typo in the SDK doc and should be '8192' not "9182"
                                      #ENDIF
                                      
                                      ENUM CopyHereOptions
                                          CHO_NOPROGRESS       =  4
                                          CHO_RENAMEONDUP      =  8
                                          CHO_YESTOALL         =  16
                                          CHO_PRESERVEUNDOINFO = 64
                                          CHO_ONLYIFWILDCARD   = 128
                                          CHO_NONAMESPROGRESS  = 256
                                          CHO_NOCONFIRMNEWDIR  = 512
                                          CHO_NOUIONERROR      = 1024
                                          CHO_NOCOPYSECURITY   = 2048
                                          CHO_NORECURSE        = 4096
                                          CHO_NOCOPYCONNECTED  = 8192   ' NOTE TYPO CORRECTED HERE 
                                      
                                      END ENUM
                                      MCM
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        Thanks, MCM,
                                        From your listing, I can see that the 20 is the combination of equates.

                                        But where did you get the quoted content from? I can't find any of the equates on MSDN.

                                        I might then guess you found it in the SDK docs somewhere? But when I search the Microsoft Windows SDK v7.1, I still don't find the information.

                                        Comment

                                        Working...
                                        X