MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: SUBST Command[Next]: Unversioned files
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Tips and Tricks->File and Directory->Extract Binary at Install Time

Extract Binary at Install Time

The following shows how you could extract a binary file at install time. It shows a binary being added to the MSI "Binary" table as well as it being extracted during install into the "installation directory".

The binary needs to be in the msi and not in a transform that applies to the msi.

The following has been scheduled after the "CreateFolders" and "InstallFiles" actions and assumes that the directory exists. If not then you would either need to adjust the VBS or create the folder or install at least one file in the MSI.

Also if your resource is in a transform then you need to add code to apply the transform, you need to process the TRANSFORMS property.

;--- Add the binary ---------------------------------------------------------
<$Binary "D:\DBAREIS\tools\msgbox.exe" key="msgbox.exe">

;--- Create Custom Action to extract binary ---------------------------------
#data "Parameters"
      "DATABASE"     "[DATABASE]"      ;;We need to know the name of the database being installed
      "TRANSFORMS"   "[TRANSFORMS]"    ;;Tranforms can contain the binaries!
      "DestDir"      "[INSTALLDIR]"    ;;The destination directory
#data
<$VbsCa Binary="ExtractBinary.VBS" DATA="Parameters">
   ;--- Define constants ----------------------------------------------------
   const msiOpenDatabaseModeReadOnly = 0
   const msiReadStreamAnsi           = 2        ;;msiReadStreamBytes fails - ON SOME BYTES ONLY!

   ;--- INSTALL -------------------------------------------------------------
   <$VbsCaEntry "Install">
       ;--- Extra a binary --------------------------------------------------
       ExtractBinary "msgbox.exe", VbsCaCadGet("DestDir") & "msgbox.exe"
   <$/VbsCaEntry>


   <?NewLine>
   '=========================================================================
   sub ExtractBinary(BinaryKey, NewFileName)
   '=========================================================================
       CaDebug 1, "Extracting Binary """ & BinaryKey & """"
       CaDebug 2, "ExtractBinary(""" & BinaryKey & """, """ & NewFileName & """)"

       ;--- Open the database -----------------------------------------------
       on error resume next
       CaDebug 2, "Opening """ & NewFileName & """"
       dim DB  : DB      = VbsCaCadGet("DATABASE")
       dim oDB : set oDB = session.installer.OpenDatabase(DB, msiOpenDatabaseModeReadOnly)
       if  err.number <> 0 then
           on error goto 0
           VbsCaRaiseError "ExtractBinary()", "Tried to open the database """ & DB & """"
       end if
       CaDebug 2, "Successfully opened """ & NewFileName & """"

;**    [CommentBlockStart     (1 May 2008 18:16:27, Dennis)
;**+----------------------------------------------------------------------
;**|       ;--- Apply Transform to insert binaries! ----------------------------
;**|       CaDebug 2, "To access the binary we first need to apply transforms..."
;**|       dim TransformList : TransformList = VbsCaCadGet("TRANSFORMS")
;**|       dim Transform     : Transform     = TransformList             ;;Dodgy, I know I only have one transform I need to apply
;**|       oDB.ApplyTransform Transform, 0
;**|       if  err.number <> 0 then
;**|           on error goto 0
;**|           VbsCaRaiseError "ExtractBinary()", "Tried to open the apply the transform """ & Transform & """"
;**|       end if
;**|       CaDebug 2, "Successfully applied the transform """ & Transform & """"
;**+----------------------------------------------------------------------
;**    CommentBlockEnd]       (1 May 2008 18:16:27, Dennis)

       ;--- Look for the BINARY ---------------------------------------------
       CaDebug 2, "Looking for the binary """ & BinaryKey & """"
       dim oView, oRec
       Set oView = oDB.OpenView("SELECT `Data` FROM `Binary` WHERE `Name`='" & BinaryKey & "'")
       oView.Execute
       set oRec = oView.Fetch
       If oRec Is Nothing Then
           on error goto 0
           VbsCaRaiseError "ExtractBinary()", "Could not find the binary """ & BinaryKey & """"
       end if
       CaDebug 2, "Found the binary """ & BinaryKey & """"

       ;--- Extract the Binary ----------------------------------------------
       CaDebug 2, "Extracting the binary """ & BinaryKey & """"
       dim FileSize, FileContents
       FileSize     = oRec.DataSize(1)
       FileContents = oRec.ReadStream(1, FileSize, msiReadStreamAnsi)
       if  err.number <> 0 then
           on error goto 0
           VbsCaRaiseError "ExtractBinary()", "Tried to extract the binary """ & BinaryKey & """"
       end if
       set oRec  = Nothing
       set oView = Nothing
       CaDebug 2, "Extracted the binary """ & BinaryKey & """ (" & FileSize & " bytes)"

       ;--- Create the new binary file --------------------------------------
       CaDebug 2, "Creating the file """ & NewFileName & """"
       dim oFs, Stream
       set oFs    = CaMkObject("Scripting.FileSystemObject")
       set Stream = oFS.CreateTextFile(NewFileName, True)
       Stream.Write FileContents
       Stream.close
       if  err.number <> 0 then
           on error goto 0
           VbsCaRaiseError "ExtractBinary()", "Failed creating the file """ & NewFileName & """"
       end if
       CaDebug 2, "Successfully created the file """ & NewFileName & """"
       set Stream = Nothing
       set oFS    = Nothing

       ;--- Get a file hash (MD5) and log it --------------------------------
       CaDebug 2, "Calculating the files MD5 (for logging)"
       dim oMD5 : set oMD5 = session.installer.FileHash(NewFileName, 0)
       CaDebug 2, "The files MD5 is : " & PrettyHash(oMD5)
       set oMD5 = Nothing

       ;--- Finished --------------------------------------------------------
       CaDebug 1, "Binary """ & BinaryKey & """ extracted!"
   end sub


   <?NewLine>
   '=========================================================================
   function PrettyHash(ByVal UglyHash)    ;;Return MD5 string from MD5 record
   '=========================================================================
       PrettyHash = Hex8(UglyHash.IntegerData(1)) & "-" & Hex8(UglyHash.IntegerData(2)) & "-" & Hex8(UglyHash.IntegerData(3)) & "-" & Hex8(UglyHash.IntegerData(4))
   end function

   <?NewLine>
   '=========================================================================
   function Hex8(Value)                   ;;Returns 8 digit hex value
   '=========================================================================
       ;--- Create the hash as 8 digit hex (Bytes are reversed) ---------
       Hex8 = hex(Value)
       Hex8 = right(string(8, "0") & Hex8, 8)

       ;--- Correct the order of the 4 bytes ----------------------------
       Hex8 = mid(Hex8,7,2) & mid(Hex8,5,2) & mid(Hex8,3,2) & mid(Hex8,1,2)
   end function
<$/VbsCa>
<$VbsCaSetup Binary="ExtractBinary.VBS" Entry="Install" Seq="InstallFiles-" CONDITION=^<$CONDITION_INSTALL_ONLY>^ DATA="Parameters">


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: SUBST Command[Next]: Unversioned files


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Sunday February 28 2016 at 3:45pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.