Inserting a registry value in an MSI database (Modify method)

This blog entry provides an example of inserting a registry value in an MSI database using the Modify method and VBScript.  It follows on from the previous blog post which provided a tutorial on deleting a registry value from an MSI database using the Modify method and VBScript.

It forms part 9 of an 17-part series that explores how to use VBScript to manipulate MSI relational databases using the Windows Installer API.  Throughout this series of tutorials, we identify the common issues that we encounter and the best practises that we use to overcome them.

In this example, we run a SQL statement to include the columns of data which we want to insert – this also helps us to identify if the row of data already exists before we try to insert it!

Note that we MUST include all of the non-nullable columns as a minimum in the SQL statement. When a column is not nullable, it means we MUST specify a value when we insert the record. Otherwise the insertion will fail. To find the non-nullable columns, consult the Windows Installer help file (MSI.chm) or MSDN. For example:

The four non-nullable columns which we MUST include when inserting into the Registry table are:

Registry
Root
Key
Component_

Dim sql : sql = "SELECT `Registry`,`Root`,`Key`,`Component_` FROM `Registry` WHERE `Registry` = 'MyNewSampleReg'"

If we were lazy, we could just return all rows using the following:

Dim sql : sql = "SELECT * FROM `Registry` WHERE `Registry` = 'MyNewSampleReg'"

This time when we execute the query, we’re not going to loop through any records using the While…Wend loop. All we want to do is see if the record already exists:

If regRecord Is Nothing Then

and if it doesn’t, we’ll start to create a new record and populate the values….

'There are no records returned, so we create a new record
    Set regRecord = oInstaller.CreateRecord(4)

    'in this example, we've created a record ensuring that all the non-nullable field are populated
    regRecord.StringData(1) = "MyNewSampleReg"
    regRecord.IntegerData(2) = 2
    regRecord.StringData(3) = "SOFTWARE\alkaneTest"
    regRecord.StringData(4) = "alkaneComponent"

Note how we’ve used StringData for columns which can accept strings as their data types, and IntegerData for columns which accept numeric values only.
Again, to find columns with an ‘Integer’ data type you should consult the Windows Installer help file (MSI.chm) or MSDN.

Once we’ve created our new record, we insert it:

regView.Modify msiViewModifyInsert,regRecord

And here is the finished script:

'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 msiViewModifyInsert = 1
Const msiViewModifyUpdate = 2
Const msiViewModifyDelete = 6
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 sql : sql = "SELECT `Registry`,`Root`,`Key`,`Component_` FROM `Registry` WHERE `Registry` = 'MyNewSampleReg'"
'create a view of the registry we want to see
Dim regView : Set regView = oDatabase.OpenView(sql)

'execute the query
regView.Execute 
Set regRecord = regView.Fetch

If regRecord Is Nothing Then
	'There are no records returned, so we create a new record
	Set regRecord = oInstaller.CreateRecord(4)

	'in this example, we've created a record ensuring that all the non-nullable field are populated
	regRecord.StringData(1) = "MyNewSampleReg"
	regRecord.IntegerData(2) = 2
	regRecord.StringData(3) = "SOFTWARE\alkaneTest"
	regRecord.StringData(4) = "alkaneComponent"

	regView.Modify msiViewModifyInsert,regRecord

End If

oDatabase.Commit

regView.Close
Set regView = Nothing
Set regRecord = Nothing
Set oDatabase = Nothing
Set oInstaller = Nothing

Thanks for reading about inserting a registry value in an MSI database using the Modify method.  Next you can find out how to handle tables that don’t exist in an MSI database using VBScript.

Deleting a registry value in an MSI database (Modify method)

This blog entry provides an example of deleting a registry value in an MSI database using the Modify method and VBScript.  It follows on from the previous blog post which provided a tutorial on uddating a primary key in an MSI database using the Modify method and VBScript.

It forms part 8 of an 17-part series that explores how to use VBScript to manipulate MSI relational databases using the Windows Installer API.  Throughout this series of tutorials, we identify the common issues that we encounter and the best practises that we use to overcome them.

Taking our script from previous tutorials, we first need to search for the record we want to delete and then we can simple replace msiViewModifyUpdate with msiViewModifyDelete:

'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 msiViewModifyInsert = 1
Const msiViewModifyUpdate = 2
Const msiViewModifyDelete = 6
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 sql : sql = "SELECT `Registry` FROM `Registry` WHERE `Registry` = 'SampleReg'"
'create a view of the registry we want to see
Dim regView : Set regView = oDatabase.OpenView(sql)

'execute the query
regView.Execute 

'fetch the first row of data (if there is one!)
Dim regRecord : Set regRecord = regView.Fetch

'whilst we've returned a row and therefore regRecord is not Nothing
While Not regRecord Is Nothing

	regView.Modify msiViewModifyDelete, regRecord 'go and fetch the next row of data Set regRecord = regView.Fetch Wend oDatabase.Commit regView.Close Set regView = Nothing Set regRecord = Nothing Set oDatabase = Nothing Set oInstaller = Nothing

