Jump to content
Xtreme .Net Talk

Recommended Posts

  • Leaders
Posted (edited)

Hi folks, long time since i done this http://www.xtremedotnettalk.com/x_images/images/smilies/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 ...

'/// 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]
			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]
			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 ...

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 http://www.xtremedotnettalk.com/x_images/images/smilies/smile.gif

CABFiles_in_NET.zip

Edited by PlausiblyDamp

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...