Install

Contents

  1. 1 Q:  How do I create a Windows Firewall rule at install time?
  2. 2 Q:  How do I remove a Windows Firewall rule at uninstall time?
  3. 3 Q:  How do I generate native machine images of my C# application at install time (ngen)?
  4. 4 Q:  How do I run a program using JavaScript?
  5. 5 Q:  How do I start a service using JavaScript?
  6. 6 Q:  My WIX installs breaks with an error claiming a NET assembly does not have a strong name.  Why does it need a strong name?
  7. 7 Q:  In WIX, I have a custom action DLL that does not work if the NET 4.0 framework is the only framework installed.  However, I have enabled useLegacyV2RuntimeActivationPolicy in the .config file.  How do I fix this?
  8. 8 Q:  In WIX, I get LGHT0094 Unresolved reference to symbol 'Property:ApplicationFolderName' in section 'Fragment' after sequencing a custom action into the UI sequence.  How do I fix this?
  9. 9 Q: If an InstallShield 2014 install fails at or before LaunchConditions and the View Readme box is checked at the final screen, I get a "Error 2732. Directory Manager not initialized."  This does not occur if there are no errors, or if they occur later on.
  10. 10 Q:  How do I disable the Cancel button in an MSI Uninstall?
  11. 11 Q:  Advanced installer fails to build in Visual Studio, reporting an exit code of 536805277.  How do I fix this?
  12. 12 Q:  In PowerShell, how do I set an MSI property?
  13. 13 Q:  In an MSI custom action, GetVersionInfo returns the wrong version, such as 0x0602 on Windows 10 or 0x0600 on Vista.  How do I fix this?
  14. 14 Q:  How do I relicense InstallShield Standalone Build after installation?
  15. 15 Q:  On Windows 10, InstallShield 2014 restarts the computer when it performs COM Extract during a command line build.  How do I fix this?
  16. 16 Q:  How do I get logs from the InstallShield setup.exe bootstrapper?
  17. 17 Q:  In MSI, I added a property to MsiHiddenProperties, but it's value is still logged out when a deferred custom action is called in the Target line.  How do I fix this?
  18. 18 Q:  InstallShield is missing some of my COM Extract registry values.  They are written out to the registry and COM Extract is running, but they are not in the Registry table.  How do I fix this?
  19. 19 Q:  Can I use JavaScript/VBScript in an MSI custom action to write out a file from the binary table?
  20. 20 Q:  How do I enumerate subkeys of a registry key in JavaScript?
  21. 21 Q:  How do I access the 64-bit registry from a JavaScript MSI custom action?


Q:  How do I create a Windows Firewall rule at install time?

A:  Use a script like this.

Q:  How do I remove a Windows Firewall rule at uninstall time?

A:  Use a script like this.

Q:  How do I generate native machine images of my C# application at install time (ngen)?

A:  Use a script like this.

Q:  How do I run a program using JavaScript?

A:  Use a script like this.

Q:  How do I start a service using JavaScript?

A:  Use a script like this.

Q:  My WIX installs breaks with an error claiming a NET assembly does not have a strong name.  Why does it need a strong name?

A:  In WIX, the File element has an attribute named "Assembly" that, if set to .net, overrides the target directory and instead installs the assembly to the GAC.  This attribute should ONLY be set on assemblies that need to be installed to the GAC.  To fix the error, either change the attribute value or sign the assembly.  Courtesy, indirectly, this blog posting.

Q:  In WIX, I have a custom action DLL that does not work if the NET 4.0 framework is the only framework installed.  However, I have enabled useLegacyV2RuntimeActivationPolicy in the .config file.  How do I fix this?

A:  Rename the .config file to "CustomAction.config".  The runtime environment of a NET component is actually determined by the host loading it.  WIX has implemented special support to recognize the config of DLL and use it, but it must be named exactly CustomAction.config or this doesn't work.

Q:  In WIX, I get LGHT0094 Unresolved reference to symbol 'Property:ApplicationFolderName' in section 'Fragment' after sequencing a custom action into the UI sequence.  How do I fix this?

