Tuesday, July 20, 2010

Using wix3 and heat to create a wxi through xls transform.

Here is a transform file which can be used with wix3 and heat if you want to create a wix include file (wxi) from a wxs fragment.

Update: Added CompnentGroupRef, CompnentGroup and CompnentRef incase -cg flag is used with heat on a fragment.
<xsl:stylesheet exclude-result-prefixes="wix" version="1.0" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" indent="yes" method="xml">
  <xsl:strip-space elements="*">
  <xsl:template match="/">
    <include>
      <xsl:apply-templates>
    </xsl:apply-templates></include>
  </xsl:template>


  <xsl:template match="wix:ComponentGroupRef">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:ComponentGroup">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:ComponentRef">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:DirectoryRef">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:Directory">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:Component">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


  <xsl:template match="wix:File">
    <xsl:element name="{name()}">
      <xsl:copy-of select="@*">
      <xsl:apply-templates>
    </xsl:apply-templates></xsl:copy-of></xsl:element>
  </xsl:template>


</xsl:strip-space>
</xsl:output>
</xsl:stylesheet>

If you need other elements it should just to copy the templates for File, Directory, Component or DirectoryRef and and rename the match. 

To use it, use the -t parameter when calling heat.exe
Example: (above saved as transform_fragment_to_inc.xsl)

heat.exe" dir "files\to\harvest" -gg -g1 -nologo -scom -sfrag -srd -sreg -svb6 -template:fragment -t:"transform_fragment_to_inc.xsl" -out "include_file.wxi"

Note: this xsl doesn't support registry entries or registering of com components when harvested by heat.

Monday, April 12, 2010

Wix 3.0 - Windows 7 x64 - votive - Visual Studio 2008

It seems like there is an issue with the installer for Wix 3.0 with the combination of Visual Studio 2008 and Windows 7 x64.

When installing the project aggregator it's installed to c:\IDE\
It should be in
C:\Program Files(x86)\Microsoft Visual Studio 9.0\Common7\IDE\ 

When installing Wix from the MSI the templates should have been installed to
C:\users\USERNAME\documents\Visual Studio 2008\Templates\ItemTemplates

and
C:\users\USERNAME\documents\Visual Studio 2008\Templates\ProjectTemplates

They are just placed as zip files in C:\Visual Studio 9.0\Common7\IDE\WiX
Unpack WixLibrary.zip, WixMergeModule.zip and WixProject.zip to
C:\users\USERNAME\documents\Visual Studio 2008\Templates\ProjectTemplates

Unpack BlankFile.zip, CustomActionCPP.zip, IncludeFile.zip, LocalizationFile.zip, TextFile.zip to
C:\users\USERNAME\documents\Visual Studio 2008\Templates\ItemTemplates

You can now create wix projects using Visual Studio... :)

Error in MSDN documentation for ssfPROGRAMFILESx86

There is a documentation error here: (or even header error)

http://msdn.microsoft.com/en-us/library/bb774096(VS.85).aspx

When using ssfPROGRAMFILESx86 with the value of 0x30, it gives the administrative tools path, while with a value of 0x2A gives Program Files X86.

Can be tested with the following vbscript:

Const PROGRAM_FILES_XEIGHTYSIX = &H2A&
Const PROGRAM_FILES_XEIGHTYSIXWRONG = &H30&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(PROGRAM_FILES_XEIGHTYSIXWRONG)
Set objFolderItem = objFolder.Self
msgbox ("Wrong Path: 0x30 :"+objFolderItem.Path)  
Set objFolder = objShell.Namespace(PROGRAM_FILES_XEIGHTYSIX)
Set objFolderItem = objFolder.Self
msgbox ("Correct Path: 0x2A : "+objFolderItem.Path)

To get the correct path, just use 0x2a instead of 0x30.

Friday, March 26, 2010

Styling QWebKit scrollbars

I read some people had problems styling the scrollbars in QWebkit. It's quite simple, if you think of them as CSS (with webkit specific parameters) instead of Qt Scrollbars. Ideally it should be a stylesheet mapping between QStyleSheet and a css, so that it would automatically do the magic.

