Why you need to take notice of the .APPX installer framework

At Build 2015 in March, Andrew Clinick said: “APPX is now our deployment model. MSI isn’t going to go away, but we want you to move to APPX. We’re investing all of our efforts into making AppX the ultimate installer across the Windows ecosystem.” At build 2015 however Windows Phone was still being discussed along with “Continuum” (the idea that your phone can be a PC in your pocket) and UWP Apps (which only come in APPX format) were important for Windows Phone. Come build 2016, Windows Phone was missing and many people now regard it as dead.

In May we heard about Appinstaller (with Windows 10 Anniversary Update) allowing you to install an .appx file by double clicking on it.

There has been recent news about Desktop Bridge and the Desktop App Converter. This is about making it easy/easier to move/shoehorn existing apps on to the .APPX model (but not making them UWP Apps). This news was fairly low key and I didn’t find the benefit arguments given too compelling for a corporate environment (Live tiles, Notifications, Cortana Integration, Re-installation of your apps after a broken PC), but there are productivity and admin reduction advantages to self-service app-stores, particularly for apps where licensing is not an issue and admin rights are not required.

For Nano Server, the news is that .APPX is the deployment framework and .MSI has been excluded:  See “Installing Windows Server Apps on Nano Server“. So it appears Andrew is still at work and APPX is still considered to have advantages over the .MSI model.

So the underlying message here for us .MSI Packagers is that although things have gone very quiet on Windows Phone and the Windows Store hasn’t taken off yet we are still going to have to take notice of the .APPX format. The good news (announced at the same Desktop Bridge session) is that the format is now supported by both Advanced installer and Installshield.

To throw in a final titbit, did you know that packages created with the Desktop App Converter use the same techniques as App-V and seemingly you can even use the SDK Tool MakeAppX.exe to Pack & Unpack App-V 5.0 Files.


Advanced Installer Evaluation

A few months ago I carried out an evaluation of Advanced Installer from Caphyon in comparison with InstallShield and decided I should share this on my Blog for the benefit of anyone else who may be trying to choose an MSI Packaging tool as I couldn’t find many other people offering reviews:

1.1         General

Advanced Installer uses a similar 3 pane view to Installshield with main areas of functionality listed down the left hand side. This view can be easily customised to only include features you use (e.g. I removed Game explorer). The screenshot view below has been customised to just show the most relevant features. You will notice there is no shortcuts option, shortcuts are found in the relevant folder(s) in the Files & Folders view.


Note: Advanced Installer also includes the ability to create build & edit projects from the command line.

Unusually each and every resource including individual registry values is given it’s own component and the approach to COM data is radically different to Installshild. There is a section in the interface dedicated to COM where the various properties are displayed as fields on a form (with drop down lists where relevant for allowable values), but the COM tables do not get populated in the MSI it produces, except for a single field in the PROGID table.

Limitations: Apart from the minor inconvenience of locating shortcuts manually, the one resource per component approach will impact on performance. e.g. Target registry overhead will be greater and Installs/Uninstalls will be slower on larger packages (I did not have opportunity to run further tests to quantify this).


Normal transform functionality is supported, although support for multiple transforms appears to be limited to during the creation of a response transform, at which point you can specify multiple additional transforms to include. The transform differences are not displayed by default in the table view. I suspect this is for performance reasons.

It is possible to merge a transform into an .MSI via file save as.
A transform can be created from the differences between 2 .MSI files.


  • A nice feature about response transform creation is that on completion you are immediately shown the properties that have been created/set.
  • When transform differences are displayed you have the option to revert any rows to their original setting(s).

Limitations: Cannot display the combined result from multiple transforms. Cannot merge transforms other than during creation of a response transform.

Alternatives: Insted has excellent transform support. Orca is also available.

Custom Actions

Equivalent functionality appears to be available for custom actions although the range of predefined custom action types is greater.


  • A much wider range of pre-defined custom action types is provided, including things like Run Powershell script (for which they have their own launcher .dll), detect service, stop service, detect if a user exists, Test ODBC connection etc.
  • Selecting where in the sequence to run your action has been made more straightforward and a range of predefined conditions can be selected from a list in a condition builder dialog. e.g. AI_DETECTED_JRE_VERSION >= “1.7”, AI_DETECTED_INTERNET_CONNECTION. The “AI_DETECTED” relates to custom Advanced Installer functionality implemented by their own .DLLs.
  • Custom Actions can be copied to another project via copy and paste.

Manipulating the Registry

Each registry key is added to it’s own component by the repackager so there is no concept here of moving registry out of the bucket components into a component associated with the owning file. Import of .REG files is available.

Registry components each have a KeyPath registered that is an offset to another registry component of +37 so component __1012 has a KeyPath of __1049 so all the registry entries appears to be chained together.


  • It isn’t possible to directly export registry keys, although you could work round this by using the MSI diff capability: Generate 2 MSIs, one with the required registry keys deleted and use MSI diff to generatate a transform containing the keys. To get a .REG file out however might require an old copy of InstallShield. NB It should be noted you can copy and paste registry from one project to another. I’m told that adding registry export capability is planned for a new release. (update: export capability has been added in Version 13.3)
  • It isn’t possible to drag n drop registry keys from the registry on the host PC into the package although in my experience this functionality is not typically used by repackagers.
  • Limited use is made of the COM tables with CLASS not being populated at all and a much smaller number of entries in the PROGID table than in a comparison InstallShield capture. I suspect this is related to the Caphyon design choice (as above) of one component for each resource rather than the more common approach of linking a COM .DLL with it’s associated advertising registry in the same component. This generates ICE33 warnings, but ICE33 appears to be considered obsolete by Microsoft https://msdn.microsoft.com/en-us/library/aa368957(v=vs.85).aspx Presumably however this would affect self-repair such that for example if you had a package without an advertised shortcut which was launched via a file type or MIME type association and you were relying on self-repair to create some HKCU registry keys in the logged on user’s profile, this would fail.
  • I could not see an option to extract COM data from a file included in your project. COM registry would normally be captured during repackaging anyway but this is not always the case. Another area where this functionality can be useful, is for identifying which component bucket registry belongs to, but this would appear to be irrelavent with the Advance Installer approach.
  • The way registry entries are chained together led to numerous ICE69 warnings in my test package. Deleting some registry keys to simulate junk cleaning, appeared to confirm this leads to a loss of referential integrity, as you now have component(s) with a missing KeyPath(s).

Alternatives: Wisecomcapture.exe can be used to extract COM registry into a .REG file which could be imported.

Manipulating Files

Text file manipulation is provided in the form of Append/Overwrite and find & replace. Regular expressions can be used for finding text. It is also possible to add variables say to an .INI file and replace these with properties specified at install time. A tick box is provided to enable the existing fle to be backed up before making changes.

Limitations: XML Files can be created but the functionality doesn’t seem to be as rich as Installshield (although I have never used this).


Repackager is incorporated into the main application’s functionality rather than being separate as it is with InstallShield and turn’s the approach to using Virtual Machine’s on it’s head by allowing you to nominate the VM and specific snapshot to be used for the capture and controlling the process externally (a bit like the way AppDNA works) rather than lauching repackaging from within the VM. Exclusions can be configured as part of the process flow before the capture begins. This process I found to be a bit problematic, with VMware, but didn’t have time to explore it fully. I got it to work with a snapshot that was suspended while logged onto the account specified and the network connection set to bridged, but in this configuration you would get a UAC prompt saying that the machine was on a different network – possibly due to the VM being in a workgroup. I did not get it to work fully with any of the other networking options, but didn’t have time to follow up with the vendor.


Hyper-V is an alternative VM option that I didn’t try, but as it is a Type 1 Hypervisor (bare metal) as opposed to Type 2 (Hosted) like VMware workstation I’m not sure if this would work on the same PC or if using Hyper-V with Advanced Installer would require you to connect to a HyperV instance on a server.

There is no separate junk cleaning step at the end of the capture stage as you would have with InstallShield Repackager before generating the .ISM, all editing happens within the main editor. This isn’t really much of a loss, it simplifies the workflow, but does mean you can’t go back to your original capture if you remove something by mistake. Having said this, there appeared to be issues with junk-cleaning registry later in the process, because of the way KeyPaths are allocated – as mentioned in the Registry section above.

