Extract cab files from MSI file.

With this script you can extract cab files that are embedded in a MSI file. The cab files are written to the start directory of the script. The MSI File name is an argument on the command line. To start the script type:

cscript extrcab.vbs orca.msi
'******************************************************************************
'** Script:    ExtrCab.vbs
'** Version:   1.0
'** Created:   30/01/2009 10:55AM
'** Author:    Adriaan Westra
'** E-mail:         
'**
'** Purpose / Comments:
'**            Extract cabinet files from MSI file.
'**
'**
'**
'** Changelog :
'** date / time         : 
'** 30/01/2009 10:55AM  :   Initial version
'**
'******************************************************************************

'*****************************************************************
'** Add Error Handling
on error resume Next

'*****************************************************************
'** Make sure the script is started with cscript
If InStr(wscript.FullName, "wscript.exe") > 0 Then
MsgBox "Please run this script with cscript.exe." & Chr(13) & _
"For example : cscript " & WScript.ScriptName & " /?", _ 
vbExclamation, WScript.ScriptName
WScript.Quit(1)
End If

'*****************************************************************
'** Get commandline parameters
Set Args = Wscript.Arguments

If Args.Count = 0 Then
	strMsiFile = InputBox("Please give the MSI File name " & _
	"to process : ",wscript.scriptname, strPath)
Else
   If InStr(Args(0),"/?") > 0 Or InStr(UCase(Args(0)),"/H") > 0 _ 
   Or InStr(UCase(Args(0)),"/HELP") > 0 Then
      DisplayHelp
      Wscript.quit(0)
   Else
      strMsiFile = Args(0)
   End if
End if



Const msiOpenDatabaseModeReadOnly = 0 
Const msiOpenDatabaseModeTransact = 1
Const msiOpenDatabaseModeListScript = 5
Const msiReadStreamAnsi = 2



Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objMSI = CreateObject("WindowsInstaller.Installer")
Set objMsiDB = objMSI.OpenDataBase(strMsiFile, msiOpenDatabaseModeReadOnly ) : CheckError

Set objView =  objMsiDB.Openview("Select Cabinet From Media") : CheckError
objView.Execute : CheckError
Set objRecord = objView.Fetch
Do until objRecord is Nothing
   If InStr(objRecord.StringData(1) ,"#") = 1 Then
      strCabFile = Mid(objRecord.StringData(1),2, Len(objRecord.StringData(1)) - 1)
   Else
      Wscript.echo "No internal cab file in this MSI"
      wscript.quit(1)
   End If
   strSQL = "Select * From _Streams where Name = '" & strCabFile & "'"
   Set objViewCab =  objMsiDB.Openview(strSQL) : CheckError
   
   objViewCab.Execute : CheckError
   Set objRecordCab = objViewCab.Fetch
   If not objRecordCab is Nothing Then
      binData = objRecordCab.readstream(2, objRecordCab.datasize(2), msiReadStreamAnsi )
      If InStr(strCabFile,".cab") = 0 Then
         strCabFile = strCabFile & ".cab"
      End If
      Set objCabFile = objFSO.CreateTextFile(strCabFile, True)
      objCabFile.Write binData
      objCabFile.Close
       wscript.echo "Created : " &  strCabFile
   End If  
   Set objRecord = objView.Fetch 
Loop
      
Set objRecord = nothing
Set objMsiDB = nothing
Set objMsi = nothing


Wscript.Quit 0

Sub CheckError
  Dim message, errRec
  If Err = 0 Then Exit Sub
  message = Err.Source & " " & Hex(Err) & ": " & Err.Description
  If Not installer Is Nothing Then
  	Set errRec = installer.LastErrorRecord
  	If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
  End If
  Wscript.Echo message
  Wscript.Quit 2
End Sub