Showing posts with label deployment. Show all posts
Showing posts with label deployment. Show all posts

Tuesday, 1 May 2012

Burn UI Customisations

I have written a couple of WiX burn UI customisations and thought they were worth sharing. They are both based on the standard WiX burn templates and can be easily implemented as mentioned in my previous post http://neilsleightholm.blogspot.co.uk/2012/05/wix-burn-tipstricks.html.

HyperlinkLicense

I changed this to include the following features:
  1. Resized to match standard WiX UIs.
  2. Add welcome text
  3. Display version number.
image

The relevant bits of code to do this is shown below, all other code it the same as the standard UI:

<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
    <Window Width="500" Height="390" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>


    <Page Name="Install">
        <Text X="11" Y="80" Width="-11" Height="30" FontId="2">#(loc.InstallHeader)</Text>
        <Text X="11" Y="121" Width="-11" Height="-129" FontId="3">#(loc.InstallMessage)</Text>
        <Hypertext Name="EulaHyperlink" X="11" Y="-107" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallLicenseLinkText)</Hypertext>
        <Text X="11" Y="-73" Width="246" Height="17" FontId="3">#(loc.InstallVersion)</Text>
        <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
        <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>
        <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
        <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
    </Page>

This also requires the addition of a few items in the HyperlinkTheme.wxl file:

  <String Id="InstallHeader">Welcome</String>
  <String Id="InstallMessage">Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit.</String>
  <String Id="InstallVersion">Version [WixBundleVersion]</String>

RtfLicense

I changed this to include the following features:
  1. Resized to match standard WiX UIs.
  2. Change odd looking 3D outline to a single line.
image

The relevant bits of code to do this is shown below, all other code it the same as the standard UI:

    <Page Name="Install">
        <Text X="11" Y="80" Width="-11" Height="-70" TabStop="no" FontId="2" HexStyle="0x800000" />
        <Richedit Name="EulaRichedit" X="12" Y="81" Width="-12" Height="-71" TabStop="yes" FontId="0" />
        <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
        <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>
        <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
        <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
    </Page>

WiX Burn – tips/tricks

This post outlines some of the things I have found out since working with the new Burn code, unless otherwise stated this refers to version 3.6.2830.0 or later. For my requirements I have only needed to create single file installation setups, so none of these examples will include download code. I keep the source to resources in a folder called “Resource” so in the examples below "Resource\" is a reference to this folder.

In many cases this information has been gleaned from the WiX Users mail list. If you spot any errors or can suggest improvements please let me know.

Basic Template

This is my outline framework that I have been using to create a burn project:
<?xml version="1.0" encoding="utf-8"?>

<?ifndef Version?>
<?define Version = "1.0.0.0" ?>
<?endif ?>

<Wix RequiredVersion="3.6.2830.0" xmlns="http://schemas.microsoft.com/wix/2006/wi
"
     xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
  <Bundle Name="My Application" Version="$(var.Version)" Manufacturer="ACME" UpgradeCode="PUT-GUID-HERE
"
    HelpUrl="http://www.nowhere.com
"
    Copyright="Copyright© 2012, ACME" IconSourceFile="Resource\Setup.ico
"
    SplashScreenSourceFile="Resource\SplashScreen.bmp
"
    AboutUrl="http://www.nowhere.com
"
    Condition="((VersionNT >= v5.1) AND (ServicePackLevel >= 3)) OR ((VersionNT >= v5.2) AND (ServicePackLevel >= 2)) OR (VersionNT >= v6.0)">

    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense" />
    <WixVariable Id="WixStdbaLicenseUrl" Value="" />
    <WixVariable Id="WixStdbaLogo" Value="Resource\logoSmall.png" />
    <Variable Name="InstallFolder" Type="string" Value="[ProgramFilesFolder]ACME\My App" />

    <Chain>
      <PackageGroupRef Id="Netfx4Full" />

      <RollbackBoundary />
     
      <MsiPackage
        Id="Setup
"
        Compressed="yes
"
        SourceFile="$(var.Setup.TargetPath)
"
        Vital="yes">
        <MsiProperty Name="INSTALLLOCATION" Value="[InstallFolder]" />
      </MsiPackage>
    </Chain>
  </Bundle>