One slight issue I experienced at the build stage was an error reporting that it could not find a file from C:\Windows\System32\config – this location is secured so the file could not be copied out & probably shouldn’t have been included anyway.

The capture approach seems to be a combination of single step snapshot & installation monitoring although there is a tick box to disable the latter.


Several times I found that building the resulting project failed because files that should have been excluded could not be located. This could probably be resolved by simply updating the folder exclusions list. On another occasion the build choked on a scheduled task it had captured (throwing an .MSI API error) and I had to exclude it from the project. Note: InstallShield Repackager did not pick up this scheduled task at all.


  • If a default install is required, you can ask Advanced Installer to automate the GUI Accept License agreement, Next, Next etc steps through the installer for you.
  • A “System Noise Recording” can be carried out before the capture begins to help minimise Junk Cleaning. A previously saved “noise” recording can also be used.

System Search

The System Search functionality appears to be broadly similar to InstallShield.

Launch Conditions

Extensive launch condition capability is provided.


Features can be added nested and shared with multiple features. Components are added to a feature via drag & drop.


An advanced condition builder is provided with a wide range of pre-defined conditions available, making the need to remember condition syntax largely a thing of the past.

ICE Validation

ICE Validation is supported as part of the build sequence, but cannot be run on it’s own No .CUB files are included with the software and manual configuration is required to enable this functionality and specify the path to the .CUB file you wish to use. The documentation recommends you install the most recent version of msival2 from the Windows SDK.

New: Probably the most important thing to say about ICE validation is that after the build is completed and the list of errors is displayed, automatic fixes can be applied for many issues on an individual basis or by selecting a group of errors. This is a useful time-saver and eliminates human error.

Note: The actual ICE number is not shown in the list of errors at this point although it is included in a log window during the build.

Alternatives: Both Insted and Orca support ICE validation

Conversion of InstallScript Packages

InstallShield includes additional functionality to support the conversion of InstallScript Packages. This technology would not be available to Caphyon as Installscript comes from the same Flexera stable as InstallShield, but I suspect this functionality is little used anyway.

Scripted install.

Merge Modules

It appears Merge Modules are not supplied out of the box, but can be added from sources such as Visual Studio.  In practice Microsoft appear in recent years to have stepped back from creating new merge modules other than for Visual C++.


After using InstallShield for a long time, Advanced Installer is a breath of fresh air. Although it uses a similar 3 pane layout to InstallShield, it feels much more modern and assumes less background knowledge on the part of the Packager. Some Windows Installer features that are obscure with Installshield (to the point that few would use them) are placed front & centre in Advanced Installer and prompt the user to consider a more advanced approach, implemented with point & click ease.

Caphyon deliver regular updates to the product and the company has a good reputation for support.

Performance in use is excellent and should improve repackaging times, although as noted the one component per resource approach will have some impact on time to install for large packages. Issues that prevent an unreserved recommendation to purchase and that may require further analysis and testing are:

  • The impact of registry KeyPath chaining.
  • The implications of reduced use of the COM tables.
  • The repackaging problems experienced with VMware although it’s possible the Hyper-V option may be a good alternative.

In the final analysis it must be noted that the core InstallShield interface/approach has hardly changed in years and Advanced Installer, despite one or two rough edges achieves the unexpected victory of making InstallShield look something of a dinosaur by comparison.

Note: This review was carried out using version 12.5. Caphyon have made various changes to the product since. I have included a link to the version history below.

Useful Links:

Advanced Installer features by edition
Advanced Installer features
Advanced Installer version history
2015 Review
2013 Short Review

Advanced Installer download page

.OSD Files revert to old versions when APP-V 4.6 sequence is installed via .MSI

Recently I was testing a sequence in standalone mode and needed to link it with another package via DSC. I edited the .OSD files in the normal manner and installed both packages.

To make sure DSC was working I launched a shortcut and opened the App-V client GUI. The parent package was shown as In Use(100%), but the dependency was still listed as Idle(0%), so it was clear that DSC linking was not working.  Next I looked in the OSD Cache “C:\ProgramData\Microsoft\Application Virtualization Client\SoftGrid Client\OSD Cache” and noticed when I opened the .OSD file that it was an old version without the DSC information!

