Creating Patch Installers

Windows Installer Technology allows for MSP Patch installers, which compliment your MSI installers really well.  However, Visual Studio doesn’t support the creation of them from within the IDE.  In fact, you have to download the Windows SDK Toolkit and use a utility called MSIMSP.  For this process, you will also need a utility called Orca from the same SDK; when you download the SDK, inside the Bin folder is an Orca.msi installer.

What you do is build the original version of your MSI installer; then you make the necessary changes and/or fixes to your product and recreate another MSI installer representing the new version of your product.  Then you pass these two MSI installers to the MSIMSP utility and it creates an MSP patch installer for you by automatically detecting the binary differences between the two MSI installers.

I used this article as a guide:  http://www.codeproject.com/KB/install/dotnetpatching.aspx

However, the Platform SDK link in the article is broken, so use this one instead:  http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en

This isn’t the most up-to-date Windows SDK, but the batch script in the CodeProject article relies on this specific versions folder structure (it has everything you need to create the MSP patch installer nicely in one folder, whereas the newest SDK does not).

I did run into a few of the same hiccups that others did (found down below in the comments of the CodeProject article).  Here are links to my posts with the solutions (you’ll have to click around each thread to see the problems posted before my posts):

Also, I had to modify his patch.cmd batch file slightly; a copy of it is pasted below.

This process isn’t as effective as it should be if you are trying to difference two Visual Studio created MSI installers.  The MSIMSP utility is very thorough in its comparison of file names, locations, sizes, versions, and every byte of data contained in the files.  It can create a binary difference between the two files in order to minimize as much as possible the patch installer’s size and speed.  It even compares the 8.3 short filename of every file.  Unfortunately, Visual Studio can be very inconsistent in its assignment of short filenames with the tilde-numbering system (i.e., "FILENA~3.TXT") if you add, rename, move, or delete even a couple of files from your project.  I often had to manually edit the short filenames in the second MSI using the Orca utility to make the names be consistent between the two versions of the Visual Studio created installers; otherwise, the MSIMSP utility would just blindly include the whole file for patching and inflate the overall size of the MSP patcher.

Good luck and enjoy not having to figure out what the deltas are between the versions of your products!

if "%1"=="" %0 Debug Release Done 

@SETLOCAL
@set path=%path%;"C:\Program Files\Microsoft Platform SDK\Samples\SysMgmt\Msi\Patching"
@set PatchTmp=C:\VSTemp

:loop
if "%1"=="Done" goto end

if not exist %1\*.msi goto nopatch
if not exist TargetImage\%1\*.msi goto nopatch

:ok
rmdir /s /q %PatchTmp%
mkdir %PatchTmp%
mkdir %PatchTmp%\TargetImage
mkdir %PatchTmp%\UpgradedImage
mkdir %PatchTmp%\Patch

for %%a in (TargetImage\%1\*.msi) do copy %%a %PatchTmp%\setup.msi
msiexec /qb /a %PatchTmp%\setup.msi TARGETDIR=%PatchTmp%\TargetImage /L*v %PatchTmp%\TargetImage\setup.log
del %PatchTmp%\setup.msi

for %%a in (%1\*.msi) do copy %%a %PatchTmp%\setup.msi
msiexec /qb /a %PatchTmp%\setup.msi TARGETDIR=%PatchTmp%\UpgradedImage /L*v %PatchTmp%\UpgradedImage\setup.log
del %PatchTmp%\setup.msi

copy patch.pcp %PatchTmp%
set PatchDir=%CD%
chdir %PatchTmp%
msimsp -s patch.pcp -p Patch\patch.msp -l Patch\patch.log -f %PatchTmp%\Tmp -d

rmdir /s /q %PatchTmp%\TargetImage
rmdir /s /q %PatchTmp%\UpgradedImage
rmdir /s /q %PatchTmp%\Tmp
chdir %PatchDir%

mkdir Patch
mkdir Patch\%1
copy %PatchTmp%\Patch\*.* Patch\%1\*.*
rmdir /s /q %PatchTmp%

:nopatch
shift
goto loop

:end
pause

Comments

