Archive › September, 2009

Word-wrap on a Flex field component

Make sure that you set the width of your field explicitly, or there will be no word wrap for you.

Some other guys found another workaround that gets around explicit widths, but it also looks fragile.

Anyway, if this comes up in a google search, I’ll have saved someone else some time. :)

Comments ( 2 )

I want to like Microsoft…

But they make it so hard.

Fail.

Comments ( 1 )

Help Authoring Tools – why are they so ugly?

Tonight I was looking at various Help Authoring Tools: RoboHelp, Madcap Flare, and others I forget. So far I haven’t been impressed with the look and feel of any of their output. I want attractive help that looks like Adobe’s, or Apple’s, or even Microsoft’s MSDN.

I guess I could spend some time figuring out which one lets me style it the best using CSS. I’m especially surprised that Adobe’s Robohelp doesn’t come with something better out of the box. It’s Adobe for goodness’ sake!

Comments ( 0 )

I’m switching from Firefox to Safari

Forever now, Firefox has always eaten up my CPU when idle. At the best of times, on my Windows or Mac machine, Firefox eats up approx 5% of my CPU, and it’s usually more like 10%. That’s the best of times. Often, I’ll wonder why my computer is crawling and look to see that Firefox is eating 20% or so, if not more. It could be a plugin I’m running, but I’ve tried disabling them to no avail. I have GMail open continuously, and after a few hours, Firefox seems to eat more and more CPU and memory. It all points towards a memory leak Javascript, but I’m no expert. Anyway, after a bit of experimenting with Safari, it doesn’t seem to exhibit such behavior. I haven’t done a long-term test, but after watching its CPU stay low, and my webpages load faster, I’m willing to do a long-term experiment. Here’s hoping…

Comments ( 0 )

Monitoring a file for changes in Adobe AIR

In a previous post, I was wondering what the best way would be to monitor a file for changes in AIR. It’s needed in order to monitor the flashlog.txt file that I want to use for crash reporting. Just came across this helpful post from Mike Chambers on Adobe Feeds. It turns out that the nice guy added a FileMonitor class to as3corelib. Cool!

Comments ( 0 )

AIR Exception Handling/Crash Reporting (cont)

I just verified that my technique as previously described works regardless of whether my AIR’s .swf file is debug or release. In release builds, I don’t see trace output in flashlog.txt, and I no longer see line numbers in my stack trace. Whew…I got nervous when I realized I was running debug swfs in last night’s tests, and am relieved to see that it still works.

Also, I verified that the Windows VM that I am testing on does not have the debug Flash player installed. That was another thing that occurred to me today as a potential hitch in the plan. I don’t know how AIR interacts with the installed Flash player, if at all, but I thought for a moment that in order to do logging, perhaps AIR required a debug version of Flash to be running. Nope! :)

So, who can tell me where I should put the code to check the log file to see if it’s been updated? I’m assuming some sort of timer so that I can check its modified date on a regular basis? If I see it’s been updated, I read it and see if there are any Error messages to be reported. I guess this approach might be strange if the computer on which my AIR app is one with the existing debug Flash runtime, and a developer who is already logging to that file. I’ll have to verify that the error written to the log file is mine before popping up the error dialog.

Comments ( 0 )

Global Exception Handling / Crash Reporting in Adobe AIR – Partially Solved?

EDIT: Jan 24th, 5:18pm (GMT+1): I am late to add this edit, but much of this post is now obsolete. Adob added Global Exception Handling to AIR 2.0. As far as I know, you won’t be able to get a stack trace if you’re not running in debug mode, and that’s a bummer, but it’s great to be able to catch unhandled exceptions now!

——

As I’ve been developing YNAB 3, I’ve been pulling my hair out to figure out a way to add crash reporting to our application. YNAB Pro, our popular C# app has it, and it’s saved us so many times I can’t even tell you! Our bug reporting system has a log of every crash we’ve ever had in the field, complete with a stack trace and user comments. I’m proud to say that we don’t get many, but when we do, it’s trivial to write back and explain how they can fix it.