It turns out that App-V stores a copy of the .OSD file(s) in an embedded #Package.cab file (also the .ICO icon files and the .XML Manifest file) and it uses these instead of the one(s) in the folder.  The good news is that this is fairly eady to fix using the free InstEd tool (InstEd download page).

Open the .MSI with Insted, then go to the Media table and right click on the row containing the .CAB file as shown:

Selecting Insted cabinet building options from context menu

The highlighted options for working with cabs are described here.

If you select Show ddf it will give you an indication if it can find the files it needs to do the rebuild –
e.g. “Failed to find file key 00000004.osd at location:
C:\Packages\MyPackage\Package\MyApp 5.3.osd”

I had to create the “Package” folder then copy the files into it from MyPackage. If InstEd can locate all the files it needs to generate the cab, selecting this option shows you the MakeCab Directive file that it will generate. You are now ready to select the Rebuild selected CABs option and complete the fix.

I know APP-V 4.6 and .OSD files are on the way out, but I think they will be with us for a while yet and this technique is useful for any .MSI with an embedded .cab file you wish to update.

Repackaging Quicktime 7.7.5 on Windows 8.1

I would like to share some lessons learnt while packaging Quicktime 7.7.5 under Windows 8.1, hopefully this will save some of you out there going through the same hoops.

So the requirements I want to deal with are:

1. Turn off Content Guide at Startup (We don’t really want our users browsing Movies etc on the Internet right)
2. Turn off Automatic Updates
3. .MOV files should launch with Quicktime not Windows Media Player by default
These defaults should apply to all users on the computer

The first 2 points are easy enough to apply via the UI the first is in Edit, Preferences, Player Preferences and the 2nd is in Quicktime Preferences.

We perform our capture of the changes and find that 2 files have been updated QTPlayerSession.xml and Quicktime.qtp, but hang on a second they are in the user profile. What’s the point in disabling automatic updates if you only disable them for 1 user that should be a per machine setting right, OK at home you might want the Content Guide setting to be individual but here we want it set as a default.

So applying Windows standards we move the files to the equivalent ProgramData folder to apply to all users, but Quicktime ignores them here…

The Answer (and another problem)

It turns out that the installer has a custom action AddQTPFileUserProfile that contains a script to copy both files from ProgramData\Apple Computer\Quicktime to the user profile, so we add our 2 captured files to the package in this location. We then test our application as an ordinary user and find our 2nd Gotcha – none of our settings have been applied! What happened, well the custom action copied the files to the user profile of the Admin account you installed under during the install, but there doesn’t seem to be any Self Repair or Active Setup mechanism in the package to deal with these for any new user that logs onto the PC.

The shortcut is advertised but as far as Windows Installer knows, nothing is missing from the user profile and repair does not run. Also because Apple have not followed .MSI standards which expect you to author the filetypes into the correct tables rather than just using the registry table, self-repair is not active when launched say by clicking on a .mov file and how many people launch Quicktime Player from the shortcut…?

So we need to add Active Setup to the package,this triggers a repair & Apple’s custom action copies the files from ProgramData. NB Active Setup ran silently & at first I thought it had failed, but when I checked the files had been copied to the user profile. Be aware also that in a 64bit environment the Active Setup keys get created under WOW6432Node.

.MOV File Type Association in Windows 8.1

Now to dealing with our 3rd requirement. If you check the registry for .MOV under HKCR you will find that the default is set as “QuickTime.mov” so everything seems fine, or maybe not.

When you try to open a .MOV file you get the following prompt:


It seems like Windows wants to remind you that you can now open .mov files with Windows Media Player and is saying are you sure? My personal experience is that WMP fails to work with .mov files from my old camera, I get a message “Windows Media Player cannot play the file” the message also suggests it might not support the codec used (I believe more recent .mov files use a different codec).

If you choose QuickTime at this point the file association is completed and the icon on .mov files changes to a QuickTime icon. This isn’t the turnkey behaviour we want in our package however

