Seite 1 von 2

CAB-Dateien extrahieren (PB4)

Verfasst: 02.05.2006 16:15
von ts-soft

Code: Alles auswählen

Structure FILE_IN_CABINET_INFO
  NameInCabinet.l
  FileSize.l
  Win32Error.l
  DosDate.w
  DosTime.w
  DosAttribs.w
  FullTargetName.s{260}
EndStructure

Procedure PSP_FileCallback(Context.l, Notification.l, Param1.l, Param2.l)
  Protected *CAB_INFO.FILE_IN_CABINET_INFO
  Protected Path.s
  If Notification = $11
    *CAB_INFO = Param1
    Path = PeekS(Context)
    Path + PeekS(*CAB_INFO\NameInCabinet)
    MakeSureDirectoryPathExists_(GetPathPart(Path))
    *CAB_INFO\FullTargetName = Path
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure

Procedure CAB_Extract(ArchivName.s, ExtractPath.s)
  If Right(ExtractPath, 1) <> "\" : ExtractPath + "\" : EndIf
  ProcedureReturn SetupIterateCabinet_(@ArchivName, 0, @PSP_FileCallback(), @ExtractPath)
EndProcedure

ArchivName.s = "MyCab.cab" ; Achtung: absoluten Pfad angeben
ExtractPath.s = "C:\windows\temp"

If CAB_Extract(ArchivName, ExtractPath)
  Debug "Alles okay my Friend"
Else
  Debug "ERROR, das ist nicht gut"
EndIf
Vielleicht kanns der eine oder andere mal gebrauchen

Verfasst: 02.05.2006 23:57
von ABBKlaus
Hi TS-Soft,

habs gleich mal ausprobiert und deine Version verbessert :twisted:

Code: Alles auswählen

#SPFILENOTIFY_STARTCOPY=$11
#FILEOP_ABORT=0
#FILEOP_DOIT=1
#FILEOP_SKIP=2

Structure FILE_IN_CABINET_INFO 
  NameInCabinet.l 
  FileSize.l 
  Win32Error.l 
  DosDate.w 
  DosTime.w 
  DosAttribs.w 
  FullTargetName.s{260} 
EndStructure 

Procedure PSP_FileCallback(Context.l, Notification.l, Param1.l, Param2.l)
;http://msdn.microsoft.com/library/en-us/setupapi/setup/psp_file_callback.asp
  Protected *CAB_INFO.FILE_IN_CABINET_INFO 
  Protected Path.s 
  If Notification = #SPFILENOTIFY_STARTCOPY
  ;http://msdn.microsoft.com/library/en-us/setupapi/setup/spfilenotify_startcopy.asp
    *CAB_INFO = Param1 
    Path = PeekS(Context) 
    Path + PeekS(*CAB_INFO\NameInCabinet) 
    If MakeSureDirectoryPathExists_(GetPathPart(Path))
      Debug Path
      *CAB_INFO\FullTargetName = Path 
      ProcedureReturn #FILEOP_DOIT
    Else
      ProcedureReturn #FILEOP_SKIP
    EndIf
  EndIf 
  ProcedureReturn 0
EndProcedure 

Procedure CAB_Extract(ArchivName.s, ExtractPath.s) 
  If Right(ExtractPath, 1) <> "\" : ExtractPath + "\" : EndIf 
  ProcedureReturn SetupIterateCabinet_(@ArchivName, 0, @PSP_FileCallback(), @ExtractPath) 
EndProcedure 

ArchivName.s = "C:\Data1.cab" ; Achtung: absoluten Pfad angeben 
ExtractPath.s = "D:\Backup\in" 

If CAB_Extract(ArchivName, ExtractPath) 
  Debug "Alles okay my Friend" 
Else 
  Debug "ERROR, das ist nicht gut" 
EndIf

Verfasst: 03.05.2006 00:11
von ts-soft
ABBKlaus hat geschrieben:Hi TS-Soft,

habs gleich mal ausprobiert und deine Version verbessert :twisted:
Da haste aber was verkehrt verstanden :mrgreen:
#FILEOP_SKIP=2 dient dafür, z.B. eine Vorschau zu erstellen, ohne zu
entpacken. Hab ich absichtlich nicht implementiert, weil dann müßten noch
die Werte in eine Linklist übertragen werden, o. ä.

Wenn es so aufwendig sein soll, hätte ich gleich die Cabinet-API verwandt
und Packroutinen beigelegt :wink:

