List Files in a CAB File in VB.NET

dynamic_sysop

Senior Contributor
Joined
Oct 1, 2002
Messages
1,039
Location
Ashby, Leicestershire.
Hi folks, long time since i done this
frown.gif

anyway i've knocked together a little example that allows you to list the files in a .CAB file ( it can be built upon to allow extraction etc... )
the class to read the cab ...
Visual Basic:
'/// at very top of Class / Form...
Imports System.Runtime.InteropServices
 
Public Class CAB
#Region "API / DELEGATES"
	<StructLayout(LayoutKind.Sequential)> _
	Public Structure FILE_IN_CABINET_INFO
		Public NameInCabinet As IntPtr
		Public FileSize As Int32
		Public Win32Error As Int32
		Public DosDate As Int16
		Public DosTime As Int16
		Public DosAttribs As Int16
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
		Public FullTargetName As String
	End Structure
	Public Delegate Function PSP_FILE_CALLBACK_A(ByVal Context As Int32, ByVal Notification As Int32, ByVal Param1 As IntPtr, ByVal Param2 As IntPtr) As Int32
	Private Declare Function SetupIterateCabinet Lib "setupapi.dll" Alias "SetupIterateCabinetA" (ByVal CabinetFile As String, ByVal Reserved As Int32, ByVal MsgHandler As PSP_FILE_CALLBACK_A, ByVal Context As Int32) As Int32
	Private Declare Function DosDateTimeToFileTime Lib "kernel32.dll" (ByVal wFatDate As Int16, ByVal wFatTime As Int16, ByRef lpFileTime As FILETIME) As Int32
	<StructLayout(LayoutKind.Sequential)> _
	Private Structure FILETIME
		'/// should be a Low & High part ( 2 x Int32 ) but 1 x Int64 works perfect with Date.FromFileTime
		Public dwLowDateTime As Int64
	End Structure
	Private Const SPFILENOTIFY_CABINETINFO As Int32 = &H10
	Private Const SPFILENOTIFY_FILEEXTRACTED As Int32 = &H13
	Private Const SPFILENOTIFY_FILEINCABINET As Int32 = &H11
	Private Const SPFILENOTIFY_NEEDNEWCABINET As Int32 = &H12
	Private Const FILEOP_SKIP As Int32 = 2
#End Region
	'/// HERE i open a CAB file to read it's contents...
	Public Sub New(ByVal cabpath As String)
		Dim cb As New PSP_FILE_CALLBACK_A(AddressOf PSP_FILE_CALLBACK)
		SetupIterateCabinet(cabpath, 0, cb, 0)
	End Sub
	Private Function PSP_FILE_CALLBACK(ByVal Context As Int32, ByVal Notification As Int32, ByVal Param1 As IntPtr, ByVal Param2 As IntPtr) As Int32
		'/// from msdn's C++ description @ [url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/setupapi/setup/psp_file_callback.asp"]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/setupapi/setup/psp_file_callback.asp[/url]
		'/// my interpretation...
		Dim FILEINCABINET As Int32 = 0
		Select Case Notification
			Case SPFILENOTIFY_FILEINCABINET
				'/// we've found a file in the CAB [img]http://www.xtremedotnettalk.com/x_images/images/smilies/smile.gif[/img]
				FILEINCABINET = PSP_FILEFOUND_CALLBACK(Context, Notification, Param1, Param2)
				'/// here we can also extract the files from the CAB.
				'/// but we'll call PSP_FILEFOUND_CALLBACK for now.
		End Select
		Return FILEINCABINET
	End Function
	Private Function PSP_FILEFOUND_CALLBACK(ByVal Context As Int32, ByVal Notification As Int32, ByVal Param1 As IntPtr, ByVal Param2 As IntPtr) As Int32
		Dim FILEFOUND As Int32
		Select Case Context
			Case 0
				Dim f_in_cab As FILE_IN_CABINET_INFO = DirectCast(Marshal.PtrToStructure(Param1, GetType(FILE_IN_CABINET_INFO)), FILE_IN_CABINET_INFO)
				Dim frm As Form1 = DirectCast(Form.ActiveForm, Form1)
				'/// convert the IntPtr value of the filename to a readable string & add to a ListView...
				Dim lvi As New ListViewItem(Marshal.PtrToStringAnsi(f_in_cab.NameInCabinet))
				'/// the FILETIME should be 2 Int32's, but to get the resulting long value required i made it one Int64 [img]http://www.xtremedotnettalk.com/x_images/images/smilies/smile.gif[/img]
				Dim ft As FILETIME
				DosDateTimeToFileTime(f_in_cab.DosDate, f_in_cab.DosTime, ft)
				Dim d As Date = Date.FromFileTime(ft.dwLowDateTime)
				lvi.SubItems.Add(New ListViewItem.ListViewSubItem(lvi, d.ToLongDateString & " " & d.ToLongTimeString))
				frm.ListView1.Items.Add(lvi)
				FILEFOUND = FILEOP_SKIP
		End Select
		'/// must Return FILEFOUND to continue enumerating the files in the cab.
		Return FILEFOUND
	End Function
End Class
the way to use it, from a Form ...
Visual Basic:
	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
		Dim OD As New OpenFileDialog
		With OD
			.Filter = "CAB files|*.CAB"
			.RestoreDirectory = True
		End With
		If OD.ShowDialog = DialogResult.OK Then
			ListView1.Columns(0).Text = OD.FileName
			Dim cabinet As New CAB(OD.FileName)
		End If
	End Sub
i've included a zipped example source code
smile.gif
 

Attachments

Last edited by a moderator:
Back
Top