web development

Error #0 on AIR application installation

I got this errormessage on “some” places while trying to install an AIR application package, while other places just worked fine.

The application could not be installed. Try installing it again. If the problem persists, contact the application author. Error #0

The first step debugging this was to find out where the AIR application installer logs errors – which by default he does not. To activate installer logging, you have to put two files in your home directory (C:\Users\youraccountname\ on Vista or C:\Documents and Settings\youraccoutname\ on XP) called .airappinstall.log and .airinstall.log.

If those two files are present, the logging writes to them automagically.

The error I found there looked like this:

Installing C:\Dokumente und Einstellungen\***\Lokale Einstellungen\Temp\fla12.tmp\setup.msi
Error occurred; beginning rollback: [ErrorEvent type="error" bubbles=false cancelable=false eventPhase=2 text="1603" errorID=0]

From here on I was very sure that it has to do with privileges… (No, there is no context menu entry on AIR packages to “install as Administrator” or “run as”…)

Finally, I checked the windows event log, and found this:

Product: *** -- Error 1925. You do not have sufficient privileges to complete this installation for all users of the machine.  Log on as administrator and then retry this installation.

Why can’t they show this error at the installer instead of error #0?…

Yes, installing as Administrator solved the problem!

Balsamiq Mockups – impressive software with an even more impressive story

mockups_fpaSince the first time I have seen Balsamiq Mockups, it rocked my world. It is now a pleasure to create mockups. With Mockups, this is a fast and intuitive process, for everyone. Yes, I like this tool as a developer, and I am sure that any non-developer will also like it as much!

There are a lot of shapes one can choose like a browser window, iphone window, any other window, webcontrols, etc. The result can be exported as PNG or saved as XML. With XML files one can even diff/merge mockups ;)

Short overview:

  • Create software mockups in minutes
  • Collaborate with your team
  • Focus on creating your product

The guy/company behind Mockups, Giacomo ‘Peldi’ Guilizzoni, is even more impressive. There is a very good interview over at 37 signals (see Sources):

“I never really understood the concept of building a company with the goal to sell it, or why one should have an ‘exit strategy.’ I just don’t get it. If you’re doing what you love, why would you want to ‘exit’? Maybe it’s because I am Italian, but I see nothing wrong with a business staying small in the long run. As long as we do great work, are happy to do it, and make people happy with it, I see no reason to change anything.”

Thank you again for the kind response to my email, Balsamiq Team, and the chance to review this very nice (and therefore rare) piece of software.


Uncompressing Zip-files with subfolders in AIR applications via JavaScript

I am currently building an AIR application with JavaScript (jQuery + jQuery UI), one function downloads zipped files and has to extract the contents somewhere to the local filesystem. Since the files may contain subfolders, i didn’t find any working example supporting subfolders in the docs or via google.

I found an Adobe Tutorial for basic Zip files (see Sources), and after reading the zip specs there was just one small change to their code to get it working with subfolders.

The spec says that entries in the zip file which are directories just end with an ‘/’. Skipping them is the whole magic. (see line 48)

Thankfully, the air.FileStream autocreates director ies, so writing the files to the subfolders does not need any change to the code. I added a basepath as parameter to the outFile function, to complete the for me intuitive function unzipFile(sourceFile, targetPath).

Here is the code:

 function unzipFile(sourceFile, targetPath)
	var bytes = new air.ByteArray();
	var fileName = new String();
	var flNameLength;
	var xfldLength;
	var offset;
	var compSize;
	var uncompSize;
	var compMethod;
	var signature; 

	var zfile = air.File.applicationStorageDirectory.resolvePath(sourceFile);
	var zStream = new air.FileStream();
	zStream.open(zfile, air.FileMode.READ);
	bytes.endian = air.Endian.LITTLE_ENDIAN;

	while (zStream.position < zfile.size)
		// read fixed metadata portion of local file header
        zStream.readBytes(bytes, 0, 30);

		bytes.position = 0;
        signature = bytes.readInt();
        // if no longer reading data files, quit
        if (signature != 0x04034b50)

		bytes.position = 8;
        compMethod = bytes.readByte();  // store compression method (8 == Deflate)

		offset = 0;    // stores length of variable portion of metadata
        bytes.position = 26;  // offset to file name length
        flNameLength = bytes.readShort();    // store file name
        offset += flNameLength;     // add length of file name
        bytes.position = 28;    // offset to extra field length
        xfldLength = bytes.readShort();
        offset += xfldLength;    // add length of extra field

		// read variable length bytes between fixed-length header and compressed file data
        zStream.readBytes(bytes, 30, offset);

		bytes.position = 30;
        fileName = bytes.readUTFBytes(flNameLength); // read file name 

		if (fileName.substr(fileName.length - 1, 1) != '/')
			bytes.position = 18;
			compSize = bytes.readUnsignedInt(); // store size of compressed portion
			bytes.position = 22; // offset to uncompressed size
			uncompSize = bytes.readUnsignedInt(); // store uncompressed size 

			// read compressed file to offset 0 of bytes; for uncompressed files
			// the compressed and uncompressed size is the same
			zStream.readBytes(bytes, 0, compSize);

			if (compMethod == 8 ) // if file is compressed, uncompress
			outFile(targetPath, fileName, bytes); // call outFile() to write out the file

This is the outFile function which writes the uncompressed files to the local file system.

 function outFile(baseDir, fileName, data)
    var outFile = air.File.applicationStorageDirectory;
    outFile = outFile.resolvePath(baseDir+air.File.separator+fileName);
    var outStream = new air.FileStream();
    outStream.open(outFile, air.FileMode.WRITE);
    outStream.writeBytes(data, 0, data.length);


Running AIR Applications straight from Eclipse (Windows) without plugins

1. Run > External Tools > External Tools Configurations…

2. Add new (External Program) Configuration

3. Main Tab:


  • Location: Point to your Adobe Air SDK\bin\adl.exe
  • Working Directory: Point to your project folder (i did this via variable in the screenshot)
  • Arguments: your main application configuration, usually application.xml

4. Finished. Run!

If you don’t see the “Program” entry in 2), check if your eclipse filters it here: