Newbie to WiX here... I have created my WiX installer package, and it installs all features correctly. Then I try adding a UI to it with the following:
<UIRef Id="WixUI_Minimal" />
<UIRef Id="WixUI_ErrorProgressText" />
and I link with "light -ext WixUIExtension -cultures:en-us". It finds this extension because it will give an error if I try it with a non-existent name, but the resulting msi package is only 30kb. I assume this should be slightly larger if the UI extension is correctly linked?
When I run the msi, it just gives the normal progress bar and no additional UI that I am expecting from WixUI_Minimal.
All the references seem to claim that a simple UIRef is all you need to get a UI when the package is linked correctly... Is there a known way for the linking to not happen correctly with no errors being thrown (even when I link with -pedantic)?
The MSI may not be significantly larger when you add the UI. There are not many graphics provided by default. However, if you are not seeing UI during the install, that does mean the UI is not being linked in.
The UIRef needs to be in a referenced section. The first section the linker starts with is the Product element. If your UIRef is a child of Product then it will definitely get linked in. The linker then walks through all the references in the Product element (anything that ends in a Ref is a reference as are many other attributes) looking for needed elements in other Fragment elements. The linker then pulls in everything in those Fragment elements. For example:
<Product>
<DirectoryRef Id='TARGETDIR' />
</Product>
<Fragment>
<Directory Id='TARGETDIR' Source='SourceDir' />
<BinaryRef Id='icon' />
<Fragment>
<Fragment>
<Binary Id='icon' Source='path\to\my.ico' />
</Fragment>
<Fragment>
<UIRef Id='WixUI_Minimal' />
</Fragment>
In the above example, the first three sections will be included by the linker. The section with UIRef='WixUI_Minimal' however is left out because nothing references it. To fix it, the UIRef could be moved to any of the other Fragment elements.
To test, try moving your UIRef to your Product element. If that doesn't work, provide more details in your question about where your UIRef is for us to help further.
Related
I've been asked to jump on a project and help build an installer. I'm normally a hardware guy so my coding experience is limited, especially when it comes to this particular instance.
Essentially I have a bunch of components: exe's, dll's, drivers, etc. that I would like to bundle together into one installer to deliver to the client. A coworker suggested using the Wix toolset to do this.
Most of the material I have found has only covered the very basics and it seems like I'm being asked to do something custom and a bit more nuanced. Any help in the form of some guidance on the most efficient/easiest way to do this would be a huge help. A rough outline of what I'll need to do and/or any examples would go a long way.
Thanks!
If you want to send a bundle of files, you can simply mention those specific files in Product.wxs file of wix setup project .
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="abc.exe" Guid="de34d0c6-3b9e-439c-a254-c9f695e2e389">
<File Id="abc.exe" Name="abc.exe" Source="$(var.abc_TargetDir)abc.exe" />
</Component>
<Component Id="abc.exe.config" Guid="3a38ad30-51ce-42fd-b262-1249c7087111">
<File Id="abc.exe.config" Name="abc.exe.config" Source="$(var.abc_TargetDir)abc.exe.config" />
</Component>
</Fragment>
Like the above abc.exe and the .config file, any other file can be sent using the component tag inside the ComponentGroup tag.
I am tasked to build 2 installers based on the same wixlib supplied by 3rd party. Full installer includes all Components, Lite only the core stuff. I assume the wixlib has the following structure:
<Fragment>
<ComponentGroup Id="CoreStuff">
<!-- List of components for this bit, roughly 5MB -->
</ComponentGroup>
</Fragment>
<Fragment>
<ComponentGroup Id="ExtraStuff">
<!-- List of components for this bit, roughly 45MB -->
<ComponentRef Id="BigFile1"/>
</ComponentGroup>
<Component Id="BigFile1">
<File Id="BigFile1_bin" Name="BigFile1.bin"/>
</Component>
</Fragment>
The installer is build in msbuild. The components are included in to the project the following way:
<Feature Id="ThirdPartyStuff">
<ComponentGroupRef Id="CoreStuff"/>
<?if $(var.Configuration) = "Full"?>
<ComponentGroupRef Id="ExtraStuff"/>
<?endif?>
</Feature>
In the end, as expected, I get LGHT0267 error:
error LGHT0267: Found orphaned Component 'BigFile1'. If this is a Product, every Component must have at least one parent Feature. To include a Component in a Module, you must include it directly as a Component element of the Module element or indirectly via ComponentRef, ComponentGroup, or ComponentGroupRef elements.
Have anyone come up with workaround on how to selectively use components provided in wixlib? I could include ExtraStuff as separate Feature for user, but the goal here is to shrink the installer. I could ask politely ThirdParty to provide two separate wixlib's, but I'd like to avoid it.
I don't think that wix has the ability to consume only part of a wixlib package. Think of wixlibs as merge modules (without viewable tables). You can't consume only half of a merge module, and you can't consume only half of a wixlib.
I'm afraid you'll have to ask the third party to break up their wixlib into two packages.
After a struggle I have got the workaround, nasty workaround:
Create dummy wixproject and include wixlib as you would normally do.
Add dummy project as your dependency for final project
In post-build event of dummy project set powershell script to run, which will:
De-compile dummy.msi with binaries output (switch -x) using dark.exe
Craft new.wxs file based on dummy.wxs with inclusion of tags to make the components conditional
Include new.wxs in the final project
My Installer required all the wizard options so I used WixUI_Mondo. That displays all the setup optoins: ( Typical, Custom and Complete ).
As per my requirement the Custom type shouldn't be displayed. By default the package so install under program files.
How can I disable this feature also just would like to display like "C:\Program Files\MyProduct" in the setup type screen?
<Feature Id='MainProgram' Title='Program' Description='The main executable.' Level='1'>
<ComponentRef Id='MainExecutable' />
</Feature>
<UIRef Id="WixUI_Mondo" />
<UIRef Id="WixUI_ErrorProgressText" />
If you don’t want to use Custom Setup, then go for WixUI_InstallDir. It has Install Directories option.
If you want to modify anything in Custom Setup, use Wix Source code. Inside the Source code you can find the UI WXS files in below location.
src\ext\UIExtension\wixlib
Open WixUI_Mondo.WXS file and Copy all coding inside the Fragment and use it in your project. If you modify the Dialog publish sequence you can do anything, (Adding Custom dialog or disabling existing dialog, etc.)
Note: You can download the Source Code from here.
Similiar question: Reusing WIX components to speed up candle/light
My project has the very same problem as the one referenced; a very large static database that never changes is compressed into the msi every time a build is required. I would like to do as the question asks: reuse a pre-compressed cab file to speed up the build time.
I started doing as the answer suggests, using the cabCache property. I added the following to the .wixproj:
<CabinetCachePath>cabs</CabinetCachePath>
<ReuseCabinetCache>True</ReuseCabinetCache>
I then seperated the static data into a fragment:
<Fragmet>
<Media Id="2" Cabinet="static.cab" EmbedCab="no" />
<Component Id="staticCab" Guid="..." >
Files ...
</Component>
And the fragment was referenced in the feature:
<ComponentRef Id="staticCab" />
This created the cab file, but left it empty. My next thought was the use a Merge Module. I created the module:
<Module Id="StaticModule" Language="1033" Version="1.0.0.0" >
<Package ...>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder" Name=".">
<Component Id="StaticFiles" Guid="...">
Files...
</ -- End all XML Tags
And then merged it:
<Directory Id="StaticDir" Name="static">
<Merge Id="StaticModule" Language="1033" src="..\Static\bin\Release\static.msm" />
</Directory>
<Feature ...>
<MergeRef Id="StaticModule"/>
</Feature>
Even after all this, the CabinetCache is still being rebuilt every time.
I guess my question would be what is the correct way to use ReuseCabinetCache. I'm still learning WIX, so I apologize if the answer is evident. I just am not sure how to use it.
Edit: A MergeModule would not be ideal since there is no need to share that logic with other msi's. It is only useful to this single project to a single development team.
I'm going to go ahead and answer my own question since it turned out to be so simple.
Change the .wxiproj to have these properties in
<CabinetCachePath>cabs</CabinetCachePath>
<ReuseCabinetCache>True</ReuseCabinetCache>
Add a media to the .wxs install
<Media Id="2" Cabinet="static.cab" EmbedCab="yes" />
In the Directory tag where you store the static files, add DiskId="2".
This will do a couple of things. First you are telling Wix that you wan't to store the cabinets in a path to reuse the cabinets. Creating a new cabinet and only storing static data in it (or data that doesn't change often) will cause Wix to use the cached version of the cabinet. Wix validates the cabinets by ensuring that:
The number of files in the cached cabinet matches the number of files being built.
The names of the files are all identical.
The order of files is identical.
The timestamps for all files all identical.
(Source: http://wix.sourceforge.net/manual-wix3/optimizing_builds.htm)
No wonder I couldn't find any documentation on it. Its so easy to do it should have been apparent to me.
Update: Also, multiple threads are used to build multiple cabinets. Creating multiple cabinets will improve the speed even more.
I want the installer to skip showing setup type screen (where you can choose Typical, Custom, Complete features), How can I do this?
I provided only one feature set named product.
And I also want the user be able to change the installation directory.
If you only require the user to customize the installation folder, use:
<UIRef Id="WixUI_InstallDir" />
If you don't permit customization of the installation folder, use:
<UIRef Id="WixUI_Minimal" />
Chances are you're using one of the built in libraries that does include the Feature Tree selction, i.e.
WixUI_Mondo
WixUI_FeatureTree
WixUI_Advanced
My application only has a licence screen then installation directory screen, and I use this configuration block to-do it:
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
<UIRef Id="WixUI_InstallDir" />
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
just before the end of my </Product> tag. All the application installs into INSTALLLOCATION in the <Directory> section.
The WixUI dialog library guide might help explain the options