It turns out Microsoft have made some big changes in this area – see this Technet Blog One advantage of these changes on a shared PC seems to be that different users could have different preferences for their file extensions. In a home environment for example there could be different preferences for .jpg files.

So far I have not managed to find a way round this and from a Packager’s perspective it seems to be one more reason to avoid Windows 8, but please submit a comment if you know better.


Installing .NET Assemblies

This seems to be a very poorly documented area so here are my gleanings on the subject:

Loading files into the Global Assembly Cache

The Global Assembly Cache or GAC is a machine-wide .NET assemblies cache for Microsoft’s CLR platform. The approach of having a specially controlled central repository addresses the shared library concept and helps to avoid pitfalls of other solutions that lead to drawbacks like DLL Hell. It is located at C:\Windows\Assembly.

To manually add a file to the Global Assembly cache the following command can be used:

gacutil.exe /i xyz.dll

NB the Adminstudio Helpfile comments: “Do not call the Global Assembly Cache tool (Gacutill.exe) from a custom action. This tool was not designed to be used during installations.”

Assemblies placed in the GAC Must have a strong name (digital signature). Errors will be listed during build if this is not the case and any attempt to install the resulting .msi will result in a rollback.

In Installshield an assembly is added to the cache via the following process:

Open your Project in Editor & do the following:

1. Go to Files & Folders under Application Data and select the [GlobalAssemblyCache] folder from the Pre-defined folder list
2. Add your .Net Assembly under this folder
3. Behind the scenes, the appropriate component will be created with the attributes set
4. When you build your project, Editor will extract Assembly information and populate the MsiAssembly and MsiAssemblyName tables. Amongst other things, this allows a database like transactional process for committing assemblies to the GAC, and hence proper rollback. It also allows proper file costing of .NET assemblies to occur.

Example Installshield .NET Assembly Component

Note the .NET Scan at build value is set to “Dependancies and Properties”. This should be changed to “Properties Only“. Any Dependancies, such as merge modules should have already been identified and catered for. This is the setting that populates the MsiAssembly andf MsiAssemblyName tables. NB The default can also be changed to “Properties Only” in Tools, Options, on the .NET tab.

Assemblies that are not placed in the GAC are known as Private assemblies.

Note: Dragging & dropping files into the GAC also appears to work.

Registering Assemblies

.NET assemblies do not typically use the registry as the the design goal is that they should be installable by the good old DOS method of just copying the files (presumably to compete with Java which does not use the registry). If the aplication needs to interoperate with COM however, the regasm command can be used used to register an assembly and this is very similar to using regsvr32 for ordinary .DLLs:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe  “C:\program files\Hummingbird\RBSCustom\Shared\Rbs.Gbm.Dms.EventSink.dll” /codebase

To unregister add -u parameter:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe  “C:\program files\Hummingbird\RBSCustom\Shared\Rbs.Gbm.Dms.EventSink.dll” /codebase -u

The following Regasm example also involves a .tlb file. If the .dll has been correctly written the .tlb should get

generated automatically by setting .NET COM Interop to Yes as above. Often however this doesn’t work and the .tlb has to be added manually. Note for package reworks where the .dll has been updated, the .tlb should match the .dll and not be from the earlier version of the .dll – the above regasm command can be used to generate the .tlb if you are unsure and you can then compare it with the .tlb present in the package. You may also find a version number in the .tlb if you open it in Notepad, that should match the .dll version.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm” HdAnswerSource.dll /tlb:HdAnswerSource.tlb /codebase

In Installshield, Regasm functionality is replaced with setting the .NET COM Interop property for the component to Yes (shown as No in the screenshot above as No is more common) this causes the relevant COM registry entries to be generated at build time and placed in the .msi. A .reg file is also created in the source folder containing the same COM entries. If you have performed a capture, you will probably already have the associated registry entires in your Registry bucket component and the .reg file can be useful for identifying these. NB: the .reg file may contain some Codebase keys that point at hardcoded file locations in your source, but using .NET COM Interop results in the correct path being recorded in the .msi registry entries generated at build time. It does this by changing the path to a variable based on the destination of the component. One slight anomaly resulting from this is that the variable uses backslashes, whereas native Codebase entries use forward slashes. I have not as yet found this to be an issue.


