Documentation ¶
Overview ¶
Package wix is a lightweight wrapper around the wix tooolset.
It is heavily inspired by golang's build system (2)
Background and Theory Of Operations ¶
wix's toolchain is based around compiling xml files into installers. Wix provides a variety of tools that can help simply this. This package leverages them.
The basic steps of making a package:
- Start with a xml file (TODO: consider a struct?)
- Create a packageRoot directory structure
- Use `heat` to harvest the file list from the packageRoot
- Use `candle` to take the wxs from (1) and (3) and make a wixobj
- Use `light` to compile thje wixobj into an msi
While this is a somewhat agnostic wrapper, it does make several assumptions about the underlying process. It is not meant as a complete wix wrapper.
So Many Guids ¶
Windows uses guids to identify how MSIs related to one another. Windows defines three codes:
- UpgradeCode: Consistent for all releases of a product -- guid(name, identifier)
- ProductCode: Identifies a product release -- guid(name, identifier, hostname, version)
- PackageCode: Identifiers a MSI package itself -- guid(name, identifier, hostname, version)
For a given input, we need a stable guid. Convinently, md5 produces a string of the correct length for these guids.
Note: MSIs can get quiet unhappy if they PackageCode changes, while the ProductCode remains the same. That will result in an error about "Another version of this product is already installed"
References
- http://wixtoolset.org/
- https://github.com/golang/build/blob/790500f5933191797a6638a27127be424f6ae2c2/cmd/release/releaselet.go#L224
- https://blogs.msdn.microsoft.com/pusu/2009/06/10/what-are-upgrade-product-and-package-codes-used-for/
- https://docs.microsoft.com/en-us/windows/desktop/Msi/preparing-an-application-for-future-major-upgrades
- https://docs.microsoft.com/en-us/windows/desktop/Msi/productcode
Index ¶
Constants ¶
const ( ErrorControlIgnore ErrorControlType = "ignore" ErrorControlNormal = "normal" ErrorControlCritical = "critical" )
const ( StartAuto StartType = "auto" StartDemand = "demand" StartDisabled = "disabled" StartBoot = "boot" StartSystem = "system" )
const ( InstallUninstallInstall InstallUninstallType = "install" InstallUninstallUninstall = "uninstall" InstallUninstallBoth = "both" )
Variables ¶
This section is empty.
Functions ¶
Types ¶
type ErrorControlType ¶
type ErrorControlType string
type InstallUninstallType ¶
type InstallUninstallType string
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service represents a wix service. It provides an interface to both ServiceInstall and ServiceControl.
func NewService ¶
func NewService(matchString string, opts ...ServiceOpt) *Service
New returns a service
type ServiceConfig ¶
type ServiceConfig struct { XMLName xml.Name `xml:"http://schemas.microsoft.com/wix/UtilExtension ServiceConfig"` FirstFailureActionType string `xml:",attr,omitempty"` SecondFailureActionType string `xml:",attr,omitempty"` ThirdFailureActionType string `xml:",attr,omitempty"` RestartServiceDelayInSeconds int `xml:",attr,omitempty"` ResetPeriodInDays int `xml:",attr,omitempty"` }
ServiceConfig implements http://wixtoolset.org/documentation/manual/v3/xsd/util/serviceconfig.html This is used to set FailureActions. There are some limitations. Notably, reset period is in days here, though the underlying `sc.exe` command supports seconds. (See https://github.com/wixtoolset/issues/issues/5963)
Docs are a bit confusing. This schema is supported, and should work. The non-util ServiceConfig generates unsupported CNDL1150 errors.
type ServiceControl ¶
type ServiceControl struct { Name string `xml:",attr,omitempty"` Id string `xml:",attr,omitempty"` Remove InstallUninstallType `xml:",attr,omitempty"` Start InstallUninstallType `xml:",attr,omitempty"` Stop InstallUninstallType `xml:",attr,omitempty"` Wait YesNoType `xml:",attr,omitempty"` }
ServiceControl implements http://wixtoolset.org/documentation/manual/v3/xsd/wix/servicecontrol.html
type ServiceInstall ¶
type ServiceInstall struct { Account string `xml:",attr,omitempty"` Arguments string `xml:",attr,omitempty"` Description string `xml:",attr,omitempty"` DisplayName string `xml:",attr,omitempty"` EraseDescription bool `xml:",attr,omitempty"` ErrorControl ErrorControlType `xml:",attr,omitempty"` Id string `xml:",attr,omitempty"` Interactive YesNoType `xml:",attr,omitempty"` LoadOrderGroup string `xml:",attr,omitempty"` Name string `xml:",attr,omitempty"` Password string `xml:",attr,omitempty"` Start StartType `xml:",attr,omitempty"` Type string `xml:",attr,omitempty"` Vital YesNoType `xml:",attr,omitempty"` // The overall install should fail if this service fails to install ServiceConfig *ServiceConfig `xml:",omitempty"` }
ServiceInstall implements http://wixtoolset.org/documentation/manual/v3/xsd/wix/serviceinstall.html
type ServiceOpt ¶
type ServiceOpt func(*Service)
func ServiceArgs ¶
func ServiceArgs(args []string) ServiceOpt
ServiceArgs takes an array of args, wraps them in spaces, then joins them into a string. Handling spaces in the arguments is a bit gnarly. Some parts of windows use ` as an escape character, but that doesn't seem to work here. However, we can use double quotes to wrap the whole string. But, in xml quotes are _always_ transmitted as html entities -- " or ". Luckily, wix seems fine with that. It converts them back to double quotes when it makes the service
func ServiceDescription ¶
func ServiceDescription(desc string) ServiceOpt
func ServiceName ¶
func ServiceName(name string) ServiceOpt
type WixOpt ¶
type WixOpt func(*wixTool)
func SkipValidation ¶
func SkipValidation() WixOpt
If you're running this in a virtual win environment, you probably need to skip validation. LGHT0216 is a common error.
func WithBuildDir ¶
func WithDocker ¶
func WithService ¶
type YesNoType ¶
type YesNoType string
http://wixtoolset.org/documentation/manual/v3/xsd/wix/serviceinstall.html http://wixtoolset.org/documentation/manual/v3/xsd/wix/servicecontrol.html https://helgeklein.com/blog/2014/09/real-world-example-wix-msi-application-installer/
const ( Yes YesNoType = "yes" No = "no" )