Tuesday, October 04, 2011

NSIS Check wether the $INSTDIR path is valid.



There are some methods that you can used to check whether or not an installation path is valid for your installer.
 
1. .onVerifyInstDir function
This will be called every time the user changes the install directory.
 2.Write a function for MUI_PAGE_CUSTOMFUNCTION_LEAVE and can then check for GetInstDirError withing that function to

check wether it is valid.

Function .onVerifyInstDir
    IfFileExists $INSTDIR\<your exe> PathGood
      Abort ; if $INSTDIR is not a winamp directory, don't let us install there
    PathGood:
FunctionEnd

!define MUI_PAGE_CUSTOMFUNCTION_LEAVE MUIDirectoryPageLeave

Function MUIDirectoryPageLeave
  GetInstDirError $0
  ${Switch} $0
    ${Case} 1
      MessageBox MB_OK "Invalid installation directory!"
      Abort
      ${Break}
    ${Case} 2
      MessageBox MB_OK "Not enough free space!"
      Abort
      ${Break}
  ${EndSwitch}
FunctionEnd

Both the above functions has some issues.
1 will only let you to continue if there is a folfer exists as described in "$INSTDIR" path.

2 will not recognize foledr names which ends with spaces or dots as invalid
eg
 C:\Abc\Your Family \your product ; invalid since it contains space after Your Family
 C:\Abc\Your Family.\your product ; invalid since it contains a dot after Your Family
 C:\Abc\Your Family\your product ; valid

Therefore we have to write our own functions to test wether a path is valid.
Following is sample codes that you can use. (Hope you have bettr understaning of NSIS functions and macros)


!define IndexOfDef "!insertmacro IndexOfMac"
!define IsContainsDotOrSpaceAtEndDef "!insertmacro IsContainsDotOrSpaceAtEndMac"
!define IsContainsInvalidCharactersDef "!insertmacro IsContainsInvalidCharactersMac"

;;;;;   Utility Macros  ;;;;;;;;;;;;
!macro IndexOfMac resVar String Char
Push "${Char}"
Push "${String}"
Call IndexOfFun
Pop "${resVar}"
!macroend

!macro IsContainsDotOrSpaceAtEndMac resVar String
Push "${String}"
Call IsContainsDotOrSpaceAtEnd
Pop "${resVar}"
!macroend

!macro IsContainsInvalidCharactersMac resVar String
Push "${String}"
Call IsContainsInvalidCharacters
Pop "${resVar}"
!macroend

!macro IsValidPathMacro resString String
StrCpy $R1 ${String}
StrCpy ${resString} True
StrCpy $R4 0 ; loop counter
loop:
    IntOp $R4 $R4 + 1    ; increment the count

    ;;;; Split string to two parts ;;;;;;
    ${IndexOfDef} $R0 $R1 "\"
    ${If} $R0 > -1
        StrCpy $R2 $R1 $R0 0        ;first part o fthe string
        IntOp $R0 $R0 + 1            ;length
        StrCpy $R3 $R1 "" $R0       ;second part of the string
        StrCpy $R1 $R3              ;update R1
    ${Else}
        Goto endOfMac
    ${EndIf}
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   
    ${If} $R4 != 1 ; since first part is the disk drive (eg C:, D:) wich is handleed by nsis itself we can omit this

check for  count = 1
   
        ${IsContainsDotOrSpaceAtEndDef} $R0 $R2
        ${If} $R0 == True
            MessageBox MB_OK "Path should not contain dots or spaces at the end"
            Goto errFound
        ${EndIf}
   
        ${IsContainsInvalidCharactersDef} $R0 $R2
        ${If} $R0 == True
            MessageBox MB_OK 'Path should not contain any of these characters:  ?, *, < , >,", \, /, :, |'
            Goto errFound
        ${EndIf}
       
    ${EndIf}
Goto loop
   
    errFound:
    StrCpy ${resString} False
    endOfMac:
!macroend
;;;;;;;Utility Macros End;;;;;;;;;;;;;;

;;;;;  Utility Functions  ;;;;;;;;;;;;;;;;
Function IndexOfFun
    Exch $R0
    Exch
    Exch $R1
    Push $R2
    Push $R3
     
    StrCpy $R3 $R0
    StrCpy $R0 -1
    IntOp $R0 $R0 + 1
    StrCpy $R2 $R3 1 $R0
    StrCmp $R2 "" +2
    StrCmp $R2 $R1 +2 -3
     
    StrCpy $R0 -1
     
    Pop $R3
    Pop $R2
    Pop $R1
    Exch $R0
FunctionEnd

Function IsContainsDotOrSpaceAtEnd
  Exch $R0
  Push $R1
  Push $R2
  Push $R3
  StrCpy $R3 False ; contain the results
 
  StrLen $R1 $R0
  IntOp $R1 $R1 - 1
  StrCpy $R2 $R0 1 $R1  ; last character of the string

  ${If} $R2 == "."
    StrCpy $R3 True
  ${Else}
      ${If} $R2 == " "
        StrCpy $R3 True
      ${EndIf}
  ${EndIf}

  StrCpy $R0 $R3
  Pop $R3
  Pop $R2
  Pop $R1
  Exch $R0
FunctionEnd

