September 16, 2011

NAnt - Some userful Tasks


1) xmlpeek -- Extracts text from an XML file at the location specified by an XPath expression

Usage: xml file used is for the given example is
<? xml version="1.0" encoding="utf-8”?>
<configuration xmlns="http://www.gordic.cz/shared/project-config/v_1.0.0.0">
    <appSettings>
        <add key="server" value="testhost.somecompany.com" />
    </appSettings>
</configuration>

Using xmlpeek to extract the value of add node where key =’server’

<xmlpeek
    file="App.config"
    xpath="/x:configuration/x:appSettings/x:add[@key ='server']/@value"
    property="configuration.server">
        <namespaces>
<namespace prefix="x" uri="http://www.gordic.cz/shared/project-config/v_1.0.0.0" />
        </namespaces>
</xmlpeek>


2) xmlpoke -- Replaces text in an XML file at the location specified by an XPath expression.

Usage: the xml file is same as above

Xmlpoke will change the value of the value property of add to the value provided which is productionhost.somecompany.com

<xmlpoke
    file="App.config"
    xpath="/configuration/appSettings/add[@key = 'server']/@value"
    value="productionhost.somecompany.com" />

3) asminfo -- Generates an AssemblyInfo.cs file using the attributes given.

Usage: 
<asminfo output="AssemblyInfo.cs" language="CSharp">
    <imports>
        <import namespace="System" />
        <import namespace="System.Reflection" />
        <import namespace="System.EnterpriseServices" />
        <import namespace="System.Runtime.InteropServices" />
    </imports>
    <attributes>
        <attribute type="ComVisibleAttribute" value="false" />
        <attribute type="CLSCompliantAttribute" value="true" />
        <attribute type="AssemblyVersionAttribute" value="1.0.0.0" />
<attribute type="AssemblyTitleAttribute" value="My fun assembly" />
<attribute type="AssemblyDescriptionAttribute" value="More fun than a barrel of monkeys" />
<attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2002, Monkeyboy, Inc." />
<attribute type="ApplicationNameAttribute" value="FunAssembly" />
    </attributes>
    <references>
        <include name="System.EnterpriseServices.dll" />
    </references>
</asminfo>

Here an AssemblyInfo.cs file is created with metadata information as provided in the attribute element of asminfo tag. The import element is used to import some namespaces in the AssemblyInfo.cs file. However reference section can be omitted as per the requirements

4) foreach -- Loops over a set of items.

Usage:  Loops over all files in the project directory.
<foreach item="File" property="filename">
    <in>
        <items>
            <include name="**" />
        </items>
    </in>
    <do>
        <echo message="${filename}" />
    </do>
</foreach>
    
Each item which it is currently looping the string value of it can be stored in ‘property’ property of the foreach tag. It can be very useful for some special requirements. Other use of this task is mentioned in the Link mentioned below.


5) scripts -- Executes the code contained within the task. This code can include custom extension function definitions. Once the script task has executed those custom functions will be available for use in the build file.

Usage: 
<script language="C#" prefix="test" >
     <code>
         <![CDATA[
              [Function("test-func")]
              public static string Testfunc(  ) {
                  return "some result !!!!!!!!";
              }
         ]]>
     </code>
</script>
<echo message='${test::test-func()}'/>

The various scripts which can be used are VB, C#, JS, JSHARP.
The reuse of the function in the NAnt script is also shown.



6) choose(NAnt contrib) : Executes an alternate set of tasks depending on conditions that are individually set on each group of tasks. Similar to if- else if.

Usage: 
<choose>
    <when test="${build.config == 'Debug'}">
        <!-- compile app in debug configuration -->
        ...
    </when>
    <when test="${build.config == 'Release'}">
        <!-- compile app in release configuration -->
        ...
    </when>
    <otherwise>
<fail>Build configuration '${build.config}' is not supported!</fail>
    </otherwise>
</choose>

Source: http://nantcontrib.sourceforge.net/release/0.85/help/tasks/choose.html

September 9, 2011

Using Radio button in InstallShield – Simplified

This article explains about adding two Radio buttons to a Radio group and setting / reading the option's value in a VBScript Custom Action.
[Note: The steps are based on Basic MSI Project using InstallShield 2011].
·         Create a Radio Group in a Custom dialog and name the property as RADIOGROUPVAR.
·         Add two radio buttons (with text Yes & No) to the Radio Group and define ‘order’ & ‘value’ properties of the radio button as detailed below

