I am trying to add my own help file to Visual Studio 2010's Help Library by using WiX to run the HelpLibraryManagerLauncher that the Sandcastle Help File Builder creates after it builds my Sandcastle project.
I am using WiX's QuietExec custom action to run the following command:
HelpLibraryManagerLauncher.exe
/product "VS"
/version "100"
/locale en-us
/silent
/brandingPackage Dev10.mshc
/sourceMedia MyClassLibraryHelp.msha
However, the MSI installer fails with the following:
Action 00:00:00: InstallVS2010Help.
CAQuietExec: Help Library Manager Launcher, version 1.0.0.0
CAQuietExec: Copyright c 2010, Eric Woodruff, All Rights Reserved
CAQuietExec: E-Mail: Eric@EWoodruff.us
CAQuietExec:
CAQuietExec: Running Help Library Manager to perform the requested action. Please wait...
CAQuietExec:
CAQuietExec: ERROR: The requested operation could not be performed.
CAQuietExec: Details: The Help Library Manager returned the exit code 401: The installation of content failed. Detailed information can be found in the event log and in the installation log.
CAQuietExec: Error 0x80070191: Command line returned an error.
CAQuietExec: Error 0x80070191: CAQuietExec Failed
CustomAction InstallVS2010Help returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Checking the EventLog, the following error is recorded:
An error occurred while updating local content: Microsoft.Help.CacheLib.CacheLibUnsignedInstallRefusedException: Exception of type 'Microsoft.Help.CacheLib.CacheLibUnsignedInstallRefusedException' was thrown.
at Microsoft.Help.CacheLib.DocumentationCache.VerifyAndExtractPackages(VendorName vendorName, ChangeDescription change, StatusCallback`1 statusCallback, CertificateCheckCallback certCheckCallback)
at Microsoft.Help.CacheLib.DocumentationCache.IntegrateChange(VendorName vendorName, ChangeDescription change, StatusCallback`1 statusCallback, CertificateCheckCallback certCheckCallback)
at Microsoft.Help.CacheLib.DocumentationCache.Update(VendorName vendorName, Boolean checkForOnlineUpdates, StatusCallback`1 statusCallback, CertificateCheckCallback certCheckCallback)
at Microsoft.Help.CacheLib.CacheManager.<>c__DisplayClass24.<UpdateAsync>b__23()
at Microsoft.Help.CacheLib.AsyncOperationRunner.Run(Object state)
Here is my WiX code:
<CustomAction Id="InstallVS2010Help" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" />
<CustomAction Id="SetPropertiesForInstallVS2010Help"
Property="InstallVS2010Help"
Value=""HelpLibraryManagerLauncher.exe" /product "VS" /version "100" /locale en-us /silent /brandingPackage Dev10.mshc /sourceMedia MyClassLibraryHelp.msha"
Execute="immediate" />
.
.
.
<InstallExecuteSequence>
<Custom Action="SetPropertiesForInstallVS2010Help" Before="InstallInitialize">NOT INSTALLED</Custom>
<Custom Action="InstallVS2010Help" Before="InstallFinalize">(NOT INSTALLED) AND (NOT UPGRADINGPRODUCTCODE) AND (NOT REMOVE="ALL")</Custom>
<InstallExecuteSequence>
If I run the HelpLibraryManagerLauncher
from a command prompt, it says that the operation completed successfully but when I check the Help Library, my help library isn't installed.
If I remove the /silent
switch however, the usual Help Library Manager window pops up and my help library is listed.
Obviously, I want to be able to automatically install my help file from WiX without having to interact with the Help Library Manager's GUI, but I must be missing something. Is it not possible to silently install a help file, either through the command prompt or through WiX? (Uninstalling silently through the command prompt works just fine, though).
The CacheLibUnsignedInstallRefusedException
is also a concern. How do I get WiX (and my MSI) to install my help file even though it isn't signed?
I am using WiX v3.5.2415, Sandcastle v2.610621.1, and Sandcastle Help File Builder v1.9.1.0. The Help 2.0 Compiler and HTML Help Workshop hhc executable that Sandcastle Help File Builder uses are from the Visual Studio 2008 SDK.
Any help would be greatly appreciated.
HelpLibManager.exe does allow silent installation of help collections. However, one of the requirements is that the help collection must be contained in a signed cab file. This means that you cannot use the .mshc file for silent installation.
First thing you need to do is acquire a Code Signing Certificate. If you don't already have one, you can purchase one from VeriSign.
Once you have a code signing certificate, you need to convert your mshc file into a cab file. You can achieve this using the makecab command on the command line.
makecab myhelp.mshc myhelp.cab
Then you need to use your code signing certificate to digitally sign the cab file. You can achieve this by using the signtool command on the command line.
signtool sign /f your-purchased-signing-certificate.pfx /p password /d "My Help Collection" myhelp.cab
Once your .cab file is signed, it can be used in a silent help installation instead of the .mshc file. Be sure to update your msha file to point to the .cab file instead of the .mshc file.
The /brandingPackage switch is not necessary. I also suggest adding the /content switch to your custom action
/content "[CommonAppDataFolder]Microsoft\HelpLibrary"
because a silent help installation will fail if the user has not yet set up the default store for local help collections. This switch gets ignored if the user has already set up his default store, so there is no harm in always using it.
Edit:
This is the wix code I'm using for silent help installations. Note that I'm using full paths to all files.
First, set a property with the path to HelpLibManager.
<SetProperty Id="HELPLIBMANAGER"
Value="[ProgramFilesFolder]Microsoft Help Viewer\v1.0\HelpLibManager.exe"
After="InstallInitialize"/>
Next, declare the custom actions that will use the HELPLIBMANAGER property we just set. Note the use of single quotes (') in the ExeCommand so that we can use double quotes (") to surround the file paths.
<CustomAction Id="InstallHelp"
Directory="YourHelpDir"
ExeCommand='"[HELPLIBMANAGER]" /product VS /version 100 /locale en-us /silent /content "[CommonAppDataFolder]Microsoft\HelpLibrary" /sourceMedia "[#filekey.msha]"'
Execute="deferred"/>
<CustomAction Id="RollbackInstallHelp"
Directory="YourHelpDir"
ExeCommand='"[HELPLIBMANAGER]" /product VS /version 100 /locale en-us /silent /uninstall /vendor "YourVendorName" /productName "YourProductName" /mediaBookList "YourMediaBookList"'
Execute="rollback"/>
Finally, schedule the custom actions:
<Custom Action="RollbackInstallHelp" After="InstallFiles">NOT REMOVE="ALL"</Custom>
<Custom Action="InstallHelp" After="RollbackInstallHelp>NOT REMOVE="ALL"</Custom>
The uninstall actions are pretty much the same and should be fairly easy to figure out. Also be aware that this only works for a 32-bit OS. If you want to also support 64-bit OS, then you're going to need a couple more custom actions to set the correct path to HelpLibManager because the paths are different between 32 and 64 bit OS.
User contributions licensed under CC BY-SA 3.0