| Index: enterprise/installer/build_enterprise_installer.py
|
| diff --git a/enterprise/installer/build_enterprise_installer.py b/enterprise/installer/build_enterprise_installer.py
|
| deleted file mode 100644
|
| index d09d47d6a6fdb84a6802de58b55586a0182eb40d..0000000000000000000000000000000000000000
|
| --- a/enterprise/installer/build_enterprise_installer.py
|
| +++ /dev/null
|
| @@ -1,530 +0,0 @@
|
| -#!/usr/bin/python2.4
|
| -#
|
| -# Copyright 2009-2010 Google Inc.
|
| -#
|
| -# Licensed under the Apache License, Version 2.0 (the "License");
|
| -# you may not use this file except in compliance with the License.
|
| -# You may obtain a copy of the License at
|
| -#
|
| -# http://www.apache.org/licenses/LICENSE-2.0
|
| -#
|
| -# Unless required by applicable law or agreed to in writing, software
|
| -# distributed under the License is distributed on an "AS IS" BASIS,
|
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -# See the License for the specific language governing permissions and
|
| -# limitations under the License.
|
| -# ========================================================================
|
| -
|
| -"""Build an installer for use in enterprise situations.
|
| -
|
| - This module contains the functionality required to build enterprise
|
| - installers (MSIs) for Omaha's various customers.
|
| -
|
| - The supplied wxs templates need to have an XML extension because SCons
|
| - tries to apply WiX building rules to any input file with the .wxs suffix.
|
| -
|
| - BuildGoogleUpdateFragment(): Build an update fragment into a .wixobj.
|
| - GenerateNameBasedGUID(): Generate a GUID based on the names supplied.
|
| - BuildEnterpriseInstaller(): Build an MSI installer for use in enterprises.
|
| -"""
|
| -
|
| -import binascii
|
| -import md5
|
| -
|
| -_GOOGLE_UPDATE_NAMESPACE_GUID = 'BE19B3E4502845af8B3E67A99FCDCFB1'
|
| -
|
| -
|
| -def BuildGoogleUpdateFragment(env,
|
| - metainstaller_path,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_custom_params,
|
| - wixobj_base_name,
|
| - google_update_wxs_template_path):
|
| - """Build an update fragment into a WiX object.
|
| -
|
| - Takes a supplied wix fragment, and turns it into a .wixobj object for later
|
| - inclusion into an MSI.
|
| -
|
| - Args:
|
| - env: environment to build with
|
| - metainstaller_path: path to the Omaha metainstaller to include
|
| - product_name: name of the product the fragment is being built for
|
| - product_version: product version to be installed
|
| - product_guid: Omaha application ID of the product the fragment is being
|
| - built for
|
| - product_custom_params: custom values to be appended to the Omaha tag
|
| - wixobj_base_name: root of name for the wixobj
|
| - google_update_wxs_template_path: path to the fragment source
|
| -
|
| - Returns:
|
| - Output object for the built wixobj.
|
| -
|
| - Raises:
|
| - Nothing.
|
| - """
|
| -
|
| - product_name_legal_identifier = product_name.replace(' ', '')
|
| -
|
| - intermediate_base_name = wixobj_base_name + '_google_update_fragment'
|
| -
|
| - copy_target = env.Command(
|
| - target=intermediate_base_name + '.wxs',
|
| - source=google_update_wxs_template_path,
|
| - action='@copy /y $SOURCE $TARGET',
|
| - )
|
| -
|
| - wix_defines = [
|
| - '-dProductName="%s"' % product_name,
|
| - '-dProductNameLegalIdentifier="%s"' % product_name_legal_identifier,
|
| - '-dProductVersion=' + product_version,
|
| - '-dProductGuid="%s"' % product_guid,
|
| - '-dProductCustomParams="%s"' % product_custom_params,
|
| - '-dGoogleUpdateMetainstallerPath="%s"' % (
|
| - env.File(metainstaller_path).abspath),
|
| - ]
|
| -
|
| - wixobj_output = env.Command(
|
| - target=intermediate_base_name + '.wixobj',
|
| - source=copy_target,
|
| - action='@candle.exe -nologo -out $TARGET $SOURCE ' + ' '.join(wix_defines)
|
| - )
|
| -
|
| - # Force a rebuild of the .wixobj file when the metainstaller changes.
|
| - # Does not necessarily force rebuild of the MSI because hash does not change.
|
| - env.Depends(wixobj_output, metainstaller_path)
|
| -
|
| - return wixobj_output
|
| -
|
| -
|
| -def _BuildMsiForExe(env,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_installer_path,
|
| - product_installer_install_command,
|
| - product_installer_disable_update_registration_arg,
|
| - product_uninstaller_additional_args,
|
| - msi_base_name,
|
| - google_update_wixobj_output,
|
| - enterprise_installer_dir,
|
| - show_error_action_dll_path,
|
| - metainstaller_path,
|
| - output_dir):
|
| - """Build an MSI installer for use in enterprise situations.
|
| -
|
| - Builds an MSI for the executable installer at product_installer_path using
|
| - the supplied details. Requires an existing Google Update installer fragment
|
| - as well as a path to a custom action DLL containing the logic to launch the
|
| - product's uninstaller.
|
| -
|
| - This is intended to enable enterprise installation scenarios.
|
| -
|
| - Args:
|
| - env: environment to build with
|
| - product_name: name of the product being built
|
| - product_version: product version to be installed
|
| - product_guid: product's Omaha application ID
|
| - product_installer_path: path to specific product installer
|
| - product_installer_install_command: command line args used to run product
|
| - installer in 'install' mode
|
| - product_installer_disable_update_registration_arg: command line args used
|
| - to run product installer in 'do not register' mode
|
| - product_uninstaller_additional_args: extra command line parameters that the
|
| - custom action dll will pass on to the product uninstaller, typically
|
| - you'll want to pass any extra arguments that will force the uninstaller
|
| - to run silently here.
|
| - msi_base_name: root of name for the MSI
|
| - google_update_wixobj_output: the MSI fragment containing the Omaha
|
| - installer.
|
| - enterprise_installer_dir: path to dir which contains
|
| - enterprise_installer.wxs.xml
|
| - show_error_action_dll_path: path to the error display custom action dll that
|
| - exports a ShowInstallerResultUIString method. This CA method will read
|
| - the LastInstallerResultUIString from the product's ClientState key in
|
| - the registry and display the string via MsiProcessMessage.
|
| - metainstaller_path: path to the Omaha metainstaller. Should be same file
|
| - used for google_update_wixobj_output. Used only to force rebuilds.
|
| - output_dir: path to the directory that will contain the resulting MSI
|
| -
|
| - Returns:
|
| - Nothing.
|
| -
|
| - Raises:
|
| - Nothing.
|
| - """
|
| -
|
| - product_name_legal_identifier = product_name.replace(' ', '')
|
| - msi_name = msi_base_name + '.msi'
|
| -
|
| - omaha_installer_namespace = binascii.a2b_hex(_GOOGLE_UPDATE_NAMESPACE_GUID)
|
| -
|
| - # Include the .msi filename in the Product Code generation because "the
|
| - # product code must be changed if... the name of the .msi file has been
|
| - # changed" according to http://msdn.microsoft.com/en-us/library/aa367850.aspx.
|
| - msi_product_id = GenerateNameBasedGUID(
|
| - omaha_installer_namespace,
|
| - 'Product %s %s' % (product_name, msi_base_name)
|
| - )
|
| - msi_upgradecode_guid = GenerateNameBasedGUID(
|
| - omaha_installer_namespace,
|
| - 'Upgrade ' + product_name
|
| - )
|
| -
|
| - copy_target = env.Command(
|
| - target=msi_base_name + '.wxs',
|
| - source=enterprise_installer_dir + '/enterprise_installer.wxs.xml',
|
| - action='@copy /y $SOURCE $TARGET',
|
| - )
|
| -
|
| - # Disable warning LGHT1076 and internal check ICE61 on light.exe. Details:
|
| - # http://blogs.msdn.com/astebner/archive/2007/02/13/building-an-msi-using-wix-v3-0-that-includes-the-vc-8-0-runtime-merge-modules.aspx
|
| - # http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/ICE61-Upgrade-VersionMax-format-is-wrong-td4396813.html # pylint: disable-msg=C6310
|
| - wix_env = env.Clone()
|
| - wix_env.Append(
|
| - WIXCANDLEFLAGS=[
|
| - '-dProductName=' + product_name,
|
| - '-dProductNameLegalIdentifier=' + product_name_legal_identifier,
|
| - '-dProductVersion=' + product_version,
|
| - '-dProductGuid=' + product_guid,
|
| - '-dProductInstallerPath=' + env.File(product_installer_path).abspath,
|
| - '-dProductInstallerInstallCommand=' + (
|
| - product_installer_install_command),
|
| - '-dProductInstallerDisableUpdateRegistrationArg=' + (
|
| - product_installer_disable_update_registration_arg),
|
| - '-dShowErrorCADll=' + env.File(show_error_action_dll_path).abspath,
|
| - '-dProductUninstallerAdditionalArgs=' + (
|
| - product_uninstaller_additional_args),
|
| - '-dMsiProductId=' + msi_product_id,
|
| - '-dMsiUpgradeCode=' + msi_upgradecode_guid,
|
| - ],
|
| - WIXLIGHTFLAGS=[
|
| - '-sw1076',
|
| - '-sice:ICE61',
|
| - ],
|
| - )
|
| -
|
| - wix_output = wix_env.WiX(
|
| - target='unsigned_' + msi_name,
|
| - source=[copy_target, google_update_wixobj_output],
|
| - )
|
| -
|
| - # Force a rebuild when the installer or metainstaller changes.
|
| - # The metainstaller change does not get passed through even though the .wixobj
|
| - # file is rebuilt because the hash of the .wixobj does not change.
|
| - # Also force a dependency on the CA DLL. Otherwise, it might not be built
|
| - # before the MSI.
|
| - wix_env.Depends(wix_output, [product_installer_path,
|
| - metainstaller_path,
|
| - show_error_action_dll_path])
|
| -
|
| - sign_output = wix_env.SignedBinary(
|
| - target=msi_name,
|
| - source=wix_output,
|
| - )
|
| -
|
| - env.Replicate(output_dir, sign_output)
|
| -
|
| -
|
| -def GenerateNameBasedGUID(namespace, name):
|
| - """Generate a GUID based on the names supplied.
|
| -
|
| - Follows a methodology recommended in Section 4.3 of RFC 4122 to generate
|
| - a "name-based UUID," which basically means that you want to control the
|
| - inputs to the GUID so that you can generate the same valid GUID each time
|
| - given the same inputs.
|
| -
|
| - Args:
|
| - namespace: First part of identifier used to generate GUID
|
| - name: Second part of identifier used to generate GUID
|
| -
|
| - Returns:
|
| - String representation of the generated GUID.
|
| -
|
| - Raises:
|
| - Nothing.
|
| - """
|
| -
|
| - # Generate 128 unique bits.
|
| - mymd5 = md5.new()
|
| - mymd5.update(namespace + name)
|
| - md5_hash = mymd5.digest()
|
| -
|
| - # Set various reserved bits to make this a valid GUID.
|
| -
|
| - # "Set the four most significant bits (bits 12 through 15) of the
|
| - # time_hi_and_version field to the appropriate 4-bit version number
|
| - # from Section 4.1.3."
|
| - version = ord(md5_hash[6])
|
| - version = 0x30 | (version & 0x0f)
|
| -
|
| - # "Set the two most significant bits (bits 6 and 7) of the
|
| - # clock_seq_hi_and_reserved to zero and one, respectively."
|
| - clock_seq_hi_and_reserved = ord(md5_hash[8])
|
| - clock_seq_hi_and_reserved = 0x80 | (clock_seq_hi_and_reserved & 0x3f)
|
| -
|
| - return (
|
| - '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % (
|
| - ord(md5_hash[0]), ord(md5_hash[1]), ord(md5_hash[2]),
|
| - ord(md5_hash[3]),
|
| - ord(md5_hash[4]), ord(md5_hash[5]),
|
| - version, ord(md5_hash[7]),
|
| - clock_seq_hi_and_reserved, ord(md5_hash[9]),
|
| - ord(md5_hash[10]), ord(md5_hash[11]), ord(md5_hash[12]),
|
| - ord(md5_hash[13]), ord(md5_hash[14]), ord(md5_hash[15])))
|
| -
|
| -
|
| -def ConvertToMSIVersionNumberIfNeeded(product_version):
|
| - """Change product_version to fit in an MSI version number if needed.
|
| -
|
| - Some products use a 4-field version numbering scheme whereas MSI looks only
|
| - at the first three fields when considering version numbers. Furthermore, MSI
|
| - version fields have documented width restrictions of 8bits.8bits.16bits as
|
| - per http://msdn.microsoft.com/en-us/library/aa370859(VS.85).aspx
|
| -
|
| - As such, the following scheme is used:
|
| -
|
| - Product a.b.c.d -> a.(c>>8).(((c & 0xFF) << 8) + d)
|
| -
|
| - So eg. 6.1.420.8 would become 6.1.41992.
|
| -
|
| - This assumes:
|
| - 1) we don't care about the product minor number, e.g. we will never reset
|
| - the 'c' number after an increase in 'b'.
|
| - 2) 'd' will always be <= 255
|
| - 3) 'c' is <= 65535
|
| -
|
| - As a final note, if product_version is not of the format a.b.c.d then
|
| - this function returns the original product_version value.
|
| - """
|
| -
|
| - try:
|
| - version_field_strings = product_version.split('.')
|
| - (major, minor, build, patch) = [int(x) for x in version_field_strings]
|
| - except:
|
| - # Couldn't parse the version number as a 4-term period-separated number,
|
| - # just return the original string.
|
| - return product_version
|
| -
|
| - # Input version number was out of range. Return the original string.
|
| - if patch > 255 or build > 65535:
|
| - return product_string
|
| -
|
| - msi_major = major
|
| - msi_minor = build >> 8
|
| - msi_build = ((build & 0xff) << 8) + patch
|
| -
|
| - return str(msi_major) + '.' + str(msi_minor) + '.' + str(msi_build)
|
| -
|
| -
|
| -def BuildEnterpriseInstaller(env,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_custom_params,
|
| - product_installer_path,
|
| - product_installer_install_command,
|
| - product_installer_disable_update_registration_arg,
|
| - product_uninstaller_additional_args,
|
| - msi_base_name,
|
| - enterprise_installer_dir,
|
| - show_error_action_dll_path,
|
| - metainstaller_path,
|
| - output_dir='$STAGING_DIR'):
|
| - """Build an installer for use in enterprise situations.
|
| -
|
| - Builds an MSI using the supplied details and binaries. This MSI is
|
| - intended to enable enterprise installation scenarios.
|
| -
|
| - Args:
|
| - env: environment to build with
|
| - product_name: name of the product being built
|
| - product_version: product version to be installed
|
| - product_guid: product's Omaha application ID
|
| - product_custom_params: custom values to be appended to the Omaha tag
|
| - product_installer_path: path to specific product installer
|
| - product_installer_install_command: command line args used to run product
|
| - installer in 'install' mode
|
| - product_installer_disable_update_registration_arg: command line args used
|
| - to run product installer in 'do not register' mode
|
| - product_uninstaller_additional_args: extra command line parameters that the
|
| - custom action dll will pass on to the product uninstaller, typically
|
| - you'll want to pass any extra arguments that will force the uninstaller
|
| - to run silently here.
|
| - msi_base_name: root of name for the MSI
|
| - enterprise_installer_dir: path to dir which contains
|
| - enterprise_installer.wxs.xml
|
| - show_error_action_dll_path: path to the error display custom action dll that
|
| - exports a ShowInstallerResultUIString method. This CA method will read
|
| - the LastInstallerResultUIString from the product's ClientState key in
|
| - the registry and display the string via MsiProcessMessage.
|
| - metainstaller_path: path to the Omaha metainstaller to include
|
| - output_dir: path to the directory that will contain the resulting MSI
|
| -
|
| - Returns:
|
| - Nothing.
|
| -
|
| - Raises:
|
| - Nothing.
|
| - """
|
| - product_version = ConvertToMSIVersionNumberIfNeeded(product_version)
|
| -
|
| - google_update_wixobj_output = BuildGoogleUpdateFragment(
|
| - env,
|
| - metainstaller_path,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_custom_params,
|
| - msi_base_name,
|
| - enterprise_installer_dir + '/google_update_installer_fragment.wxs.xml')
|
| -
|
| - _BuildMsiForExe(
|
| - env,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_installer_path,
|
| - product_installer_install_command,
|
| - product_installer_disable_update_registration_arg,
|
| - product_uninstaller_additional_args,
|
| - msi_base_name,
|
| - google_update_wixobj_output,
|
| - enterprise_installer_dir,
|
| - show_error_action_dll_path,
|
| - metainstaller_path,
|
| - output_dir)
|
| -
|
| -
|
| -def BuildEnterpriseInstallerFromStandaloneInstaller(
|
| - env,
|
| - product_name,
|
| - product_version,
|
| - product_guid,
|
| - product_custom_params,
|
| - product_uninstaller_additional_args,
|
| - product_installer_data,
|
| - standalone_installer_path,
|
| - show_error_action_dll_path,
|
| - msi_base_name,
|
| - enterprise_installer_dir,
|
| - output_dir='$STAGING_DIR'):
|
| - """Build an installer for use in enterprise situations.
|
| -
|
| - Builds an MSI around the supplied standalone installer. This MSI is
|
| - intended to enable enterprise installation scenarios while being as close
|
| - to a normal install as possible. It does not suffer from the separation of
|
| - Omaha and application install like the other methods do.
|
| -
|
| - This method only works for installers that do not use an MSI.
|
| -
|
| - Args:
|
| - env: environment to build with
|
| - product_name: name of the product being built
|
| - product_version: product version to be installed
|
| - product_guid: product's Omaha application ID
|
| - product_custom_params: custom values to be appended to the Omaha tag
|
| - product_uninstaller_additional_args: extra command line parameters that the
|
| - custom action dll will pass on to the product uninstaller, typically
|
| - you'll want to pass any extra arguments that will force the uninstaller
|
| - to run silently here.
|
| - product_installer_data: installer data to be passed to the
|
| - product installer at run time. This is useful as an alternative to
|
| - the product_installer_install_command parameter accepted by
|
| - BuildEnterpriseInstaller() since command line parameters can't be
|
| - passed to the product installer when it is wrapped in a standalone
|
| - installer.
|
| - standalone_installer_path: path to product's standalone installer
|
| - show_error_action_dll_path: path to the error display custom action dll that
|
| - exports a ShowInstallerResultUIString method. This CA method will read
|
| - the LastInstallerResultUIString from the product's ClientState key in
|
| - the registry and display the string via MsiProcessMessage.
|
| - msi_base_name: root of name for the MSI
|
| - enterprise_installer_dir: path to dir which contains
|
| - enterprise_standalone_installer.wxs.xml
|
| - output_dir: path to the directory that will contain the resulting MSI
|
| -
|
| - Returns:
|
| - Target nodes.
|
| -
|
| - Raises:
|
| - Nothing.
|
| - """
|
| - product_name_legal_identifier = product_name.replace(' ', '')
|
| - msi_name = msi_base_name + '.msi'
|
| - product_version = ConvertToMSIVersionNumberIfNeeded(product_version)
|
| -
|
| - omaha_installer_namespace = binascii.a2b_hex(_GOOGLE_UPDATE_NAMESPACE_GUID)
|
| -
|
| - # Include the .msi filename in the Product Code generation because "the
|
| - # product code must be changed if... the name of the .msi file has been
|
| - # changed" according to http://msdn.microsoft.com/en-us/library/aa367850.aspx.
|
| - msi_product_id = GenerateNameBasedGUID(
|
| - omaha_installer_namespace,
|
| - 'Product %s %s' % (product_name, msi_base_name)
|
| - )
|
| - msi_upgradecode_guid = GenerateNameBasedGUID(
|
| - omaha_installer_namespace,
|
| - 'Upgrade ' + product_name
|
| - )
|
| -
|
| - # To allow for multiple versions of the same product to be generated,
|
| - # stick output in a subdirectory.
|
| - output_directory_name = product_guid + '.' + product_version
|
| -
|
| - copy_target = env.Command(
|
| - target=output_directory_name + msi_base_name + '.wxs',
|
| - source=(enterprise_installer_dir +
|
| - '/enterprise_standalone_installer.wxs.xml'),
|
| - action='@copy /y $SOURCE $TARGET',
|
| - )
|
| -
|
| - wix_env = env.Clone()
|
| - wix_candle_flags = [
|
| - '-dProductName=' + product_name,
|
| - '-dProductNameLegalIdentifier=' + product_name_legal_identifier,
|
| - '-dProductVersion=' + product_version,
|
| - '-dProductGuid="%s"' % product_guid,
|
| - '-dProductCustomParams="%s"' % product_custom_params,
|
| - '-dStandaloneInstallerPath=' + (
|
| - env.File(standalone_installer_path).abspath),
|
| - '-dShowErrorCADll=' + env.File(show_error_action_dll_path).abspath,
|
| - '-dProductUninstallerAdditionalArgs=' + (
|
| - product_uninstaller_additional_args),
|
| - '-dMsiProductId=' + msi_product_id,
|
| - '-dMsiUpgradeCode=' + msi_upgradecode_guid,
|
| - ]
|
| -
|
| - if product_installer_data:
|
| - wix_candle_flags.append('-dProductInstallerData=' + product_installer_data)
|
| -
|
| - wix_light_flags = [
|
| - '-sw1076',
|
| - '-sice:ICE61',
|
| - ]
|
| -
|
| - wix_env.Append(
|
| - WIXCANDLEFLAGS=wix_candle_flags,
|
| - WIXLIGHTFLAGS=wix_light_flags
|
| - )
|
| -
|
| - wix_output = wix_env.WiX(
|
| - target = output_directory_name + '/' + 'unsigned_' + msi_name,
|
| - source = [copy_target],
|
| - )
|
| -
|
| - # Force a rebuild when the standalone installer changes.
|
| - # The metainstaller change does not get passed through even though the .wixobj
|
| - # file is rebuilt because the hash of the .wixobj does not change.
|
| - # Also force a dependency on the CA DLL. Otherwise, it might not be built
|
| - # before the MSI.
|
| - wix_env.Depends(wix_output, [standalone_installer_path,
|
| - show_error_action_dll_path])
|
| -
|
| - sign_output = wix_env.SignedBinary(
|
| - target=output_directory_name + '/' + msi_name,
|
| - source=wix_output,
|
| - )
|
| -
|
| - return env.Replicate(output_dir + '/' + output_directory_name, sign_output)
|
|
|