You need to implement this CSS in all the documents loaded. You can do this modifying the DOM for the document you load. If you are to provide static content, I would recommend putting the CSS into the content instead, as that is easier to modify later.

Here's a small example on how to style the scrollbars:
::-webkit-scrollbar {
    width: 42px;
}

::-webkit-scrollbar-track-piece {
    background: #CCCCCC;
    border: 2px solid #6666CC;
   -webkit-border-radius: 10px;
    width:20px;
}
::-webkit-scrollbar-thumb:vertical {
    height: 40px;
    border: 2px solid #6666CC;
    background-color: #6666CC;
    -webkit-border-radius: 10px;
}

::-webkit-scrollbar-button:end:increment {
    height:42px;
    width:42px;
    background-image: url(arrow-down.png);
    background-repeat:no-repeat;
    background-color:white;
}
::-webkit-scrollbar-button:start:decrement 
{
    height:42px;
    width:42px;
    background-image: url(arrow-up.png);
    background-repeat:no-repeat;
    background-color:white;
}

::-webkit-scrollbar-button:end:increment:hover {
    background-color:green;
}
::-webkit-scrollbar-button:start:decrement:hover
{
    background-color:green;
}

:not(.none):not(.double-start)::-webkit-scrollbar-track-piece:vertical:end:single-button,
:not(.none):not(.double-start)::-webkit-scrollbar-track-piece:vertical:end:double-button,
.single::-webkit-scrollbar-track-piece:vertical:end,
.double-end::-webkit-scrollbar-track-piece:vertical:end,
.double-both::-webkit-scrollbar-track-piece:vertical:end 
{
    margin-bottom: 40px;
}

:not(.none):not(.double-end)::-webkit-scrollbar-track-piece:vertical:start:single-button,
:not(.none):not(.double-end)::-webkit-scrollbar-track-piece:vertical:start:double-button,
.single::-webkit-scrollbar-track-piece:vertical:start,
.double-start::-webkit-scrollbar-track-piece:vertical:start,
.double-both::-webkit-scrollbar-track-piece:vertical:start 
{
    margin-top: 40px;
}



This is just an example, and you probably want to change it a lot to suite your needs.

Saturday, February 27, 2010

Three scripts for running VirtualBox in headless mode (Ubuntu)

I needed some init.d scripts for virtualbox, and I thought I should share them, as I found a lot of information out there that these scripts used ideas from:

Script 1 to start a virtualbox (vbox_start_vm)
Starts and sleeps x number of seconds, but doesn't start it if it's already running!

#!/bin/bash

if [ -z $1 ] ; then
        echo "SERVER Name is Missing... the number is 42."
        echo "usage vbox_single_start "
        exit 1
fi

if /usr/bin/VBoxManage -q showvminfo $1 | grep -i running ; then
        echo VM Guest $1 is already powered on!
        exit 1
else
        echo Starting $1
        /usr/bin/VBoxManage startvm $1 --type vrdp
        if [ $2 ] ; then
            sleep $2
        fi
fi
exit 0


Script 2 to stop a virtualbox (vbox_stop_vm)
This script tries to acpi-shutdown the system, and wait for 240 seconds before forcing it down if all fails.

#!/bin/bash
MAX_WAIT_TIME=300 # max seconds to wait before doing poweroff (force)

function wait_until_machine_shutdown_else_terminate {
    if /usr/bin/VBoxManage -q list runningvms | grep -i $1 ; then
        #echo "sleeping 10 seconds"
        sleep 10
        let MAX_WAIT_TIME=MAX_WAIT_TIME-10
        if [ $MAX_WAIT_TIME -lt 0 ] ; then
            echo "Had to force the power on the server... Sorry about that!"
            /usr/bin/VBoxManage controlvm $1 poweroff
            sleep 10
        else
            if [ $MAX_WAIT_TIME -lt 200 ] ; then
                    #try to do another acpipowerbutton
                /usr/bin/VBoxManage controlvm $1 acpipowerbutton
            fi
            wait_until_machine_shutdown_else_terminate $1
        fi
    fi
}