Adobe doesn’t think this is important

Coming from the C# world, I thought it would be easy: Just put a try/catch around the main block, and then catch unhandled exceptions, pop up a dialog, and be done! Well, amazingly, you can’t catch unhandled exceptions in Flex/AIR. Yeah, you read that right. You can’t. The #1 voted on bug in their Flex database, with 415 votes as of now, is (to paraphrase) “Please add global exception handling“. Coming in at 160 votes is, to paraphrase again, “Please oh please add global exception handling!“. There seems to be a lot of silence from Adobe on these issues. They’re not prioritized high, and no one ever really comments on those bugs. It’s kinda weird to be honest….

Why it’s worse than you think

Anyway, the way it works is this: The Flash player intercepts exceptions like this and handles it for you. “That’s okay,” you’re thinking. “As long as my user knows something went wrong, I won’t have automatic exception handling, but at least they’ll know to email me when they see the error dialog.” What I haven’t mentioned yet is that there IS NO ERROR DIALOG on the runtime installations of the Flash player or in the default installation of Adobe AIR. Yep: When your shiny component throws an exception deep in the bowels, your users will know something went wrong because the app might start acting “strange” a few minutes later for who knows what reason. Some people in the Flex world get around this by telling their users to install the debug player of Flash. Even though that would be a crazy solution, I don’t have that luxury since we’re deploying in Adobe AIR.

Why it’s even worse than that

Thanks to Doug McCune’s excellent post on this topic, I saw that someone was Monkey Patching their Flex libraries to add some code to try and catch most errors. That got me thinking: “I’ll just monkey patch a low-level class like SystemManager to intercept most of the event dispatches and make sure I have a try-catch around it!” That’s all well and good, except that if an exception happens as the result of a “EventDispatcher.dispatchEvent”, your code will never know that an exception happened. That’s because the flash player is in charge of that handy dispatchEvent method, and it will happily swallow up your exception, display nothing to the user, and return the code to you as if nothing happened. (In case you’re wondering, the return value of dispatchEvent is still “true” even though it failed due to an exception). I learned all about this from Luke Bayes‘ excellent blog post on the topic.

Yep, still worse

At one point I thought that I’d just turn logging on and watch where my application’s error output was being sent. If I see an error, “BAM!” crash report time! From everything I’d read, the only way to get logging was with a debug flash player. AIR doesn’t have a debug version (or so I thought), so that looked like a dead end.

Some light at the end of the tunnel

I found out about Luke’s post from Jörg Birkhold’s post about his cool discovery that you can easily catch exceptions that are a result of “callLater” functions. That’s awesome, and it’s going to make this job 50% easier. You don’t even have to monkey-patch. So, that takes care of “callLater”, which will take care of a lot of the drawing code and plenty of other behind-the-scenes stuff that I don’t quite understand. That still doesn’t cover exceptions as the result of a dispatched event though, which means an uncaught exception as the result of user input is going to be ignored…

I’m getting desperate here…

Since the current dispatchEvent function swallows our exceptions, and a lot of our unexpected exceptions will be in response to events like mouse or keyboard input, maybe there is a way I can make the SystemManager use my own dispatchEvent method so I don’t have to rely upon the one built into Flash Player. Nope. You can’t implement your own IEventDispatcher without using EventDispatcher.dispatchEvent. It’s a good thing – that solution was going to be messy…

Popping up error messages in the release version of AIR!

When re-reading Doug’s post I saw my comment at the bottom that said, ‘For our beta testers (who are obviously more hardcore), I plan on using this cookbook trick to get it to pop up the error dialog: http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postid=13206&loc=en_US&productid=4

I had forgotten all about that! Turns out that if you drop an empty file called “Debug” into your application’s META-INF/AIR folder, AIR will happily pop up an ActionScript error box, complete with stack trace, in case of an exception. Zavi discovered this by using Procmon, which is an excellent tool.

An app can set its own debug flag

So first I decided to see if the application itself could write that debug file out itself on startup. The answer is:
Macs: Yes
Windows XP: Yes
Vista and up: No!

Vista and Windows 7 have strict permissions around writing to Program Files, so that’s not going to work, but let’s just punt on that for now. So sure enough, I’ve got it writing the magic debug file at startup in the Application’s creationComplete event handler. Unfortunately, it appears that by the time the app can write this file out, AIR seems to have decided whether or not it’s in debug mode (not 100% confirmed yet), so if this goes into production, the app would have to restart itself when it first launches, but that would be doable. Even if I wrote the code in the first line of SystemManager, the AIR runtime is bootstrapped by then, so I doubt there is a way around this. On Windows, I think an external process is going to be required to install this file, but if you’re talking about hardcore beta testers, that might be okay.

Wait – that probably means we can turn on logging!

Something Zavi said in his post about that putting the AIR player into debug mode got me thinking: What if it really is just the Flash player running in debug? That means I might be able to turn on logging! I fired up ProcMon myself and sure enough, there were some beautiful calls to try and read mm.cfg, the Flash Player debug configuration file. I my mm.cfg in the right location for XP and told it to log traces and errors.

[code lang="as3"]ErrorReportingEnable=1
TraceOutputFileEnable=1[/code]

I fired my test app up again (one that throws an exception right when it launches), and I saw not only did I get a popup telling me about the error, but I simultaneously got the entire stack trace written out to the flashlog.txt log file! I also verified that the AIR app can read from the flash log file as it’s running. Now that I can watch the flashlog.txt file for changes, I have a way to detect with certainty if there is ever an exception anywhere in an AIR app. I need to turn this into a library and clean code, and it’s possible that I’m overlooking something, but with this, coupled with Jörg’s callLater handling, and I think we have all of the bases covered.

So, what risks am I running by running the app in debug mode? How big of a performance hit are we talking here?

I’ll post more as I finish up the code to verify that this works, but when YNAB 3 goes into beta, I think we’re going to have a way for people to automatically submit bugs, and I can’t tell you how releaved I am about that!

Comments ( 8 )

File.applicationDirectory.resolvePath – Can’t get to the relative parent

I was banging my head against a wall trying to do this in a unit test:
var file : File = File.applicationDirectory.resolvePath(“./../src/test/SomeFile.txt”);

Turns out that you can’t get to the relative parent of the applicationDirectory though. Flex/AIR has abstracted that away from you, presumably to prevent you from looking in places you shouldn’t. (Edit: I no longer believe that, as you can easily get to any arbitrary folder you want via the File constructor.) So, I just told the project to copy non-embedded assets to the output folder, and now as long as the files for my tests are located somewhere in one of my source folders, I can reference the test files I want relative to the applicationDirectory.

UPDATE: Thanks to Jijith chandran for making the following suggestion and spelling out how to use the File constructor:
You can get it using the following
[code lang="as3"]

new File(File.applicationDirectory.nativePath).resolvePath(”./../src/test/SomeFile.txt”);

[/code]

Comments ( 4 )

Automatic Flex Formatting

There is a cool MXML and Flex AS3 automatic code formatter that some cool guys published on SourceForge.

I was having a hard time getting it installed the manual way, so here is the easy way:
1) In Flex Builder (standalone or Eclipse), go to Help->Software Updates->Find and Install
2) Choose “Search for new features to install”
3) New Remote Site
4) Name it whatever you want and use this as the URL:
[code lang="as3"]http://flexformatter.googlecode.com/svn/trunk/FlexFormatter/FlexPrettyPrintCommandUpdateSite/[/code]

Now hit next a couple of times and you should see it downloading and installing. It will recommend that you restart (good advice), and then you’ll know if it installed because a) you’ll have some new toolbar buttons, and b) you’ll have a new “Flex Formatting” option in “Flex Builder->Preferences”

Good stuff!

Comments ( 0 )

To open aum.flexbuilder.osx, you need to install Rosetta.

Is anyone else getting the above error message when starting up Flex Builder on Snow Leopard? It appears to load/run just fine in spite of this warning, but it would be more fun if it wasn’t there at all…

Comments ( 0 )