Radio Button
Order
Value
Yes
2
Yes
No
1
No

In this example, Order is set to 1 for ‘No’ radio button and hence it will be selected by default.
·         Further set the value of ‘RADIOGROUPVAR’ in Property Manager as No, to ensure that ‘No’ radio button is selected by default.
So now the UI Design is done.
·         Set / Read the radio button value through VB Script Custom Action
o   Set
Session.Property(“RADIOGROUPVAR”)=”No”
o   Read
MSGBOX “RADIOGROUPVAR Value =>“  &  Session.Property(“RADIOGROUPVAR”)

August 15, 2011

More about Upgrades

A great challenge that the Application Packaging team faces during the installer development is to make decision about how are we going to distribute future releases to customers? It depends on various factors like
  • How big is the installation?
  • What will be the impact if your customer has to reinstall the product? For example re-installation will have an adverse effect on realtime applications with huge database.
  • Frequency of upgrades to be released
Here is what Shieldmaster have compiled on Upgrade Strategy, which will help to address Customer's concern by choosing appropriate Upgrade technique.

InstallTalk's recommendations on when to use major or minor upgrades

If you would like to have a single installer with support for seamless, which should not to disturb existing installation during upgrade and for new customers the same should behave like a fresh installation, then minor upgrade is your choice. Here is the Step by Step approach to create minor upgrade.

July 16, 2011

Did you know that Low disc space can also result in CCNet Exception?

The CruiseContrl.Net users might have encountered Exceptions on various reasons like session timeout etc. but very recently I have observed that one of the build resulted in the following exception, when there is low disc space.
"There was an exception trying to carry out your request."

Exception Message
Unable to execute transform: C:\Program Files\CruiseControl.NET\webdashboard\xsl\header.xsl

The subsequent builds successed after freeing up required disc space.
Note: This was verified in CruiseControl.Net  v1.5.7217.6

November 21, 2010

How to create a Custom User friendly Log for InstallScript?

This article explains how to create your own logging for InstallScript / InstallScript MSI project or Custom Actions writted in InstallScript.

Use the following code-snippet to create Custom Logging for InstallScript

// Prototype Definition
prototype ISfn_CreateLogFile();
prototype BOOL ISfn_LogError(STRING, STRING, STRING);


// Global Declaration
STRING gLogFilePath,gLogFileName,sgLogfile, gsvProductName; // For Log file
BOOL IsLogCreated,IsLogWritten,IsTempLogPath; // For Log file


Add the following code in OnBegin event for InstallScript / InstallScript MSI project or just before invoking ISfn_LogError function.
// Read the ProductName to a variable
nvSize = 256;
MsiGetProperty(ISMSI_HANDLE,"ProductName",gsvProductName,nvSize);

//Create the Log File
ISfn_CreateLogFile();

 

How to invoke ISfn_LogError function for Custom Log?
For Example:
ISfn_LogError("Local system name", "From Wscript : '" + svLocalSystemName + "'" ,"Success")
- first parameter states that the particular step is perfomed while getting Local System Name,
- the second parameter logs the retrieved local system name, the third parameter
- the third parameter determines that the actions output is a Success
Function Definition:
Copy the following function definition to your .rul file:
//---------------------------------------------------------------------------
// ISfn_CreateLogFile()
// Description: This function creates the installation log file in the format of
// PRODUCTNAME_Install_<InstallDate>__<InstallTime>.txt under
// Temp folder of the currently logged in user.
//---------------------------------------------------------------------------

function ISfn_CreateLogFile()


STRING sInstallerLogFilePath,sProdName;
STRING sSysDate,sSysTime,sHhr,sMin,sSec,svString,sLogFileName;
NUMBER nvResult,nPos,nHhrLen,nMinLen;
STRING szErrMsg;
NUMBER nvFileHandle;
begin


sInstallerLogFilePath="";
sInstallerLogFilePath = TempFolder;
if (ExistsDir(sInstallerLogFilePath)=0) then
         gLogFilePath = sInstallerLogFilePath;
else
         sInstallerLogFilePath = "";
         GetDisk(TempFolder,sInstallerLogFilePath);
         gLogFilePath = sInstallerLogFilePath + "\\";
         IsTempLogPath = TRUE;