The /codebase parameter in the example regasm command above, adds entries to the registry under the relevant Clsid, pointing to the source location of the assembly. This is for information purposes only and in .msi terms, is only valid for private assemblies. Shared assemblies are loaded directly into the GAC by the .msi and therefore /codebase does not apply. The .reg file mentioned above (generated as a result of Setting .NET COM Interop for the component to yes) will not contain a codebase entry if you have specified that it is being installed to [GlobalAssemblyCache]. If it is a private assembly however (placed under your Installdir rather than in the GAC), the Codebase entry will be generated.

Note: using gacutil to load an assembly to the GAC also results in a Codebase entry, as there is a source location for the file at the time when gacutil is run.

“Assembly”=”Hummingbird.DM.Extensions.Forms.LocationSave, Version=, Culture=neutral, PublicKeyToken=null”
“CodeBase”=”file:///C:/Program Files/Hummingbird/DM Extensions/Hummingbird.DM.Extensions.Forms.LocationSave.dll”

“Assembly”=”Hummingbird.DM.Extensions.Forms.LocationSave, Version=, Culture=neutral, PublicKeyToken=null”
“CodeBase”=”file:///C:/Program Files/Hummingbird/DM Extensions/Hummingbird.DM.Extensions.Forms.LocationSave.dll”

Since writing this I have found some assemblies loaded into the GAC that also had Codebase entries pointing at the GAC.

Identifying Assemblies

Where COM Interop is being used an Assembly can be identified by an Assembly value Under the InprocServer32 entry in the registry. Assemblies can also often be identified by looking at the Version tab under properties for the file and the Language is shown as Language Neutral.  Another approach is to open the file in notepad, sroll to the end and look for the word A s s e m b l y. In Dependancy Walker the .dll will show a dependency on MSCOREE.DLL.

Guidelines from the Windows Installer SDK

  • A Windows Installer component should contain no more than one assembly.
  • All of the files in the assembly should be in a single component.
  • Each component that contains an assembly should have an entry in the MsiAssembly table.
  • The strong assembly cache name of each assembly should be authored into the MsiAssemblyName table.
  • Use the Registry table instead of the Class table when you register COM Interop for an assembly.
  • Assemblies that have the same strong name are the same assembly. When the same assembly is installed by different applications, the components that contain the assembly should use the same value for the ComponentId in their Component tables.
  • The KeyPath value in the Component table for a component that contains the assembly should not be Null.

Error Knowledgebase:

When you build the .msi, you may get the following error shown in the tasks tab in the “Output Window” pane at the bottom of the editor screen :

ISDEV : error -6210: An error occurred building COM .NET Interop information for Component rbs.gbm.dms.eventsink.dll

This may well be because it was not possible to resolve a dependancy. Switch to the build tab and you will find the output of the regasm command:

e.g. RegAsm : error RA0000 : Could not load file or assembly ‘Hummingbird.DM.Extensions.Interop.VBFORMS, Version=, Culture=neutral, PublicKeyToken=fcfae4436272f66a’ or one of its dependencies. The system cannot find the file specified.

In this instance the dependancy was Hummingbird.DM.Extensions.Interop.VBFORMS.dll. If this is being installed by your package, place a copy of the file in the same folder as the assembly you are registering. If you get another error -6120 go through the same process and see if this time a different file is required.

When all the dependancies are found the error will go away and the relevant COM registry will be added to the .msi.



Sometimes when working interactively Windows may prevent you from deleting files from the GAC. Try the following:
Back up [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Assemblies\Global] to a .reg file, then delete this key. Delete the assembly(s) from the GAC, reinstate the reg file (edit first if necessary).

After you have installed the .NET Framework, the .NET Framework Optimisation Service will run to precompile .NET assemblies in the background. Typically it will be done with the high priority assemblies in 5-10 minutes, and wait until your PC is idle to process the rest. This may corrupt your capture, so you might want to disable the service temporarily (I haven’t tried this), or leave the PC for long enough till it is finished



Troubleshooting .NET Assembly Installation Issues