Monday, February 18, 2013

Scripting on Linux

One of the best user contributed collections on unix scripting, available at The Linux Documentation Project. This has lots of illustrative and sometimes idiosyncratic examples which are better suited to learning than any other online site.

Friday, February 8, 2013

Inno Setup: Creating a scheduled Log Rotator

Setting up a rotation mechanism for log files on a Windows machine can be an interesting problem. This could be real easy on Linux using CRON but on Windows you may find the a tool called waRmZip (download from sourceforge or look at very useful. It works very well and you can set up a scheduler job to fire it at a predetermined time. To do this kind of thing in Inno Setup, use the code below:

function GetDoLogRotateTaskAddParams(Default: String):String;
  // This will use the Operation System SYSTEM account for running the task
  result := '/Create /RL HIGHEST /F /TN "MODULE Log Rotate" /SC DAILY /ST 23:59 /RU "" /TR "' + ExpandConstant('{sys}\cscript.exe \"{#InstallHomeDir}\Tools\waRmZip.wsf\" C:\Logs /gt:1MB /ma:1 /md:\"C:\Logs\Backup-$DAY\" /q');
  if Length(LogDeleteTime) > 0 then begin
    result := result + ' /da:'+LogDeleteTime;
  result := result + '"';  

This assumes that the waRmZip is installed using the following command:

Source: waRmZip.wsf; DestDir: {#InstallHomeDir}\Tools;

A Task scheduler can be created using the following "Run" command in Inno Setup:

Filename: "schtasks.exe"; Parameters: "{code:GetDoLogRotateTaskAddParams}"; Description: " Log Rotate Task"; Flags: runhidden; Check: GetDoLogRotateTask;

Automating FTP using WinSCP scripting

The tool WINSCP can be used for scripting ftp related tasks. These are especially useful in automating FTP related tasks in an installer. I am posting some sample code here which may be useful. The entire set of scripting capabilities can be obtained from the WINSCP website.

option batch on
option confirm off'
open ftp://:@

This script can then be invoked using the command as below: /console /script=

Inno Setup: Creating a Windows Scheduled Task

On some occasions, you may need to create a scheduled task in Windows using Inno Setup. Here is an easy way of doing this using the command "schtasks.exe". You should put that in the "Run" section in the script:

Filename: "schtasks.exe"; Parameters: "{code:GetDoModuleTaskAddParams}"; Description: "Module Job Task"; Flags: runhidden; Check: GetDoModuleTask;

function GetModuleTaskAddParams(Default: String):String;
  // This will use the Operation System SYSTEM account for running the task
  result := '/Create /RL HIGHEST /F /TN "Module Job" /SC DAILY /ST 23:59 /RU "" /TR "' + ModuleSubDir + '\' + ModuleFileName;
  result := result + '"';  

Thursday, February 7, 2013

Inno Setup: Deleting files during install

Deleting files selectively can be a daunting task with Inno Setup. Especially if the sequence presented is Backup the files, then delete them before the new ones are copied on top. In my previous posts I mentioned steps how to take a backup of files and here are some details on how to delete files from a particular folder or for that matter, based on a pattern. This may be necessary on several occasions:
  1. On a Windows system, especially some versions of the OS may be buggy. You copy new DLLs over existing ones and the system doesn't acknowledge - keeps using the old DLLs. Especially observed on some Windows 2003 Servers when the number of arguments in a function defined inside the DLL was varied and a new DLL copied over. This kind of thing happens rarely but when it strikes, you can spend hours star gazing. The solution is to delete the DLLs and copy new ones over.
  2. New files you are copying may be fewer and you dont want old junk in the folder.
Here it goes:

Step #1: Add a function call in the install directives. I will explain the arguments and why the complexity in a bit...

Check:DeleteFiles(ExpandConstant('{app}\\bin\*'), ExpandConstant('{#InstallHomeDir}\UnInstall\{#MyAppVersion}\Websites\\bin'));

Step #2: Create a function to delete the files. 

function DeleteFiles(pattern,dirToCheck:String):Boolean;
  // We will run ONLY if exists condition is satisfied
  if not DirExists(dirToCheck) then begin
    result := true;

  alen := GetArrayLength(DirArray);
  for i := 0 to alen -1 do begin
    if CompareText(pattern, DirArray[i]) = 0 then begin
      result := true;
  //MsgBox(pattern, mbError, MB_OK);
  DelTree(pattern, false, true, false);
  SetArrayLength(DirArray, alen+1);
  DirArray[alen] := Copy(pattern,0,length(pattern));
  result := true;

Importance of the second argument: You should know by now that Inno Setup calls all the Check functions BEFORE it calls any File directives. This means that if you are making any backups, the Check function above which deletes the files can delete the files BEFORE the backup ever happens. The second argument tells the function where to look if the files have been backed up before they are deleted. If the backup folder exists, that means the files must have been copied (you can extend that check any way you want). The array used in the delete function is also important. The delete must be done ONLY once before the code is installed. The function may be called again by InnoSetup and if the delete kicks in again, you can kiss your installed files goodbye!