#ensure that the server name is entered
if [ -z $1 ] ; then
        echo "SERVER Name is Missing... the number is 42."
        echo "usage vbox_stop_vm "
        exit 1
fi

if /usr/bin/VBoxManage -q showvminfo $1 | grep -i running ; then
        echo VM Guest $1 is powered on! Will send ACPI shutdown.
        /usr/bin/VBoxManage controlvm $1 acpipowerbutton
        # if parameter for sleep is provided, do here
        if [ $2 ] ; then
            sleep $2
        fi
        # wait until it's been shutdown!
        wait_until_machine_shutdown_else_terminate $1
else
        echo Server $1 is not running!
        exit 1
fi
exit 0

Script 3 - the actual init.d script calling the other scripts (call it what you want on your system)

#! /bin/sh
# some errors with networking, so need to restart at end of init sequence
#NOT NEEDED BRIDGE WORKS?!?!?!?!

case "$1" in
   start)
        echo -n "Starting all the VirtualBox VMS"
        /etc/init.d/vbox_start_vm "Windows2008_DC" 60
        /etc/init.d/vbox_start_vm "Windows2008_Test" 60
        /etc/init.d/vbox_start_vm "Ubuntu_Web_Server" 15
        /etc/init.d/vbox_start_vm "Ubuntu_DB_Server" 15
        /etc/init.d/vbox_start_vm "Ubuntu_Testing_Server" 15
        echo "Done";
;;

stop)
        echo -n "Stopping all the VirtualBox VMS"
        /etc/init.d/vbox_stop_vm "Windows2008_DC" 
        /etc/init.d/vbox_stop_vm "Windows2008_Test" 
        /etc/init.d/vbox_stop_vm "Ubuntu_Web_Server" 
        /etc/init.d/vbox_stop_vm "Ubuntu_DB_Server" 
        /etc/init.d/vbox_stop_vm "Ubuntu_Testing_Server" 
        echo "Done";
;;

*)
echo "Usage: /etc/init.d/vbox_vm_startup {start|stop}"

exit 1
;;

esac
exit 0

I needed to implement these functions, as I now have 1 Ubuntu server with Virtualbox on top running all 5 servers at home. I wanted to have a full-blown test environment to play around in without having more than 1 server. 

The only problem so far is that the disk controller wasn't fast enough (Dell SAS 6/ir). To help this perform better I added an extra HD outside the SAS controller running the swap spaces and the pagefiles for the Windows servers. That made a huge difference, especially for the windows servers. If you are going to run your vm's on a mirrored raid, I won't recommend the SAS 6/ir if the virtual servers will be accessed by more than 20-25 users. It will feel a bit sluggish... Maybe not so much for the users, but if you do iostat as a admin, you will be in "shock" over the terrible write performance for the SAS 6/ir in mirror mode.

Testing software

Sometimes I hear people saying: "That software are for handicapped" or "I cannot make this software work for handicapped as well".

I read a great presentation over at slideshare.net: Georgia Tech hacking Accessibility

Highly recommended reading. To summarize: Software developers and companies should think that people with different disabilities are extreme testers. If your application can be accessed and work for them, it will be easier for everyone else. Instead of thinking of it as an obstacle...

An example is how visualization with symbols, text-to-speech and speech recognition now are getting more and more common. In the beginning this was for people that couldn't access computers without help.

For information about symbols: (In Norwegian) www.symboler.no. For english: www.widgit-online.com

Monday, February 8, 2010

Move an iscsi target from one windows 2008 server to another

After disconnecting an iscsi target on server A, then getting it connected on server B, it only said: "The disk is offline due to an policy set by the administrator".

I'm the administrator, and I did not set a policy. Well. This one was actually easier than I first thought...

Go into Computer Management -> Storage Right click on the disk and click online. (This does not show up when clicking on the partition, you have to click the grey square on the left)

I went back and forth trying to have the target on both computers, reading about cluster services and stuff, and after googling the error message, although sometimes the solution is easier...