我在这里看到可以使用SQL更新MSI表模式 - https://msdn.microsoft.com/en-us/library/aa368562%28v=vs.85%29.aspx
(供参考:列定义格式 - https://msdn.microsoft.com/en-us/library/aa367870%28v=vs.85%29.aspx)
我想将表格的列从SHORT(最大值32767)更改为INTEGER(最大值2147483647)。所有这些命令都给出了同样的错误:
CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` ALTER `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` ALTER `Sequence` INTEGER 4:
CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` ALTER COLUMN `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` ALTER COLUMN `Sequence` INTEGER 4:
CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` UPDATE `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` UPDATE `Sequence` INTEGER 4:
CScript WiRunSQL.vbs Test.msi "ALTER TABLE `File` MODIFY `Sequence` INTEGER"
Msi API Error 80004005: OpenView,Sql
1: 2237 2: C:\Test.msi 3: ALTER TABLE `File` MODIFY `Sequence` INTEGER 4:
我知道我可以通过Orca或InstEdit中的UI进行这些架构更改,并且我确信这些应用程序只是在底层运行SQL。我似乎无法弄清楚正确的陈述是什么......
更新:我最后编写了以下VB脚本以更新文件和媒体表(因为我需要更改其Sequence和LastSequence列的数据类型):
' MSI table schemas that need updating:
' Table Column Expected Data Type
' ----- ------ ------------------
' File Sequence SHORT
' Media LastSequence SHORT
'
'
' Structure of this script:
' 1. Create a FileTemp table, with the correct schema
' 2. Copy all the rows from File -> FileTemp
' 3. Delete the File table
' 4. Re-create the File table, with the correct schema
' 5. Copy all the rows from FileTemp -> File
' 6. Delete the FileTemp table
' 7. Repeat 1-6 for the Media table
'
Set Args = wscript.Arguments
If Args.Count() = 1 Then
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
strMsiPath = fso.GetAbsolutePathName(Args.item(0))
Else
wscript.echo "Usage: UpdateSchema.vbs <full path to wix msi file>"
Wscript.Quit 1
End If
'Open the MSI with read/write permissions
set installer = CreateObject("WindowsInstaller.Installer")
set db = installer.OpenDatabase(strMsiPath, 1)
'Step 0 (start clean)
'For testing purposees: if the "FileTemp" table exists -> delete it so
'that we start fresh with each run of this script
findFileTempTableSQL = "SELECT * FROM `_Tables` WHERE `Name`='FileTemp'"
Set fileTempView = db.OpenView(findFileTempTableSQL)
fileTempView.Execute()
Set fileTempRecord = fileTempView.Fetch
If fileTempRecord Is Nothing Then
wscript.echo "***FileTemp Table does not exist (skipping...)"
Else
wscript.echo "***FileTemp Table exists (deleting...)"
dropTableSQL = "DROP TABLE `FileTemp`"
Set dropTableView = db.OpenView(dropTableSQL)
dropTableView.Execute()
db.Commit
End If
'Global Strings
g_FileTableCreationDefinition = "(`File` CHAR(72) NOT NULL," &_
" `Component_` CHAR(72) NOT NULL," &_
" `FileName` CHAR(255) NOT NULL LOCALIZABLE," &_
" `FileSize` LONG NOT NULL," &_
" `Version` CHAR(72)," &_
" `Language` CHAR(20)," &_
" `Attributes` SHORT," &_
" `Sequence` SHORT NOT NULL" &_
" PRIMARY KEY `File`)"
g_FileTableInsertDefinition = "(`File`,`Component_`,`FileName`,`FileSize`,`Version`,`Language`,`Attributes`,`Sequence`)"
g_MediaTableCreationDefinition = "(`DiskId` SHORT NOT NULL," &_
" `LastSequence` SHORT NOT NULL," &_
" `DiskPrompt` CHAR(64) LOCALIZABLE," &_
" `Cabinet` CHAR(255)," &_
" `VolumeLabel` CHAR(32)," &_
" `Source` CHAR(72)" &_
" PRIMARY KEY `DiskId`)"
g_MediaTableInsertDefinition = "(`DiskId`,`LastSequence`,`DiskPrompt`,`Cabinet`,`VolumeLabel`,`Source`)"
'Update the File table to fix the `Sequence` column data type...'
'Step 1 - Create a FileTemp table, with the correct schema
CreateTable db, "FileTemp", g_FileTableCreationDefinition
'Step 2 - Copy all the rows from File -> FileTemp
CopyFileTableData db, "File", "FileTemp"
'Step 3 - Delete the File table
DropTable db, "File"
'Step 4 - Re-create the File table, with the correct schema
CreateTable db, "File", g_FileTableCreationDefinition
'Step 5 - Copy all the rows from FileTemp -> File
CopyFileTableData db, "FileTemp", "File"
'Step 6 - Delete the FileTemp table
DropTable db, "FileTemp"
'Update the Media table to fix the `LastSequence` column data type...'
'Step 1 - Create a MediaTemp table, with the correct schema
CreateTable db, "MediaTemp", g_MediaTableCreationDefinition
'Step 2 - Copy all the rows from Media -> MediaTemp
CopyMediaTableData db, "Media", "MediaTemp"
'Step 3 - Delete the Media table
DropTable db, "Media"
'Step 4 - Re-create the Media table, with the correct schema
CreateTable db, "Media", g_MediaTableCreationDefinition
'Step 5 - Copy all the rows from MediaTemp -> Media
CopyMediaTableData db, "MediaTemp", "Media"
'Step 6 - Delete the MediaTemp table
DropTable db, "MediaTemp"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Helper Sub-functions
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'This is a function that will copy 'File' table data
' arguments:
' db - the MSI database object
' sourceTableName - a string representing the table name were data will be copied 'from', e.g. "File"
' destTableName - a string representing the table name were data will be copied 'to', e.g. "FileTemp"
Sub CopyFileTableData(db, sourceTableName, destTableName)
wscript.echo "***Copying rows from "+sourceTableName+" Table to "+destTableName+" Table..."
Set view = db.OpenView("SELECT * FROM "+sourceTableName)
view.Execute
Do
Set record = view.Fetch
If record Is Nothing Then Exit Do
File = record.StringData(1)
Component_ = record.StringData(2)
FileName = record.StringData(3)
FileSize = record.StringData(4)
Version = record.StringData(5)
Language = record.StringData(6)
Attributes = record.StringData(7)
Sequence = record.StringData(8)
recordValues = "('"+File+"','"+Component_+"','"+FileName+"',"+FileSize+",'"+Version+"','"+Language+"',"+Attributes+","+Sequence+")"
insertSQL = "INSERT INTO "+destTableName+" "+g_FileTableInsertDefinition+" VALUES "+recordValues
Set insertView = db.OpenView(insertSQL)
insertView.Execute
db.Commit
Loop
End Sub
'This is a function that will copy 'Media' table data
' arguments:
' db - the MSI database object
' sourceTableName - a string representing the table name were data will be copied 'from', e.g. "Media"
' destTableName - a string representing the table name were data will be copied 'to', e.g. "MediaTemp"
Sub CopyMediaTableData(db, sourceTableName, destTableName)
wscript.echo "***Copying rows from "+sourceTableName+" Table to "+destTableName+" Table..."
Set view = db.OpenView("SELECT * FROM "+sourceTableName)
view.Execute
Do
Set record = view.Fetch
If record Is Nothing Then Exit Do
DiskId = record.StringData(1)
LastSequence = record.StringData(2)
DiskPrompt = record.StringData(3)
Cabinet = record.StringData(4)
VolumeLabel = record.StringData(5)
Source = record.StringData(6)
recordValues = "("+DiskId+","+LastSequence+",'"+DiskPrompt+"','"+Cabinet+"','"+VolumeLabel+"','"+Source+"')"
insertSQL = "INSERT INTO "+destTableName+" "+g_MediaTableInsertDefinition+" VALUES "+recordValues
Set insertView = db.OpenView(insertSQL)
insertView.Execute
db.Commit
Loop
End Sub
'This is a function that will create a MSI table
' arguments:
' db - the MSI database object
' tableName - a string representing the table name, e.g. "File"
' tableDefinitino - a string representing the table column definition, e.g. "(`File` CHAR(72) NOT NULL,...)"
Sub CreateTable(db, tableName, tableDefinition)
Set view = db.OpenView("CREATE TABLE "+tableName+" "+tableDefinition)
wscript.echo "***Creating '"+tableName+"' Table..."
view.Execute
db.Commit
End Sub
'This is a function that will drop any table from the MSI
' arguments:
' db - the MSI database object
' tableName - a string representing the table name, e.g. "File"
Sub DropTable(db, tableName)
Set view = db.OpenView("DROP TABLE "+tableName)
wscript.echo "***Dropping '"+tableName+"' Table..."
view.Execute
db.Commit
End Sub