Home » MSI (Windows Installer) » Useful Adminstrative Scripts » Rename Single-file Components

Rename Single-file Components

Posted on by

Description

This script will rename single-file components to their filename.

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 "Renaming Single-file Components to their File Name"
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 filenameLength : filenameLength = 0
Dim component : component = ""
Dim filename : filename = ""
Dim tempTable : tempTable = ""	
Dim tempColumn : tempColumn = ""
Dim tempColVal : tempColVal = ""

Dim componentView, componentRec, fileView, fileRec, id, compExistView, compExistRec, tablesRec, tablesView, tempTableRec, tempTableView

If oDatabase.TablePersistent("Component") = 1 AND oDatabase.TablePersistent("File") = 1 And oDatabase.TablePersistent("FeatureComponents") Then

	Set componentView = oDatabase.OpenView("SELECT `Component` FROM `Component`")
	componentView.Execute
	Set componentRec = componentView.Fetch

	'component table has records
	Do Until componentRec Is Nothing
		component = componentRec.StringData(1)

		If Not isMSMData(component) Then

			Set fileView = oDatabase.OpenView("SELECT `FileName` FROM `File` WHERE `Component_`='" & component & "'")
			fileView.Execute
			If not fileView.Fetch is nothing and fileView.Fetch is nothing Then  'it has one file

				Set fileRec = fileView.Fetch
				filename = fileRec.StringData(1)

				If InStr(filename,"|") Then
					'attempt to get actual filename if there is a sfn equivalent
					filename = Split(filename,"|")(1)
				End If

				filenameLength = Len(filename)
				If Not (LCase(filename) = Left(LCase(component),filenameLength)) Then	

					If Not IsNumeric(Left(filename,1)) AND Not Instr(filename,"-") > 0 Then						
						'if filename doesnt start with a number or contain a '-' we rename
						'(otherwise if it does contain one of these it will constantly rename the ocmponent each time you run it)
						renameComponent component,filename
					End If 

				End If					
			End If

			Set fileView = Nothing
			Set fileRec = Nothing
		end If
		Set componentRec = componentView.Fetch
	Loop

	Set componentRec= Nothing
	Set componentView= 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

'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

Function renameComponent(oldComponent,newComponent)

	'check component doesnt exist
	id = 0		
	Do While componentExists(newComponent)	
		id = id + 1			
		newComponent = newComponent & id
	Loop

	Set tablesView = oDatabase.OpenView("SELECT `Table`,`Name` FROM `_Columns` WHERE `Name`= 'Component_' OR Name`= 'Component'") 
	tablesView.Execute
	Set tablesRec = tablesView.Fetch
	Do While Not tablesRec Is Nothing
		tempTable = tablesRec.StringData(1)
		tempColumn = tablesRec.StringData(2)

		If oDatabase.TablePersistent(tempTable) = 1 Then 					
			Set tempTableView = oDatabase.OpenView("SELECT `" & tempColumn & "` FROM `" & tempTable & "` WHERE `" & tempColumn & "`='" & oldComponent & "'")
			tempTableView.Execute
			Set tempTableRec = tempTableView.Fetch	
				Do Until tempTableRec Is Nothing						
					tempTableRec.StringData(1) = newComponent
					tempTableView.Modify msiViewModifyReplace, tempTableRec
					Set tempTableRec = tempTableView.Fetch
				Loop
			Set tempTableView = Nothing
			Set tempTableRec = Nothing							
		End If			

		Set tablesRec = tablesView.Fetch
	Loop						

	Set tablesView = Nothing
	Set tablesRec = Nothing

	Set tablesView = oDatabase.OpenView("SELECT `Table`,`Column` FROM `_Validation` WHERE `Category`= 'Condition' OR `Category`= 'Formatted' OR `Category`= 'Identifier'") 
	tablesView.Execute
	Set tablesRec = tablesView.Fetch
	Do While Not tablesRec Is Nothing
		tempTable = tablesRec.StringData(1)
		tempColumn = tablesRec.StringData(2)

		If oDatabase.TablePersistent(tempTable) = 1 Then 					
			Set tempTableView = oDatabase.OpenView("SELECT `" & tempColumn & "` FROM `" & tempTable & "`")
			tempTableView.Execute
			Set tempTableRec = tempTableView.Fetch	
				Do Until tempTableRec Is Nothing	

					tempColVal = tempTableRec.StringData(1)

					If InStr(tempColVal,"$" & oldComponent) Then
						tempTableRec.StringData(1) = Replace(tempColVal,"$" & oldComponent,"$" & newComponent)
						tempTableView.Modify msiViewModifyReplace, tempTableRec						
					End If

					If InStr(tempColVal,"?" & oldComponent) Then
						tempTableRec.StringData(1) = Replace(tempColVal,"?" & oldComponent,"?" & newComponent)
						tempTableView.Modify msiViewModifyReplace, tempTableRec						
					End If

					Set tempTableRec = tempTableView.Fetch
				Loop
			Set tempTableView = Nothing
			Set tempTableRec = Nothing							
		End If			

		Set tablesRec = tablesView.Fetch
	Loop						

	Set tablesView = Nothing
	Set tablesRec = Nothing

     WriteLog "Component: " & oldComponent & " renamed to : " & newComponent

End Function

'used to see if a component exists or Not
Function componentExists(component)

	'this function is called initially with '1' as the id.  Then this value gets incrememnetd if the component exists
	Set compExistView = oDatabase.OpenView("SELECT `Component` FROM `Component` WHERE `Component`='" & component & "'")
	compExistView.Execute
	Set compExistRec = compExistView.Fetch
	If Not compExistRec is Nothing Then
		Set compExistView = Nothing
		Set compExistRec = Nothing
		componentExists = True			
	Else
		Set compExistView = Nothing
		Set compExistRec = Nothing
		componentExists = False
	End If	

End Function

 

Comments have now been disabled. If you have a question to ask about this post please ask the community!