Sonntag, 24. Februar 2013

BURN #03: Applying patches in the bootstrapper

Slipstreaming msp packages (like tweaking the RTM installer to install patches automatically)

Technically, slipstreaming is installing the patch-msp with the msi in a single transaction:
msiexec /i D:\product.msi PATCH=D:\patch.msp

Andreas Kerl's .NET-dev article explained how to slipstream patches into an installer:
<PackageGroup Id="Product">
  <MsiPackage Id="Product" Name="packages\product.msi">
    <SlipstreamMsp Id="Patch"/>
  </MsiPackage>
  <MspPackage Name="packages\patch.msp"/>
</PackageGroup>

Well, that does not seem to be necessary, much simpler and also working due to the MspPackage/@Slipstream attribute being set to 'yes' always, this works too:
<PackageGroup Id="Product">
  <MsiPackage Id="Product" Name="packages\product.msi"/>
  <MspPackage Id="Patch" Name="packages\patch.msp"/>
</PackageGroup>

See Stewart Heath's article.

Freitag, 22. Februar 2013

Starting to LOG and TRACE my programs


BURN #02: How to sign the msi packages and the Bootstrapper

Some examples on conditions, how to change the installer GUI, and signing the packages.

http://neilsleightholm.blogspot.de/2012/05/wix-burn-tipstricks.html

About signing:
I created several .wixproj files for msbuild compilation. But to get signing to work, i had to do the following (this is probably just one way to do it):

Wix projects by default call a wix.targets task, which has many msbuild tasks for building the msi/merge modules, whatever with the installed wix version. It also holds an abstract task which you can redefine/redirect to sign you stuff.

To sign msi and cab packages:
<Target Name="SignCabs">
  <Exec Command="$(signToolCall) &quot;%(SignCabs.FullPath)&quot;" />
 </Target>
 
 <Target Name="SignMsi">
  <Exec Command="$(signToolCall) &quot;%(SignMsi.FullPath)&quot;" />
 </Target>

To sign BURN bootstrapper:
<Target Name="SignBundleEngine">
  <Exec Command="$(signToolCall) &quot;@(SignBundleEngine)&quot;" />
 </Target>
 
 <Target Name="SignBundle" >
  <Exec Command="$(signToolCall) &quot;@(SignBundle)&quot;" />
 </Target>

And most important: each .wixproj file must have a property called (it does not matter in which property group you push that):
<PropertyGroup>
  <!-- this makes wix sign everything it can -->
  <SignOutput>true</SignOutput>
 </PropertyGroup>

To streamline everything, just put this one line into your .wixproj file:
    <Import Project="$(WixTargetsPath)" />
 <!-- the WixTargetsPath line already exists. add your default targets file to your .wixproj targets -->
    <Import Project="..\Default.targets" />

And to round everything up, here's my complete Default.targets file with methods to find the ProgramFiles (x86) directory and the windows installer SDK directory:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <PropertyGroup>
  <!--MSBuild 4.0 property-->
  <ProgramFiles32>
  $(MSBuildProgramFiles32)
  </ProgramFiles32> 
  <!--Use OS env var as a fallback:- 32 bit MSBuild 2.0/3.5 on x64 will use this-->
  <ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">
  $(ProgramFiles%28x86%29)
  </ProgramFiles32>

  <!-- Handle MSBuild 2.0/3.5 running in 64 bit mode - neither of the above env vars are available. http://stackoverflow.com/questions/336633
       NB this trick (Adding a literal " (x86)" to the 64 bit Program Files path) may or may not work on all versions/locales of Windows -->
  <ProgramFiles32 Condition ="'$(ProgramFiles32)'=='' AND 'AMD64' == '$(PROCESSOR_ARCHITECTURE)'">
  $(ProgramFiles) (x86)
  </ProgramFiles32>

  <!--Catch-all - handles .NET 2.0/3.5 non-AMD64 and .NET 2.0 on x86 -->
  <ProgramFiles32 Condition=" '' == '$(ProgramFiles32)' ">
  $(ProgramFiles)
  </ProgramFiles32>

  <!-- some important directories -->
  <ProductsDir Condition=" '$(ProductsDir)' == '' ">
  $(MSBuildThisFileDirectory)..\Products\
  </ProductsDir>
  <msiDir>
  "$(ProgramFiles32)\Microsoft SDKs\Windows\v7.0A\bin\"
  </msiDir>
  
  <!-- signtool configuration -->
  <signTool>
  $(msiDir)signtool.exe
  </signTool>
  <timeStampServer>
  http://timestamp.verisign.com/scripts/timestamp.dll
  </timeStampServer>
  <signKey>
  "$(ProductsDir)your_key_file.pfx"
  </signKey>
  <uniformResourceLocator>
  www.your_web_adress.com
  </uniformResourceLocator>
  <signToolCall>
  $(signtool) sign  /f $(signKey) /p smokey11 /du $(uniformResourceLocator) /t $(timeStampServer)
  </signToolCall>
 </PropertyGroup>

 <PropertyGroup>
  <!-- this makes wix sign everything it can -->
  <SignOutput>true</SignOutput>
 </PropertyGroup>
 
 <Target Name="SignCabs">
  <Exec Command="$(signToolCall) &quot;%(SignCabs.FullPath)&quot;" />
 </Target>
 
 <Target Name="SignMsi">
  <Exec Command="$(signToolCall) &quot;%(SignMsi.FullPath)&quot;" />
 </Target>
 
 <Target Name="SignBundleEngine">
  <Exec Command="$(signToolCall) &quot;@(SignBundleEngine)&quot;" />
 </Target>
 
 <Target Name="SignBundle" >
  <Exec Command="$(signToolCall) &quot;@(SignBundle)&quot;" />
 </Target>