pavan
if u run the above cmd file,it is going into an infinite loop.
pavan
ERROR: PatchGUID property is missing from the Properties table of the .pcp file. This is a required property
ravish
Found the solution…
i was missing "/D" option for chdir in my .cmd file
ravish
Hi Mike,
Thanks for the very useful article.
While prepating a patch as described above, i am getting following error
Failed to create patch. Error code: 0xC00E5198

any idea what can be the problem ?
Baburaj
Hi I’m getting this error while patching:

ERROR: UpgradedImages.MsiPath ‘C:\VSTemp\UpgradedImage\ERP.msi’ does not exist.


What could be the reason? I used your patch.cmd file.
Mike Murray
I think you will find the following link helpful:

http://forum.installsite.net/index.php?showtopic=15237

I think you will find the whole website InstallSite.net to be a helpful resource for all questions about installers, especially MSI and MSP installers.
daniju
Hi michael, thanks for your post is very interesting.

I´m trying release step to step, but my problem is the next:

***** Log starting: 2008-10-29 10:24:54 *****

Input-PCP path = ‘patch.pcp’
Patch-MSP path = ‘Patch\patch.msp’
Temp Folder = ‘C:\VSTemp\Tmp'
Patch GUID = ‘{91FF215B-112C-42B9-8862-FEE08663EC9C}’
ListOfPatchGUIDsToReplace = “none”
ListOfTargetProductCodes = ‘*’
PatchSourceList = ‘PatchSourceList’
AllowProductCodeMismatches = ‘1’
AllowProductVersionMajorMismatches = ‘1’
OptimizePatchSizeForLargeFiles = ‘blank’
ApiPatchingSymbolFlags = ‘0x00000000’
MsiFileToUseToCreatePatchTables = ‘blank’
SqlCmdToCreatePatchTable = ‘blank’
SqlCmdToCreatePatchPackageTable = ‘blank’
SqlCmdToCreateMsiPatchHeadersTable = ‘blank’
DontRemoveTempFolderWhenFinished = ‘1’
IncludeWholeFilesOnly = ‘0’
MinimumRequiredMsiVersion = ‘200’
SEQUENCE_DATA_GENERATION_DISABLED = ‘blank’
AllowRemoval = ‘blank’

Using internal SQL cmd to create ‘Patch’ table.
Using internal SQL cmd to create ‘PatchPackage’ table.
Using internal SQL cmd to create ‘MsiPatchHeaders’ table.

Files differ: ‘C:\VSTemp\UpgradedImage.\AlbumFotos.dll’,
‘C:\VSTemp\TargetImage.\AlbumFotos.dll’.
Patch file created: FTK=_0E2D0A15B23B989808E6FD64A243497B; temp location=fam1\00002.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\PruebasPictureBox.dll’,
‘C:\VSTemp\TargetImage.\PruebasPictureBox.dll’.
Patch file created: FTK=_24E4033462F0482C9B569672F8337663; temp location=fam1\00003.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\DermaDatos.dll’,
‘C:\VSTemp\TargetImage.\DermaDatos.dll’.
Patch file created: FTK=_294ABD0349756E66C6CB0D11001752CE; temp location=fam1\00004.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\CapturaImagenesPruebas.dll’,
‘C:\VSTemp\TargetImage.\CapturaImagenesPruebas.dll’.
Patch file created: FTK=_5E58F544E2DC940F4F3139031A15DE72; temp location=fam1\00005.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\PruebasInforme.exe’,
‘C:\VSTemp\TargetImage.\PruebasInforme.exe’.
Patch file created: FTK=_7328B00680B1965AF0370EF0DE389DBE; temp location=fam1\00006.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\MotorAlertas.dll’,
‘C:\VSTemp\TargetImage.\MotorAlertas.dll’.
Patch file created: FTK=_7FBC6D05562B82F2CDC2F1BDBE476432; temp location=fam1\00007.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\ModoDiapositiva.dll’,
‘C:\VSTemp\TargetImage.\ModoDiapositiva.dll’.
Patch file created: FTK=_8FEA4D552741B28293ABC797812149CD; temp location=fam1\00008.HDR.
Files differ: ‘C:\VSTemp\UpgradedImage.\Derma.exe’,
‘C:\VSTemp\TargetImage.\Derma.exe’.
Patch file created: FTK=_5260684262CA164CEF0A33F5A94CAC55; temp location=fam1\00009.HDR.
ERROR: Since MSI 3.0 will block installation of major upgrade patches with sequencing information, creation of such patches is blocked.

