Finding changed files

Written by Mark Howard on 30.04.2008 | Tags: , ,

Listing the most recently changed files in the currently directory:

ls -FlArt

Finding the most recenly changed files (recursively):

find . -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort

Universal International Freephone Numbers

Written by Mark Howard on 24.04.2008 | Tags:

Skype support has just confirmed that I’m not going insane and it is in fact a limitation of their software that means I cannot dial a Universal International Freephone Number with skype-out.

I need one to join a web based conferencing system and don’t have a real phone nearby. So I’ll have to stick to calling the US-freephone number from England and suffer the lag in the call :(

Wix

Written by Mark Howard on 17.03.2008 | Tags: ,

I’ve had a long outstanding requirement to add a windows installer to one of our products. Ideally this should be a standard .msi file, so that it can be easily managed remotely. My own requirement was that this must integrate into our maven2 build system, ideally without requring any extra installation other than by the standard maven dependency resolution mechanisms. I was also interested in maven2 plugins that could generate both .msi files and linux graphical installer applications (for the poor users). My initial investigations found — as always — many half-written and completely unusable maven plugins. But it’s easy enough to run commands through the mvn antrun plugin. After much investigation, I came across the open source Windows Installer XML toolkit. This is an open-source microsoft application. It does exactly what it is supposed to - creates .msi files from xml files. The XML format is sadly poorly documented, with the best example being a tutorial which is far too verbose for it’s own good. It also lacks what I consider basic functionality, such as performing simple string replacements in script files as they are installed. Anyway, we now have a working .msi compiler. This is performed in the build script with the following statements:

  1. We start by modifying the xml file, to include the correct version. This is defined as a property in the POM, rather than using the standard version property, since this must be in the form major.minor.build (no -SNAPSHOT allowed!).
    <replaceregexp file="src/assembly/installer.wxs\" match="Codepage=&quot;1252&quot; Version=&quot;.*&quot;>" replace="Codepage=&quot;1252&quot; Version=&quot;${windowsVersion}&quot;>" byline="true" />
  2. An execution of maven-dependency-plugin copies all the dependant jars to a target location (maven-jar-plugin is also configured to output here):
    <execution> <id>copy-dependencies</id> <phase>process-resources</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/installer/lib </outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> <includeScope>runtime</includeScope> <silent>true</silent> </configuration> </execution>
  3. Next, we run the heat.exe tool. This is a pre-processor which generates a fragment wix xml file containing details of all the files we want to install (i.e. all the dependencies). We could have alternatively hand-crafted this code, but that would be far more susceptible to problems when the code is updated:
    <exec dir=\"target\" executable=\"heat.exe\" failonerror=\"true\"> <arg line=\"dir installer -sfrag -gg -out components.wxs -template:fragment\" /> </exec>
  4. The current version of heat generates an invalid xml fragment - it defines an invalid top-level directory, when it should just have a directory ref to the installdir directory. A simple regexp fixes this:
    <replaceregexp file="target/components.wxs" match="&lt;Directory Id=&quot;installer&quot;.*&gt;" replace="&lt;DirectoryRef Id=&quot;INSTALLDIR&quot;&gt;" byline="true" /> <replaceregexp file="target/components.wxs" match="^ &lt;\/Directory&gt;" replace="&lt;\/DirectoryRef&gt;" byline="true" />
  5. The XML is then ‘compiled’ into an intermediate form:
    <exec dir="target" executable="candle.exe" failonerror="true"> <arg line="..\src\assembly\installer.wxs components.wxs -ext WixUIExtension" /> </exec>
  6. The final .msi installer is generated from these intermediate files (like a linker):
    <exec dir="target" executable="${light}" failonerror="true"> <arg line="-ext WixUIExtension -cultures:en-us installer.wixobj components.wixobj -out ${project.name}-${project.version}.msi" /> </exec>
  7. As a final safety-net, we run the automatic msi testing tool. I’m not convinced that this does very much, but it’s cheap to include:
    <exec dir="target" executable="${smoke}" failonerror="true"> <arg line="radiusjobmanager-${project.version}.msi" /> </exec>
Comments

Recent Comments

  • Mark Howard: Petr: Thanks for the comment - learning from experienced users is always helpul. I hadn’t...
  • Petr Kozelka: Yes, this is possible and usually works. However, like many other things, possible is not always good,...
  • Jesus: Thanks a lot mate, it saved my day!!! By the way, why are things so difficult with maven/maven2?
  • Tomas: Hi, It doesn’t work for me with multi-module project (have one parent project and poms for each module)....
  • Seth: Teach by example. Don’t tell anybody anything. It is the surest way to raise friction. Instead, just show...