A:  The Before/After attribute of the Custom element is referencing something that does not exist, such as a dialog name.  Remove this clause and rebuild.

Q: If an InstallShield 2014 install fails at or before LaunchConditions and the View Readme box is checked at the final screen, I get a "Error 2732. Directory Manager not initialized."  This does not occur if there are no errors, or if they occur later on.

A:  This is due to a bug in InstallShield's implementation.  The viewer custom action relies on the directory table initialization, which does not occur until CostInitialize.  To fix this:
  1. Open the install in InstallShield and goto the Direct editor.
  2. In the custom action table, change the type of ShowMsiLog to 242.
  3. Change the Source field of the ShowMsiLog custom action to a new property name - for example, ShowMsiLogViewer.
  4. Return to the normal InstallShield custom action editor and create a new set property (type 51) CA, called for example ShowMsiLogViewer_SetProp, that sets the property specified in step 3 equal to "[SystemFolder]\notepad.exe".
  5. In the UI sequence view, sequence the new CA created in step 4 in just before LaunchConditions.

Q:  How do I disable the Cancel button in an MSI Uninstall?

A:  Write a custom action that sends a special message and sequence it into the Execute sequence, not UI.  This will disable the cancel button AFTER MSI has finished initializing - after it enters the transacted sequence - so users will still see an active Cancel button briefly during initialization.  Source this article.  Use code like this.
function Dag_DisableCancelButton()
{
    var logRecord = Session.Installer.CreateRecord(2);
    logRecord.IntegerData(1) = 2;
    logRecord.IntegerData(2) = 0;
    Session.Message(Session_Message_Type_CommonData, logRecord)
}

Q:  Advanced installer fails to build in Visual Studio, reporting an exit code of 536805277.  How do I fix this?

A:  Open the Project outside of Visual Studio, click Product Details|Control Panel Icon, reselect the icon, then select File|Save.  Courtesy this page.

Q:  In PowerShell, how do I set an MSI property?

A:  You can't.  The MSI provider for PowerShell is very limited.  Use a VBScript/JavaScript/C++ custom action instead, running PowerShell from it to perform the PowerShell logic if needed. Courtesy this link.

Q:  In an MSI custom action, GetVersionInfo returns the wrong version, such as 0x0602 on Windows 10 or 0x0600 on Vista.  How do I fix this?

A:  This was an intentional change Microsoft made at Windows 7 to improve application compatibility, by extending pre-existing "version lie" functionality to msiexec.  There is no fix.  To workaround this, either use the VersionNT property in MSI, or repackage your executable code so it is an EXE with a proper manifest, which will avoid this problem.  For example, if this is code in DllRegisterServer, do manual COM registration/unregistration instead via regsvr32.  Courtesy this MSDN link.

Q:  How do I relicense InstallShield Standalone Build after installation?

A:  Follow these steps:
  1. Get the MAC address and hostname of the machine.
  2. Login to the Flexera license provisioning website and generate a license, using the MAC and hostname from step 1.
  3. Click Save All to save the license to a file.  If this is the second time generating a license for this MAC, the license will list both products separately.
  4. Copy the LIC file to license.lic in the System subdirectory of InstallShield Standalone.

Q:  On Windows 10, InstallShield 2014 restarts the computer when it performs COM Extract during a command line build.  How do I fix this?

A:  InstallShield 2014 is officially not compatible with Windows 10.  In particular, the kernel driver used for COM Extract is incompatible with Windows 10.  To workaround this, set HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\InstallShield\RegSpy\UseAPIRegistryHooks equal to 1 or 0.  Value 1 uses registry redirection, and value 0 uses an older API hooking method that probably won't work.  Value 2 is the default kernel driver method.  Note this will affect all versions of InstallShield on the machine.  Flexera has a good though somewhat buried article on their COM Extract technologies here.

Q:  How do I get logs from the InstallShield setup.exe bootstrapper?

