Installer patches are used to patch an already installed product in order to update/add some more features or fixation of errors/bugs etc.
While creation a patch for a product about whom, the build procedure is not known to me, I first tried WIX provided Patch Creation Properties (.pcp file) method, which resulted in a big sized msp file (500+ MB). When I tried to apply the patch, it shows the setup dialogs for Updated build but failed with following message:
"Another version is already installed. You must first uninstall it in order to install this version."
I even changed the Product Code in the 2nd msi (in all tables), but doesn’t solved any problem.
Then changing attribute value of WholeFilesOnly="no" from ‘yes’ under PatchCreation element reduced the size to 262 MB (I know its not a small size for a patch). But resulted in same error when tried to apply on installed product.
Alternatively, I tried msdn tutorial for using Patch Creation Properties (.pcp) file and that resulted in exactly same problem as that of Wix pcp case.
The I tried Wix Patching which actually supports making a patch by selectively adding Components to be patched on target machine. So I added few components, just to prototype it. And when Pyro.exe complaint about different GUIDs, that makes me to check for Component Ids (GUIDS) in both builds.
If you have installed Microsoft SDK 7.x then there would be a script file installed as C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\msi\scripts\WiDiffDb.vbs. I used this file to get a difference report between the Updated Msi and Target msi and to my surprise, every Component Id (GUID) was changed in Updated build.
To confirmed my doubt, I then took differences between other versions and found that Component Ids were totally refreshed in every build.
Well, why we should not change the Component Ids without any specific reason, can be measured from this article. And when to change Component GUIDs, read this.
Anyhow, I’m sure, that there could be some reason behind changing Component GUIDs in every build, but that causes problems in generating patches.
To cope with this situation, I played a small hack with the Upgraded msi.. Guess What.. here is the CSharp source code for that hack .
Yes, reading Component Ids from Original MSI and replacing in Updated msi while comparing Component Names and making Component GUIDs same in both msi.
And now when I tried to create patch using Wix Patching … O Yes, it worked.. and I’ve working patch and when I tested, it worked as expected. .
And then I tried to use Patch Creation Properties (*.pcp) methods again with this modified Updated msi, but in vain. Problem never changed .
The only difference is that, this method needs a selection of Component manually, while in Patch Creation Properties (*.pcp) methods, it took whole builds differences and generates a patch upon these.
Although, Wix Patching is the only working solution I have in this situation, but Product owners are not happy with this . Because now they have to select files manually.
Anyhow, I’m still looking for some other solutions. And you have some better solution/correction/Tutorial etc etc. you are most welcome to share it..
While creation a patch for a product about whom, the build procedure is not known to me, I first tried WIX provided Patch Creation Properties (.pcp file) method, which resulted in a big sized msp file (500+ MB). When I tried to apply the patch, it shows the setup dialogs for Updated build but failed with following message:
"Another version is already installed. You must first uninstall it in order to install this version."
I even changed the Product Code in the 2nd msi (in all tables), but doesn’t solved any problem.
Then changing attribute value of WholeFilesOnly="no" from ‘yes’ under PatchCreation element reduced the size to 262 MB (I know its not a small size for a patch). But resulted in same error when tried to apply on installed product.
Alternatively, I tried msdn tutorial for using Patch Creation Properties (.pcp) file and that resulted in exactly same problem as that of Wix pcp case.
The I tried Wix Patching which actually supports making a patch by selectively adding Components to be patched on target machine. So I added few components, just to prototype it. And when Pyro.exe complaint about different GUIDs, that makes me to check for Component Ids (GUIDS) in both builds.
If you have installed Microsoft SDK 7.x then there would be a script file installed as C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\msi\scripts\WiDiffDb.vbs. I used this file to get a difference report between the Updated Msi and Target msi and to my surprise, every Component Id (GUID) was changed in Updated build.
To confirmed my doubt, I then took differences between other versions and found that Component Ids were totally refreshed in every build.
Well, why we should not change the Component Ids without any specific reason, can be measured from this article. And when to change Component GUIDs, read this.
Anyhow, I’m sure, that there could be some reason behind changing Component GUIDs in every build, but that causes problems in generating patches.
To cope with this situation, I played a small hack with the Upgraded msi.. Guess What.. here is the CSharp source code for that hack .
C# - Update Component Ids
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using WindowsInstaller;
- namespace msitest
- {
- class Program
- {
- static void Main(string[] args)
- {
- string OrignalMSI = @"D:\ABD\OriginalBuild_225en1\MyProduct.msi";
- string UpdatedMSI = @"D:\ABD\UpdatedBuild_351en1\MyProduct.msi";
- string strFileMsiNameOnly = Path.GetFileNameWithoutExtension(OrignalMSI);
- string strDirectory = Path.GetDirectoryName(OrignalMSI);
- // Create an Installer instance
- Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
- Installer inst = (Installer)Activator.CreateInstance(classType);
- Database OriginalMSIdb = inst.OpenDatabase(OrignalMSI, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
- Database UpdatedMSIdb = inst.OpenDatabase(UpdatedMSI, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
- View OrgMsiView = OriginalMSIdb.OpenView("Select `Component`,`ComponentId` From Component");
- View UpdMsiView = null;
- OrgMsiView.Execute(null);
- Dictionary<string,string> OrgMsiComponents=new Dictionary<string,string>();
- Record OrgMsiRecord = OrgMsiView.Fetch();
- string updQuery="";
- while (OrgMsiRecord != null)
- {
- Console.WriteLine(OrgMsiRecord.get_StringData(1) + " " + OrgMsiRecord.get_StringData(2));
- updQuery = "Update `Component` SET `Component`.`ComponentId`=" + "'" + OrgMsiRecord.get_StringData(2) + "'" + " WHERE `Component`.`Component`=" + "'" + OrgMsiRecord.get_StringData(1) + "'";
- UpdMsiView=UpdatedMSIdb.OpenView(updQuery);
- UpdMsiView.Execute(null);
- //consolestring result = r.get_StringData(1);
- OrgMsiRecord = OrgMsiView.Fetch();
- }
- UpdatedMSIdb.Commit();
- // close the database
- OrgMsiView.Close();
- UpdMsiView.Close();
- }
- }
- }
And now when I tried to create patch using Wix Patching … O Yes, it worked.. and I’ve working patch and when I tested, it worked as expected. .
And then I tried to use Patch Creation Properties (*.pcp) methods again with this modified Updated msi, but in vain. Problem never changed .
The only difference is that, this method needs a selection of Component manually, while in Patch Creation Properties (*.pcp) methods, it took whole builds differences and generates a patch upon these.
Although, Wix Patching is the only working solution I have in this situation, but Product owners are not happy with this . Because now they have to select files manually.
Anyhow, I’m still looking for some other solutions. And you have some better solution/correction/Tutorial etc etc. you are most welcome to share it..
No comments:
Post a Comment