Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.5 KiB

  1. ' Windows Installer utility to report the differences between two databases
  2. ' For use with Windows Scripting Host, CScript.exe only, lists to stdout
  3. ' Copyright (c) 1999, Microsoft Corporation
  4. ' Simply generates a transform between the databases and then view the transform
  5. '
  6. Option Explicit
  7. Const icdLong = 0
  8. Const icdShort = &h400
  9. Const icdObject = &h800
  10. Const icdString = &hC00
  11. Const icdNullable = &h1000
  12. Const icdPrimaryKey = &h2000
  13. Const icdNoNulls = &h0000
  14. Const icdPersistent = &h0100
  15. Const icdTemporary = &h0000
  16. Const msiOpenDatabaseModeReadOnly = 0
  17. Const msiOpenDatabaseModeTransact = 1
  18. Const msiOpenDatabaseModeCreate = 3
  19. Const iteViewTransform = 256
  20. If Wscript.Arguments.Count < 2 Then
  21. Wscript.Echo "Windows Installer database difference utility" &_
  22. vbNewLine & " Generates a temporary transform file, then display it" &_
  23. vbNewLine & " 1st argument is the path to the original installer database" &_
  24. vbNewLine & " 2nd argument is the path to the updated installer database"
  25. Wscript.Quit 1
  26. End If
  27. ' Cannot run with GUI script host, as listing is performed to standard out
  28. If UCase(Mid(Wscript.FullName, Len(Wscript.Path) + 2, 1)) = "W" Then
  29. WScript.Echo "Cannot use WScript.exe - must use CScript.exe with this program"
  30. Wscript.Quit 2
  31. End If
  32. ' Connect to Windows Installer object
  33. On Error Resume Next
  34. Dim installer : Set installer = Nothing
  35. Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError
  36. ' Create path for temporary transform file
  37. Dim WshShell : Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckError
  38. Dim tempFilePath:tempFilePath = WshShell.ExpandEnvironmentStrings("%TEMP%") & "\diff.tmp"
  39. ' Open databases, generate transform, then list transform
  40. Dim database1 : Set database1 = installer.OpenDatabase(Wscript.Arguments(0), msiOpenDatabaseModeReadOnly) : CheckError
  41. Dim database2 : Set database2 = installer.OpenDatabase(Wscript.Arguments(1), msiOpenDatabaseModeReadOnly) : CheckError
  42. Dim different : different = Database2.GenerateTransform(Database1, tempFilePath) : CheckError
  43. If different Then
  44. database1.ApplyTransform tempFilePath, iteViewTransform + 0 : CheckError' should not need error suppression flags
  45. ListTransform database1
  46. End If
  47. ' Open summary information streams and compare them
  48. Dim sumInfo1 : Set sumInfo1 = database1.SummaryInformation(0) : CheckError
  49. Dim sumInfo2 : Set sumInfo2 = database2.SummaryInformation(0) : CheckError
  50. Dim iProp, value1, value2
  51. For iProp = 1 to 19
  52. value1 = sumInfo1.Property(iProp) : CheckError
  53. value2 = sumInfo2.Property(iProp) : CheckError
  54. If value1 <> value2 Then
  55. Wscript.Echo "\005SummaryInformation [" & iProp & "] {" & value1 & "}->{" & value2 & "}"
  56. different = True
  57. End If
  58. Next
  59. If Not different Then Wscript.Echo "Databases are identical"
  60. Wscript.Quit 0
  61. Function DecodeColDef(colDef)
  62. Dim def
  63. Select Case colDef AND (icdShort OR icdObject)
  64. Case icdLong
  65. def = "LONG"
  66. Case icdShort
  67. def = "SHORT"
  68. Case icdObject
  69. def = "OBJECT"
  70. Case icdString
  71. def = "CHAR(" & (colDef AND 255) & ")"
  72. End Select
  73. If (colDef AND icdNullable) = 0 Then def = def & " NOT NULL"
  74. If (colDef AND icdPrimaryKey) <> 0 Then def = def & " PRIMARY KEY"
  75. DecodeColDef = def
  76. End Function
  77. Sub ListTransform(database)
  78. Dim view, record, row, column, change
  79. On Error Resume Next
  80. Set view = database.OpenView("SELECT * FROM `_TransformView` ORDER BY `Table`, `Row`")
  81. If Err <> 0 Then Wscript.Echo "Transform viewing supported only in builds 4906 and beyond of MSI.DLL" : Wscript.Quit 2
  82. view.Execute : CheckError
  83. Do
  84. Set record = view.Fetch : CheckError
  85. If record Is Nothing Then Exit Do
  86. change = Empty
  87. If record.IsNull(3) Then
  88. row = "<DDL>"
  89. If NOT record.IsNull(4) Then change = "[" & record.StringData(5) & "]: " & DecodeColDef(record.StringData(4))
  90. Else
  91. row = "[" & Join(Split(record.StringData(3), vbTab, -1), ",") & "]"
  92. If record.StringData(2) <> "INSERT" AND record.StringData(2) <> "DELETE" Then change = "{" & record.StringData(5) & "}->{" & record.StringData(4) & "}"
  93. End If
  94. column = record.StringData(1) & " " & record.StringData(2)
  95. if Len(column) < 24 Then column = column & Space(24 - Len(column))
  96. WScript.Echo column, row, change
  97. Loop
  98. End Sub
  99. Sub CheckError
  100. Dim message, errRec
  101. If Err = 0 Then Exit Sub
  102. message = Err.Source & " " & Hex(Err) & ": " & Err.Description
  103. If Not installer Is Nothing Then
  104. Set errRec = installer.LastErrorRecord
  105. If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
  106. End If
  107. Wscript.Echo message
  108. Wscript.Quit 2
  109. End Sub