Kae Travis

Delete Empty Components

Description:

This script will delete empty components from a Windows Installer.

Usage

CScript.exe {Script} {MSI}

Script

'set up log file
Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
'create a name/path for log file
Dim MSIPath : Set MSIPath = fso.GetFile(WScript.Arguments(0))  
Dim logFile : logFile = Left(MSIPath.Path, InStrRev(MSIPath.Path, ".") - 1) & ".log"
Dim objLogFile : Set objLogFile = fso.OpenTextFile(logFile, ForAppending, True)
WriteLog "Deleting Empty Components"
WriteLog "Processing: " & MSIPath.Name
'create 2 constants - one for when we want to just query the MSI (read) and one for when we want to make changes (write)
Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1
'create WindowsInstaller.Installer object
Dim oInstaller : Set oInstaller = CreateObject("WindowsInstaller.Installer")
'open the MSI (the first argument supplied to the vbscript)
Dim oDatabase : Set oDatabase = oInstaller.OpenDatabase(WScript.Arguments(0),msiOpenDatabaseModeTransact) 
Dim componentsView, componentsRec, tableView, tableRec, dataView, dataRec
Dim emptyComponent : emptyComponent = True
Dim tempComponent : tempComponent = ""
If oDatabase.TablePersistent("Component") = 1 Then
Set componentsView = oDatabase.OpenView("Select `Component` From `Component` ORDER BY `Component`")
componentsView.Execute
Set componentsRec = componentsView.Fetch
Do While Not componentsRec is Nothing
tempComponent = componentsRec.StringData(1)
emptyComponent = True
'list the tables that have 'Component_' (foreign key) columns
Set tableView = oDatabase.OpenView("SELECT `Table` FROM `_Columns` WHERE `Name`= 'Component_' AND `Table` <> 'FeatureComponents'") 
tableView.Execute
Set tableRec = tableView.Fetch
Do While Not tableRec is Nothing
Set dataView = oDatabase.OpenView("SELECT  `Component_` FROM `" & tableRec.StringData(1) & "`  WHERE `Component_`='" & tempComponent & "'")
dataView.Execute
If Not dataView.Fetch is Nothing Then 'this table has a some data belonging to some component
'component contains data
emptyComponent = False
'skip component and move to next
Exit Do
End If
Set tableRec = tableView.Fetch
Loop
If emptyComponent Then
'delete the empty component
oDatabase.OpenView("DELETE FROM `Component` WHERE `Component` = '" & tempComponent & "'").Execute
oDatabase.OpenView("DELETE FROM `FeatureComponents` WHERE `Component_` = '" & tempComponent & "'").Execute
WriteLog "Deleting empty component: " & tempComponent
End If
Set componentsRec = componentsView.Fetch
Loop
Set tableRec = Nothing
Set tableView = Nothing
Set componentsView = Nothing
Set componentsRec = Nothing
Set dataView = Nothing
End If	
oDatabase.Commit
objLogFile.Close
Set fso = Nothing
Set objLogFile = Nothing	
Set oDatabase = Nothing
Set oInstaller = Nothing
Sub WriteLog(LogMessage)
WScript.echo Now() & ": " & LogMessage
objLogFile.Writeline(Now() & ": " & LogMessage)
End Sub

 

Delete Empty Components
Delete Empty Components

12 thoughts on “Delete Empty Components

  1. Hi,

    i have tried using this script to remove empty component, but its not removing them, i am not getting any error it say just processing MSI.

    WriteLog “Deleting Empty Components”

    WriteLog “Processing: “ & MSIPath.Name

     

    i have updated the script with

    Dim Test : Set Test = dataView.Fetch ‘after line 51.

    Script is deleting some components with file along with empty components.

    Kindly Help.

    Many Thanks,

    Shashi

  2. If the MSI isn’t too big you can zip it and mail it to me. If it is big, strip out all the cabs/streams first…. Give me an example of a component that it is not removing.

  3. My Test MSI has some empty components i tried using the write log, the script is not going in to the below condition.

    If emptyComponent Then
    WriteLog ” component name: ” & tempComponent
    WriteLog “Deleting empty component: ” & tempComponent
    End If

  4. If i add the below after line 51 in the script,

    Dim Test : Set Test = dataView.Fetch

    Script enters the loop :

    If emptyComponent Then
    WriteLog ” component name: ” & tempComponent
    WriteLog “Deleting empty component: ” & tempComponent
    End If

    Log Output:

    9/27/2016 4:39:49 PM: Deleting Empty Components
    9/27/2016 4:39:49 PM: Processing: Test.msi
    9/27/2016 4:39:49 PM: component name: NewComponent2
    9/27/2016 4:39:49 PM: Deleting empty component: NewComponent2
    9/27/2016 4:39:49 PM: component name: NewComponent1
    9/27/2016 4:39:49 PM: Deleting empty component: NewComponent1
    9/27/2016 4:39:49 PM: component name: LendingBBLOracleConnect_old.dll
    9/27/2016 4:39:49 PM: Deleting empty component: LendingBBLOracleConnect_old.dll
    9/27/2016 4:39:49 PM: component name: OraOps10.dll
    9/27/2016 4:39:49 PM: Deleting empty component: OraOps10.dll
    9/27/2016 4:39:49 PM: component name: gacutil.exe
    9/27/2016 4:39:49 PM: Deleting empty component: gacutil.exe
    9/27/2016 4:39:49 PM: component name: LendingBBLOracleConnect_SELEX.dll
    9/27/2016 4:39:49 PM: Deleting empty component: LendingBBLOracleConnect_SELEX.dl

  5. I have one query component having ini table entry I want move to different component and then want delete that component ,

    For example ;

    A&B having two components

    A component having exe file

    B component having ini table entry

    Just I want to move ini file to A component

    Then I want delete B component

    Can you please add this point to delete component script

Leave a Reply