Function IsContainsInvalidCharacters
Exch $R0
    Push $R1
    Push $R2
    StrCpy $R2 True ; contain the results
    ${IndexOf}  $R1 $R0 "\"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "/"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "*"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "?"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "<"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 ">"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 ":"
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "$\""
    IntCmp $R1 -1 0 invalidFound invalidFound
    ${IndexOf}  $R1 $R0 "|"
    IntCmp $R1 -1 0 invalidFound invalidFound
    StrCpy $R2 False
    invalidFound:

    StrCpy $R0 $R2
    Pop $R2
    Pop $R1
    Exch $R0
FunctionEnd



Usage

Replace the code based on GetInstDirError on above MUIDirectoryPageLeave function with the macro we have defined.
The example code would looks like


Function MUIDirectoryPageLeave
    !insertmacro IsValidPathMacro $R0 "$INSTDIR"
    ${If} $R0 == False
        Abort
    ${EndIf}
FunctionEnd



Sunday, June 19, 2011

Using Hudson as a CI tool for .NETprojects



Hudson is an open source CI (Continuous Integration) tool (http://hudson-ci.org/). The most interesting fact is that, it can be easily configured by the web interface provided. Execution of Hudson is based on the pluggings. These pluggins extended the Hudson with a range of build tools. I have not configured any other tool before this even though I have used CC.Net. But after two- three times of tries I was able to set it up and build my first .NET project.

1. Install
First of all we need to install the Hudson, It comes as .war file. You can download it on http://hudson-ci.org/downloads/war/latest/hudson.war. You have to have java installed on your machine before you install the Hudson. Once you download the “Hudson.war” file, do the following. Open the command- prompt and locate the folder where “Hudson.war” file exists. Chose a location in your file-system where you have enough space (here I have chosen c:\Hudson), because your project files will be copied to here and build, so it needs some space. Then issue the following command on command-prompt.
java -DHUDSON_HOME=c:\Hudson -jar hudson.war
Now you would see some Hudson installing status messages are appearing on the command prompt, and will be paused (hold) at some point, which means Hudson is running (Do not close the command prompt). You can check it by typing http://localhost:8080/ on your web browsers address bar, Hudson dashboard may appear.
1.1
You can install Hudson as a windows service, so that you do not want to open the command prompt every time you need to access the Hudson. To install it as a windows service, click on “Manage Hudson” link and then click on “Install as windows Service” link. Now Hudson will prompt whether you like to access the Hudson which is installed as a service on your machine. Then it will restart. You can now close the command prompt you opened previously and try accessing it by http://localhost:8080/.
If the web page (Hudson dashboard) does not come, check the windows services (right click on MyComputer -> Manage -> Services) and make sure it is there. Stop the service and restart it, it will probably work when you try to access it again.
2. Configuration
As I mentioned earlier, Hudson is running based on pluggins, there is a link on Hudson dashboard where you can install the pluggings (you may notice that a number of pluggings have been listed) you want. Since we are interested in building .Net projects you may either use MSBuild and/or Nant to build your projects. ( I am using MSBuild)
2.1
To install the pluggings click on click on “Manage pluggings” link, select the MSBuild plugging and click to install. (This is the minimum requirement that you need to build .NET project from Hudson)
2.2
Then you need to configure MSBuild plugging: Click on “Configure System” link and fill the MSBuild name and Path to MSBuild fields on the page and click save.
Here you need to have the MSBuild.exe within your system. This is typically copied when you install visual studio or Microsoft.NET Framework SDKs. Since you are developing .NET project this may already within your system. Most probably on following locations depending on the version of .NET Framework you are using.
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
C:\Windows\Microsoft.NET\Framework\v3.5
If you successfully went through above steps, you have now configured the minimum requirements to build a .Net project, Why waiting let’s just add a project and build.
3. Adding a project
3.1
On Hudson dashboard click on New Job. Provide a meaning full job name (name of your project ).
Chose Build a free-style software project option and click ok. Here you may see a number of configuration options; you can leave most of them unchanged (since here I’m describing the basic and minimum requirements).
3.2
Under Source Code Management provide the URL of the repository. (I haven’t tried the option none here since my source code was already located in SVN). Note - For the sake of safe just install the Subversion plugging as well. This may be required if you are using SVN.
3.3
Under Build section click on the button “Add build step” and chose the Build a visual studio project or solution using MSBuild. Select the MsBuild Version (the combo box may list the available MSbuild names. You may see the entry you have added on step 2.2). Provide the MsBuild Build File in the text box given. This is the path to the .proj or .sln file that MSBuild will use to build.
That’s it click on save and return to dashboard. Now you will see the job that you have added on the top of the page.
4. Build
Click on the project name (you have created on step 3 will now appear as a link). And you will be taken to that project page, on the left hand side of the page you will find the button you expected. Why waiting click on Build Now. The results may appear in few seconds to few minutes depending on the size of your project. An entry will be added to Build History (left bottom of the page), click on that link and click on Console Output if you wish to explore what has happened throughout the build process.
Note
I have written this note in a hurry. By the time I am writing this I was thinking of exploring other features of Hudson, I have just succeeded building my first .Net project on Hudson and I thought it would be better to share this experience, because this will be helpful for a guy who is trying this for first time like me. I beg your pardon that I couldn’t insert any images of installation or configuration process and for the spelling and grammar mistakes. This was first blog I have written, I have no any idea of a writing style, but I written as I understood. Again I’m sorry, If a reader could not understand this after reading the whole document. Please feel free to mail and contact me in case of you met with a problem. I believe it’s my responsibility to answer those who meet with problems after reading this because they spent their time to read this article.
Susinda Perera
E-mail : susinda@gmail.com
References
A pretty good link to visit, has explain with images.