Thanks for reading about deleting a registry value in an MSI database using the Modify method.  Next you can find out how to insert a registry value in an MSI database using the Modify method and VBScript.

Updating a primary key in an MSI database (Modify method)

This blog entry provides an example of updating a primary key in an MSI database using the Modify method and VBScript.  It follows on from the previous blog post which provided a tutorial on updating a registry value using the Modify method of an MSI database.

It forms part 7 of an 17-part series that explores how to use VBScript to manipulate MSI relational databases using the Windows Installer API.  Throughout this series of tutorials, we identify the common issues that we encounter and the best practises that we use to overcome them.

Here we would change the SQL query to select our primary key value (in other words, we’re selecting the Registry column now instead of the Value column):

Dim regView : Set regView = oDatabase.OpenView("SELECT `Registry` FROM `Registry` WHERE `Registry` = 'SampleReg'")

and we would modify it like this:

regRecord.StringData(1) = "NewSampleReg"
regView.Modify msiViewModifyReplace, regRecord

So in full it becomes:

'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 msiViewModifyInsert = 1
Const msiViewModifyUpdate = 2
Const msiViewModifyDelete = 6
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 sql : sql = "SELECT `Registry` FROM `Registry` WHERE `Registry` = 'SampleReg'"
'create a view of the registry we want to see
Dim regView : Set regView = oDatabase.OpenView(sql)

'execute the query
regView.Execute 

'fetch the first row of data (if there is one!)
Dim regRecord : Set regRecord = regView.Fetch

'whilst we've returned a row and therefore regRecord is not Nothing
While Not regRecord Is Nothing

	regRecord.StringData(1) = "NewSampleReg" 
	regView.Modify msiViewModifyReplace, regRecord

	'go and fetch the next row of data	
	Set regRecord = regView.Fetch
Wend

oDatabase.Commit

regView.Close
Set regView = Nothing
Set regRecord = Nothing
Set oDatabase = Nothing
Set oInstaller = Nothing

Note that this essentially won’t update that particular row. Instead it will delete the current row, and insert the new row containing the new primary key value.

Thanks for reading about updating a primary key in an MSI database using the Modify method and VBScript.  Next you can find out how to delete a registry value in an MSI database using the Modify method and VBScript.

Updating a registry value in an MSI database (Modify method)

This blog entry provides an example of updating a registry value in an MSI database using the Modify method and VBScript.  It follows on from the previous blog post which provided a tutorial on updating a registry value in an MSI database.

It forms part 6 of an 17-part series that explores how to use VBScript to manipulate MSI relational databases using the Windows Installer API.  Throughout this series of tutorials, we identify the common issues that we encounter and the best practises that we use to overcome them.

Similarly to Updating a registry value in an MSI database let’s update the key we inserted earlier and change:

HKLM\Software\AlkaneTest\testName testValue

to

HKLM\Software\AlkaneTest\testName NewTestValue

When using the Modify method, we are modifying a record object (or in other words, a row of data returned from one of our tables). In order to do this, we must first find the record which we want to modify. To do this, we’ll base our script on Reading a registry value from an MSI database but change our SQL statement to:

Dim sql : sql = "SELECT `Value` FROM `Registry` WHERE `Registry` = 'SampleReg'"

Because we are searching for the name of a primary key (‘Registry’), and the primary key is always unique, this query will return one row of data. When we go inside the While…Wend loop we set our new value:

regRecord.StringData(1) = "newTestValue"
regView.Modify msiViewModifyUpdate, regRecord

Note how the value we are modifying is regRecord.StringData(1). The ‘1’ is referencing the column in the select statement above (i.e, the ‘Value’ column).
If our select statement was:

Dim sql : sql = "SELECT `Registry`,`Key`,`Value` FROM `Registry` WHERE `Registry` = 'SampleReg'"

Then our Modify statment would be this (Note how ‘1’ now becomes ‘3’, because ‘Value’ is the third column in our select query):

regRecord.StringData(3) = "newTestValue"
regView.Modify msiViewModifyUpdate, regRecord

Anyway, your script should now look like this:

'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 msiViewModifyInsert = 1
Const msiViewModifyUpdate = 2
Const msiViewModifyDelete = 6
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 sql : sql = "SELECT `Value` FROM `Registry` WHERE `Registry` = 'SampleReg'"
'create a view of the registry we want to see
Dim regView : Set regView = oDatabase.OpenView(sql)

'execute the query
regView.Execute 

'fetch the first row of data (if there is one!)
Dim regRecord : Set regRecord = regView.Fetch

'whilst we've returned a row and therefore regRecord is not Nothing
While Not regRecord Is Nothing

	regRecord.StringData(1) = "newTestValue"
	regView.Modify msiViewModifyUpdate, regRecord

	'go and fetch the next row of data	
	Set regRecord = regView.Fetch
Wend

oDatabase.Commit

regView.Close
Set regView = Nothing
Set regRecord = Nothing
Set oDatabase = Nothing
Set oInstaller = Nothing

Thanks for reading about updating a registry value in an MSI database using the Modify method and VBScript.  Next you can find out how to update a primary key in an MSI database using the Modify method and VBScript.