A:  Run it with /debuglog.  The bootstrapper logs to "%TEMP%\InstallShield.txt".

Q:  In MSI, I added a property to MsiHiddenProperties, but it's value is still logged out when a deferred custom action is called in the Target line.  How do I fix this?

A:  Edit the custom action type and add the poorly documented msidbCustomActionTypeHideTarget flag, value 0x2000.  That will suppress logging of Target unless MisLogging has the debug flag set.  There is no absolute way to suppress the logging.

Q:  InstallShield is missing some of my COM Extract registry values.  They are written out to the registry and COM Extract is running, but they are not in the Registry table.  How do I fix this?

A:  The COM Extract process ISRegSpy only logs entries that are written if they do not already exist.  Modify your install build script to unregister the problematic objects before calling InstallShield.  Note for .NET, if an assembly has a type library, it will not be unregistered unless /tlb is specified on the regasm command line.


Q:  Can I use JavaScript/VBScript in an MSI custom action to write out a file from the binary table?

A:  Not reliably.  The FileSystemObject's methods are specifically designed for text files and will fail in DBCS locales with certain binary strings.  Write a C++ or NET EXE custom action instead.  See this MSDN blog.


Q:  How do I enumerate subkeys of a registry key in JavaScript?

A:  Use the StdRegProv WMI provider, but the EnumKeys method can't be called directly due to language limitations.  Instead, use WMI's indirect method invocation to execute the method.  However, note that when run inside an MSI, this will access the 32-bit registry.  Sources:  MSDN WMI Sample, this page citing the problem.
function EnumerateSubkeys( rootHiveCode, subkeyPath )
{
    // The EnumKey method cannot be called directly from JavaScript because the keys out parameter is not supported.
    // Instead, the method is called with WMI's equivalent of reflection.
    var wmiRegistryProvider = GetObject("winmgmts:\\\\.\\root\\default:StdRegProv");
    method = wmiRegistryProvider.Methods_.Item("EnumKey");
    var inParams = method.InParameters.SpawnInstance_();
    inParams.hDefKey = rootHiveCode;
    inParams.sSubKeyName = subkeyPath;
    var outParams = wmiRegistryProvider.ExecMethod_(method.Name, inParams);
    return outParams.sNames.toArray();
}

Q:  How do I access the 64-bit registry from a JavaScript MSI custom action?

A:  Create a WbemScripting.SWbemNamedValueSet object to specify the context as 64-bit, then pass this to a WbemScripting.SWbemLocator in ConnectServer and invoke the method via WMI reflection.  For example:
// Determines if the specified registry key exists
// regType  - optional, 32 or 64 to specify the 32-bit or 64-bit registry.  Default 64.
// valueName - optional, if unspecified uses default value
function Registry_KeyExists( rootHiveCode, keyPath, valueName, regType )
{
    if (regType == undefined)
        regType = 64;
    if ((valueName == undefined) || (StringIsNullOrEmpty(valueName)))
        valueName = "";
 
    var wmiContext = new ActiveXObject("WbemScripting.SWbemNamedValueSet");
    wmiContext.Add("__ProviderArchitecture", regType);
 
    var wmiFactory              = new ActiveXObject("WbemScripting.SWbemLocator");
    var wmiServer               = wmiFactory.ConnectServer("", "root\\default", "", "", "", "", 0, wmiContext);
    var wmiRegistryProvider     = wmiServer.Get("StdRegProv");
    var valueExists             = false;
 
    var methodInvocationInfo          = wmiRegistryProvider.Methods_("CheckAccess").Inparameters;
    methodInvocationInfo.hDefkey      = rootHiveCode;
    methodInvocationInfo.sSubkeyname  = keyPath;
    methodInvocationInfo.uRequired    = 1;
 
    try
    {
        var methodResult = wmiRegistryProvider.ExecMethod_("CheckAccess", methodInvocationInfo, 0, wmiContext);
        valueExists = methodResult.bGranted;
    }
    catch (ignoredException)
    {
        // Ignore
    }
    return valueExists;
}
Source:  here, among others.