</Wix
>

Notes:

  • This template reference the .Net 4 framework, for this I just copied the WiX source but set ExePackage/@Compresses=”yes” to embed the framework in my installation.
  • The Bundle/@Condition sets the install to only run on Windows XP SP3, Windows 2003 SP2 or later.
  • The WixStdbaLicenseUrl is set to an empty string to hide the license URL hyperlink as it is not require for my installation.
  • By referencing my WiX MSI setup project in the burn project I can reference the MSI using the syntax SourceFile="$(var.Setup.TargetPath)" where Setup is the name of my project.
  • The preprocessor variable for the version allows me to set the version from my build environment.

No License UI

To create an installation without a license URL link use the following:
       <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense" /> 
    <WixVariable Id="WixStdbaLicenseUrl" Value="" />

Hyperlink to local License file

If you want to have a link to local license file as part of your installation save the license file as an html document and then reference it as follows:
    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
      <Payload SourceFile="Resource\License.htm" />
    </BootstrapperApplicationRef>
    <WixVariable Id="WixStdbaLicenseUrl" Value="License.htm" />

This embeds the file license.htm file within the bundle and extracts it when the installation is run, if the user clicks the hyperlink then the file is loaded in the default browser.

RichText box license dialog

To create an installation with the license displayed in a richtext control use the following:
    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
    <WixVariable Id="WixStdbaLicenseRtf" Value="Resource\License.rtf" />

Custom UI

If you want to customise the standard UIs copy them from the WiX source and reference them like this:
    <WixVariable Id="WixStdbaThemeXml" Value="Resource\HyperlinkTheme.xml" />
    <WixVariable Id="WixStdbaThemeWxl" Value="Resource\HyperlinkTheme.wxl" />

.Net Framework 3.5 SP1 Install

To install the .Net Framework v3.5 SP1 I use this:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <Fragment>
    <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v3.5" Value="Version" Variable="Netfx35Version" />

    <PackageGroup Id="Netfx35">
      <ExePackage Id="Netfx35
"
        Cache="no
"
        Compressed="yes
"
        PerMachine="yes
"
        Permanent="yes
"
        Vital="yes
"
        Name="Redist\dotnetfx35.exe
"
        SourceFile="..\Redist\dotnetfx35.exe
"
        InstallCommand="/q /norestart /lang:ENU
"
        RepairCommand="/q /norestart /lang:ENU
"
        UninstallCommand="/q /norestart /lang:ENU
"
        InstallCondition="NOT Netfx35Version OR (Netfx35Version &lt; v3.5.30729.1)" 
        DetectCondition="Netfx35Version AND (Netfx35Version &gt;= v3.5.30729.1)">
        <ExitCode Value ="3010" Behavior="forceReboot" />
      </ExePackage>
    </PackageGroup>
  </Fragment>
</Wix
>

Signing a package