</Project>

Dienstag, 19. Februar 2013

BURN #01: Get the BootstrapperApplicationData.xml

This one is not tricky at all. You basically want to get this data if your installer is running, to get the dependencies of the .msi packages right.
Now, there's no example from wix.sourcefourge.com, nor from anywhere else I searched.

This code in your BootstrapperApplication UX (user experience) gets you the file.
    string fileName = "BootstrapperApplicationData.xml"; 
    string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), fileName); 
    using (FileStream stream = new FileStream(path, FileMode.Open)) 
    { 
        ... 
    }

If you want to have this file without running your installer: don't go starting it and searching for the file. That'd suck. No, just go to cmd, and run:
%WiX%\bin\dark.exe <your_file> -x <extract_to_this_dir>

So, how to get custom data in there?
It's a bit fuzzy at the moment, but Rob Mensching said:
You just add rows to a table that has BootstrapperApplicationData="yes". The Binder will translate all those rows into BootstrapperApplicationData.xml.
-----------------------
First, the CustomTable definition (just Column elements) can be put in a separate Fragment. Then, when you populate a CustomTable (add Row elements) that CustomTable will reference the definition.That means you need to put the CustomTable/Row in a fragment that is referenced. 
Often, the CustomTable/Row data is so verbose, there is a tendency to put it in a separate Fragment. That is a completely reasonable but now it's floating in an island that needs a "hackish" reference. Empty PayloadGroup for Bundles is very good, BTW.
So what's the ideal?  The ideal is to create an Extension. The Extension would then extend the compiler to provide a "pretty face" on your CustomTable and be far more powerful than the raw Row elements. 
We cheated for a long time with the wixstdba by using WixVariables before finally creating the "pretty face". Looking back, we should have done it earlier. <smile/> 

Donnerstag, 14. Februar 2013

What to do if dependency injection complains: especially Unity!!

Well, Unity simply sucks up to a certain version. It fails to get the assembly and complains with: Assembly can't be found. -- yeah, but which assembly, asshole???
Slashdot said something about that here.
That statement below catches such events and lets you know something. If it helps?
AppDomain.CurrentDomain.AssemblyResolve +=
          new ResolveEventHandler(CurrentDomain_AssemblyResolve);

How to add syntax highlighting to blog posts

This should be the first post.. but here we go as second :)
How to add syntax highlighting to a blog per javascript (from alexgorbatchev)

Currently I use prettyprint (Prettify) from a google dev:
http://code.google.com/p/google-code-prettify/
To use it, simply put this in your &lt;head&gt; tag:
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?autoload=true&skin=sunburst&lang=css" defer="defer"></script>
Stackoverlflow on code formatting
Escape the html characters

Shamelessly copied from: oneqonea.blogspot.com
<!-- Syntax Highlighter Additions START -->
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css" />
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeEmacs.css" rel="stylesheet" type="text/css" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript" />

<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPowerShell.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js" type="text/javascript" />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js" type="text/javascript" />
 
<script language="javascript" type="text/javascript">
 SyntaxHighlighter.config.bloggerMode = true;
 SyntaxHighlighter.all();
</script>
<!-- Syntax Highlighter Additions END -->

Mittwoch, 13. Februar 2013

How to redirect assembly versions in .NET


.NET Assembly versions can be redirected in application, publisher policy, or machine configuration files.
The assemblies need to be signed == have a strong name. If they are not signed, the version is not taken into account by calling assemblies.
Slashdot had it's take on that here.

This example shows how to redirect in the app.config file
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <publisherPolicy apply="no" />
      <dependentAssembly>
        <!-- i stumbled over this one: i started using culture="en-us", that failed. -->
        <assemblyIdentity name="MyDependant.Assembly.ToRedirect"
          publicKeyToken="cf95ca7471e897ff"
          culture="Neutral" />
        <!--  -->
        <bindingRedirect oldVersion="1.0.0.0-1.0.0.163" newVersion="1.0.0.163" />
        <publisherPolicy apply="no" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>