***** Log finishing: 2008-10-29 10:25:05 *****

What is my problem?? Can you help me, please???

Thank you very much

Catastrophic Failure

So I got a "Catastrophic Failure" in the Silverlight 2 beta 1 designer in VS 2008 this morning.  Have no clue what it means, but it seemed temporary (I was in the middle of typing in the XAML view and the designer didn’t like something I did).  Here is a screenshot, it’s pretty amusing:

screenshot

ASP.NET Security Tutorials

Comments

Scott Mitchell, from 4GuysFromRolla.com, is writing a terrific tutorial series on ASP.NET Forms Authentication, Authorization, User Accounts, and Roles.  This is a great series of articles on the use of ASP.NET’s built-in libraries to authenticate and identify visitors, lock down parts of your site through authorization, and manage users and roles.  When it’s all finished, it is supposed to be a 14-part series or something like that.  Here is the link:

http://asp.net/learn/security/?lang=cs

Migrating From vs 2005 to 2008

So I just finished migrating a whole slew of our large solutions and projects from Visual Studio 2005 to Visual Studio 2008.  The conversion process itself was really simple and painless (and not too time consuming).  There were a few gotchas with our Setup (AKA Deployment) Projects however:

  1. It appears that Microsoft moved the location of it’s prerequisite packages for the BootStrapper for VS 2008.  Microsoft used to keep them at C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages, but now in 2008 it looks they have moved them to a more isolated and common location.  The new location is C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages.  When I converted our setup projects to VS 2008 format, some of the prerequisites couldn’t be found because of this.  I just went to the old VS 2005 BootStrapper location and copied the folders of the packages I needed to the new VS 2008 location (for example, the MDAC package is under a folder called MDAC28, and it is not in VS 2008’s list of packages by default anymore).
  2. We had a folder structure into which we were dropping the Primary Output of a web application in our setup projects.  For a web application project, the Primary Output is the DLL libraries in the bin directory of the web site.  In VS 2005, you would create a bin folder at the root level of the web site and put the Primary Output down a level in the bin folder.  Well, now in VS 2008, it appears that wherever you put the Project Output, the setup project will create a bin folder at that location and put the DLL libraries in that bin folder one level down from where you put the Project Output.  So I had to go back through our setup projects and move the location of those Primary Outputs one level up (or else it would create a bin folder inside of the bin folder).

One nice thing about the migration to VS 2008 is that it looks like Microsoft has a new version of the Visual C++ Runtime Libraries prerequisite (I don’t know if the libraries are actually any different, but at least the redistributable package and logic are improved).  We have a set of products that have this package as a prerequisite during install.  Every time you ran the installer it would reinstall the package.  It was almost as if it wasn’t doing any logic to detect if it already had the package installed.  The following link might be the explanation of why we were seeing this odd behavior (even though it references the MDAC package):  http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=339044&SiteID=1

Well, the new Visual C++ Runtime Libraries package works great and doesn’t keep reinstalling itself as a prerequisite with every install or update of one of our products that depend on it.

FOLLOWUP (06/19/08):  Actually, we ended it up having to revert back to the Visual C++ Runtime Libraries from Visual Studio 2005, as another prerequisite we were using (DTSearch) wasn’t compatible with the new C++ libraries with VS 2008.  We’ll check again next year.

Comments

Anonymous
This is extraordinary! As per comment your post 2, folder structure.

I am actually moving straight from 2005 to 2010, and had come across just this problem. I hadn't thought it might actually emanate from 2008 in the first place. And this was the only thread I could find covering just this. I am in process of moving the POs one level up…
Anonymous
Your number 2 post regarding folder structure was the first I've seen of its kind. I was particularly confused since each converted solution I tried gave a Parser error. I've been researching this issue for days why our 2005 solutions haven't been converted to 2008 successfully. Thanks so much for posting this info!