Verfasst: 03.05.2006 00:24
von ABBKlaus
wie gesagt hab nur deinen code verbessert weil
MakeSureDirectoryPathExists_(GetPathPart(Path))
liefert immerhin ein Ergebnis zurück (#True/#False) und das habe Ich umgesetzt wie es sich gehört.
Und das überspringen einer Datei ist immerhin keine schlechte Alternative wenn ein Verzeichnis nicht existiert also warum nicht <)
SPFILENOTIFY_STARTCOPY
The callback routine should return one of the following values.
FILEOP_ABORT Abort the queue commit process.
FILEOP_DOIT Perform the file copy operation.
FILEOP_SKIP Skip the current copy operation.

Verfasst: 03.05.2006 00:39
von ts-soft
Wenn das Verzeichnis nicht existiert oder schreibgeschützt ist, bricht die API
sowieso ab, aber schaden kann es nicht.

Man könnte jetzt den Context Parameter, der ja für Benutzerdefinierte
Sachen da ist, erweitern und die Adresse einer Structure übergeben, die
dann Parameter für Vorschau oder Extrahieren enthält, sowie die Adresse
einer Linkliste, die dann gefüllt wird, mit Pfaden, Dateinamen und Attributen.

So könnte man das CAB-Archiv durchsuchen, ohne zu entpacken.

Das wäre dann eine sinnvolle Erweiterung, zu der ich zu Faul war /:->

Das Beispiel ist auch mehr für Einsteiger gedacht.

Verfasst: 03.05.2006 00:57
von ABBKlaus
So hab mal ein wenig mit Google gesucht und ein MS-Beispiel gefunden /:->
PS : in meinem code war auch ein fehler :oops:
#SPFILENOTIFY_STARTCOPY <> $11

Code: Alles auswählen

#SPFILENOTIFY_FILEINCABINET  = $11
#SPFILENOTIFY_NEEDNEWCABINET = $12
#SPFILENOTIFY_FILEEXTRACTED  = $13

#FILEOP_ABORT = 0
#FILEOP_DOIT  = 1
#FILEOP_SKIP  = 2

Structure FILE_IN_CABINET_INFO 
  NameInCabinet.l 
  FileSize.l 
  Win32Error.l 
  DosDate.w 
  DosTime.w 
  DosAttribs.w 
  FullTargetName.s{260} 
EndStructure 

Structure FILEPATHS
  Target.l
  Source.l
  Win32Error.l
  Flags.l
EndStructure

Procedure PSP_FileCallback(Context.l, Notification.l, Param1.l, Param2.l)
;http://msdn.microsoft.com/library/en-us/setupapi/setup/psp_file_callback.asp
;Beispielcode : http://support.microsoft.com/kb/q189085/
  Protected *CAB_INFO.FILE_IN_CABINET_INFO 
  Protected *FILE_INFO.FILEPATHS
  Protected Path.s
  
  retval.l=#NO_ERROR
  
  Select Notification
    Case #SPFILENOTIFY_FILEINCABINET
      *CAB_INFO = Param1 
      Path = PeekS(Context) 
      Path + PeekS(*CAB_INFO\NameInCabinet) 
      If MakeSureDirectoryPathExists_(GetPathPart(Path))
        *CAB_INFO\FullTargetName = Path 
        retval = #FILEOP_DOIT
      Else
        retval = #FILEOP_SKIP
      EndIf
    Case #SPFILENOTIFY_FILEEXTRACTED
      *FILE_INFO = Param1
      Debug "Extracted "+PeekS(*FILE_INFO\Target)
      retval = #NO_ERROR
    Case #SPFILENOTIFY_NEEDNEWCABINET ; unexpected
      retval = #NO_ERROR
  EndSelect
  
  ProcedureReturn retval
EndProcedure 

Verfasst: 03.12.2006 11:29
von DROOPY
Hello, this code can be converted to pb 3.94 ?
Regards

Verfasst: 03.12.2006 20:02
von ts-soft
DROOPY hat geschrieben:Hello, this code can be converted to pb 3.94 ?
Regards
I think, there is no convert required :wink:

Verfasst: 03.12.2006 22:57
von DROOPY
I got an error in the structure line

Code: Alles auswählen

FullTargetName.s{260}
Replaced by

Code: Alles auswählen

FullTargetName.s
And the code doesn't works :cry:

Verfasst: 04.12.2006 00:07
von ts-soft
@Droopy:
Change the structure like this:

Code: Alles auswählen

  FullTargetName.b[260]
And something to:

Code: Alles auswählen

PokeS(*CAB_INFO\FullTargetName[0],Path)
Not tested