Kae Travis

Delete Duplicate Registry

Description:

This script will delete duplicate registry entries in the Registry table of 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 "Removing Duplicate Registry"
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
Const msiViewModifyReplace = 4
'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 registryView, registryRecord, duplicateView, duplicateRecord, tempRecord
If oDatabase.TablePersistent("Registry") = 1 And oDatabase.TablePersistent("Component") = 1  Then
Set registryView = oDatabase.OpenView("SELECT `Registry`,`Key`,`Name`,`Value`,`Component_` FROM `Registry`")
registryView.Execute
Set registryRecord = registryView.Fetch
Do Until registryRecord Is Nothing
Set duplicateView = oDatabase.OpenView("SELECT `Registry` FROM `Registry` WHERE `Key`=? AND `Name`=? AND `Value`=? AND `Registry` <> ?")
Set tempRecord = oInstaller.CreateRecord(4)    
tempRecord.StringData(1) = registryRecord.StringData(2)    
tempRecord.StringData(2) = registryRecord.StringData(3)
tempRecord.StringData(3) = registryRecord.StringData(4)  
tempRecord.StringData(4) = registryRecord.StringData(1) 		
duplicateView.Execute(tempRecord)
Set tempRecord = Nothing
Set duplicateRecord = duplicateView.Fetch
While not duplicateRecord is Nothing
if not isMSMData(registryRecord.StringData(1)) and not isMSMData(duplicateRecord.StringData(1)) Then
WriteLog "DELETE FROM `Registry` WHERE `Registry` = '" & registryRecord.StringData(1) & "'"
oDatabase.OpenView("DELETE FROM `Registry` WHERE `Registry` = '" & registryRecord.StringData(1) & "'").Execute
Else
WriteLog "Omitted Duplicate Registry in Merge Module: " & registryRecord.StringData(1)
end If
Set duplicateRecord = duplicateView.Fetch
Wend
Set registryRecord = registryView.Fetch
Loop
End If
objLogFile.Close
Set fso = Nothing
Set objLogFile = Nothing	
Set registryView = Nothing
Set registryRecord = Nothing
Set duplicateView = Nothing
Set duplicateRecord = Nothing
oDatabase.Commit	
Set oDatabase = Nothing
Set oInstaller = Nothing
Sub WriteLog(LogMessage)
WScript.echo Now() & ": " & LogMessage
objLogFile.Writeline(Now() & ": " & LogMessage)
End Sub
'returns true if tempData contains MSM decoration
Function isMSMData(tempData)
isMSMData = False
Dim Match
Dim regEx : Set regEx = New RegExp
regEx.MultiLine = vbTrue
regEx.global = vbTrue
regEx.Pattern = "[A-Za-z0-9]{8}_[A-Za-z0-9]{4}_[A-Za-z0-9]{4}_[A-Za-z0-9]{4}_[A-Za-z0-9]{12}"
For Each Match in regEx.Execute(tempData)
isMSMData = True
Next
Set regEx = Nothing
End Function

 

Delete Duplicate Registry
Delete Duplicate Registry

Leave a Reply