endif;

// Creating the Log File Name
sProdName = gsvProductName;
//Frame the Log File Name
// Get the current date.
GetSystemInfo (DATE, nvResult, sSysDate);
// Get the current time.
GetSystemInfo (TIME, nvResult, sSysTime);
nPos = StrFind(sSysTime,":");
//Get the Hour part from the Date
StrSub ( sHhr, sSysTime, 0, nPos );
nHhrLen = StrLength(sHhr);
nHhrLen = nHhrLen + 1;
//Get the Minutes part from the Date
StrSub ( sMin, sSysTime, nHhrLen, 2 );
nMinLen = StrLength(sMin);
nMinLen = nHhrLen + nMinLen + 1;
//Get the Seconds part from the Date
StrSub ( sSec, sSysTime, nMinLen, 2 );
sSysTime = sHhr + "_" + sMin + "_" + sSec;
//Frame the final Log File name
if (!MAINTENANCE) then
          sLogFileName = sProdName + "_Install_" + sSysDate + "__" + sSysTime +".txt";
else
          sLogFileName = sProdName + "_UnInstall_" + sSysDate + "__" + sSysTime +".txt";
endif;
gLogFileName = sLogFileName;
// Set the file mode to append.
OpenFileMode (FILE_MODE_APPEND);
// Create a new file and leave it open.
if (CreateFile (nvFileHandle, gLogFilePath, sLogFileName) != 0) then
        // Report the error.
       MessageBox ("Error log file creation failed. Installation continues...", INFORMATION);
       IsLogCreated = FALSE;
else
       IsLogCreated = TRUE;endif;
// Set the message to write to the file.
// Append the message to the file.
// Write the Header Informations into the file
szErrMsg = "*******************************************************************************************************************";

if (WriteLine(nvFileHandle, szErrMsg) != 0) then
       // Report the error.
       MessageBox ("Errors couldnot be logged into the log file.     Installation continues...", INFORMATION);
       IsLogWritten = FALSE;
else
        IsLogWritten = TRUE;
        sgLogfile = gLogFilePath ^ sLogFileName;
endif;

if (IsLogWritten = TRUE)then
endif;
szErrMsg = "";
if (!MAINTENANCE) then
        szErrMsg = " "+ gsvProductName +" Installation Log ";
else
        szErrMsg = " "+ gsvProductName +" UnInstallation Log ";
endif;
WriteLine(nvFileHandle, szErrMsg);
szErrMsg = "";
szErrMsg = " Created on " + sSysDate + "__" + sSysTime + " ";
WriteLine(nvFileHandle, szErrMsg);
szErrMsg = "";
szErrMsg = "*******************************************************************************************************************";
WriteLine(nvFileHandle, szErrMsg);
szErrMsg = "";

// Close the file.
CloseFile (nvFileHandle);
end; // end of ISfn_CreateLogFile


 //---------------------------------------------------------------------------
// ISfn_LogError()
// Description: This function logs the installation actions in the Installation
// log file which was created using ISfn_CreateLogFile() function
// Input Parameters:
// ActionRequested: Action name/detail that is related to that particular action
// Parameters: Data that are passed to that particular function / action
// Status: Determines the output of that particular action(Information/Success/Error)
//---------------------------------------------------------------------------
function BOOL ISfn_LogError(ActionRequested, Parameters, Status)


NUMBER nvFileHandle,nvResult;
STRING szErrMsg,sSysDate,sSysTime;
begin
end; // end of ISfn_LogError
if (IsLogCreated=TRUE && IsLogWritten = TRUE) then
GetSystemInfo (DATE, nvResult, sSysDate);
GetSystemInfo (TIME, nvResult, sSysTime);
szErrMsg = "";
if Status = "Error" then
szErrMsg = "[" + sSysDate + "," + sSysTime + "] ERROR " + ActionRequested + " :: " + Parameters + " :: " + Status;
else
szErrMsg = "[" + sSysDate + "," + sSysTime + "] " + ActionRequested + " :: " + Parameters + " :: " + Status;
endif;

OpenFileMode (FILE_MODE_APPEND);
if (OpenFile (nvFileHandle, gLogFilePath, gLogFileName) = 0) then
WriteLine(nvFileHandle, szErrMsg);
endif;
CloseFile (nvFileHandle);
szErrMsg = "";
endif;