This is the approach I use (http://wix.sourceforge.net/manual-wix3/insignia.htm):

  1. insignia -ib Setup.exe -o engine.exe
  2. signtool engine.exe (extra parameters excluded for simplicity)
  3. insignia -ab engine.exe Setup.exe -o Setup.exe
  4. signtool Setup.exe

You can also use modify the wixproj to override the SignBundleEngine and SignBundle targets (sample copied from this thread http://sourceforge.net/mailarchive/message.php?msg_id=29179087):

<Target Name="SignBundleEngine">
  <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f privatekey.pfx /p mypassword /t http://timestamp.comodoca.com/authenticode &quot;@(SignBundleEngine)&quot;" />
</Target>
<Target Name="SignBundle" >
  <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f privatekey.pfx /p mypassword /t http://timestamp.comodoca.com/authenticode &quot;@(SignBundle)&quot;" />
</Target>

I found this problematic because:

  1. My certificate is not in the certificate store so I have to use signtool (as above).
  2. Signtool is not in the path or referenced via an environment variable so you have to know the path to the location of the Platform SDK you have installed and hard code it.
  3. You signing password is hard coded in the wixproj file.

Edit 07/05/2012: ARPSYSTEMCOMPONENT not required as this supplied by burn.

Wednesday, 19 August 2009

Registration Free COM

From Windows XP SP2 Microsoft introduced a feature called RegFree COM, which allows you to call COM objects (yes some of us still use COM) without needing to register them first. The object in question must be in the same folder as the caller but this makes it much easier to install these objects and goes a little way to the xcopy distribution utopia. To use RegFree COM your caller and callee assemblies needs to have manifest files either externally or embedded - Manifest Files Reference. The assemblies can be written in any language that supports COM and you can call between languages, e.g. vb to vb, vb to .Net, .Net to vb.

The calling application needs a manifest file configured as follows, in this example the application is called MyApp.exe so the manifest is MyApp.exe.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="MyApp" version="0.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="ComAssembly.dll" version="1.2.3.4" />
</dependentAssembly>
</dependency>
</assembly>

The COM assembly needs a manifest file configured as follows, in this example the assembly is called ComAssembly.dll so the manifest is ComAssembly.dll.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="ComAssembly.dll" version="1.2.3.4" />
<file name="ComAssembly.dll">
<comClass clsid="{11111111-2222-3333-4444-555555555555}" threadingModel="Both" />
</file>
</assembly>

In MyApp.exe.manifest I have set the version to “0.0.0.0” this should really match the application version but “0.0.0.0” works. The dependentAssembly/assemblyIdentity  can be repeated for as many COM dependencies that you have.

The assemblyIdentity in the caller manifest must match exactly the one in the callee.

Getting this right can be quite difficult to debug, on XP the only clues to problems are written to the system eventlog with the source SideBySide. On Vista (and I assume Windows 7 and Windows Server 2008 although I haven’t tried it) you can use SxsTrace to help debug the problem. To start trace run “SxsTrace Trace -logfile:SxsTrace.etl” to convert the log file to something you can view run “SxsTrace Parse -logfile:SxsTrace.etl -outfile:SxsTrace.txt”.

The two manifest files presented here have been reduced to the minimum required to get the code to work, they are more settings that can be included see the Manifest Files Reference for more details.

See also:

Saturday, 16 August 2008

Report Loader for SQL Server Reporting Services

I recently had to deploy some reports to SQL Server Reporting Services and found that Microsoft don't supply any tools to make this easy. My requirement was to be able to take reports from developers and deploy them directly to Reporting Services and fix up the database connections to point at the correct SQL server for the environment. With the help of the code from Jason Smith at SQLdbatips.com I wrote a command line deployment program in C#.

The command line syntax for this program is shown below:

ReportLoader [--help|-?|-h] (--url=targeturl|--server=targetserver)
[--source=sourcefolder] --target=targetfolder [--connstring=connstring]
[--username=username --password=password]

--help - this information
--url - target rss server url
--server - target server name, defaults to current folder
--source - source folder containing reports (*.rdl) and datasources (*.rds)
--target - target folder name
--connstring - connection string to use
--username - username to use in datasource
--password - password for username
--delete - delete all reports before upload

Examples:
ReportLoader --url="http://localhost/ReportServer/ReportService2005.asmx" --source="D:\My Reports\Reports" --target="/My Reports"
ReportLoader --server=rsserver --source="D:\My Reports\Reports"
--target="/My Reports" --connstring="Data Source=SQLSERVER;Initial Catalog=Database"
--username=DOMAIN\SvcMyReports --password=pass


The command line help doesn't say it but this will also upload GIF and JPG files it finds in the source directory.

If you would like to use this the source and compiled application are available here: ReportLoader.zip. If you have any comments about it or suggestions to improve it please let me know.

If I get time I would like to convert this application in to a custom action for Windows Installer that can be used from WiX.

Edit: 05 October 2008 - Updated download to include -url parameter.

Saturday, 9 August 2008

Deployment Driven Development

In Peter Marcu's Blog he talks about this (http://blogs.msdn.com/pmarcu/archive/2008/05/22/Design-your-Application-to-Fit-Your-Shipping-Container.aspx) and it something that I feel needs promoting more.

In my roll I often have to deploy new components or systems that have not considered how they will be deployed. In a lot of cases the development teams pick a new technology (usually from Microsoft) because it solves a development issue but this then creates a whole new deployment problem.

One example I came across recently was SQL Reporting Services, there doesn't seem to be any sensible way of deploying this. I have written a command line program to do this which I hope to share here soon.