Tim Blair
Changing the Working Directory of <cfexecute> (12/07/2005)
This morning I was struggling with a <cfexecute> call to create a password protected ZIP file. I've got a nice UDF which uses the standard java.util.zip.* hierarchy of classes to create standard ZIPs, but unfortunately Java doesn't support encoded/password protected ZIPs. I found a nice command line ZIP program and got it building my protected ZIP for me. The only problem was that it always included the full path information for each file in the ZIP, and there was no flag for setting a new relative "root".
I figured that I could change the relative root by running the command directly form the directory I was trying to ZIP up, so the first thing I looked at was the <cfexecute> call — when I use that tag, where does is the command I run executed from? What's the "context root"? Well, in my case it was C:\CFusionMX\runtime\bin. Next question: is there any way to change this? Simple answer: no. More complicated answer: yes, in a round-a-bout kind of way...
When <cfexecute> runs it uses one of the exec() methods from java.lang.Runtime, which in turn calls some native functions to perform the actual execution of the command. By digging further into the various methods in this class I noticed that a number of the exec() methods provide the facility to provide an argument which sets "working directory of the subprocess", i.e. the relative root that I was looking for! A little more playing lead me to this generic solution for running a process from a given relative root, rather than the default:
Of course, this method does have it's drawbacks. Firstly, the child process is forked and control immediately returned to the controlling application, so there's no way of catching any errors from the process, or indeed any output. Also, and more importantly in my case, if the process creates a file which you rely on existing to keep processing in CF then you need some way of waiting until the file has actually been created. I created a small loop which checked for the existence of the file every 1/2 second for a maximum of 20 seconds — if it's still not there then we give up and say something's gone wrong.
This method doesn't have all the nicities of <cfexecute>, but does allow me to accomplish what I set out to do!
Article Archive (September '03 – '05)
- Private CFC Methods and "this" 01/09/2003
- Active Sessions Across CF Applications 12/09/2003
- isnumeric() - Too Clever for It's Own Good? 15/03/2004
- Modifying Page Generated Content 15/03/2004
- CF and Arrays of Basic Java Types 17/03/2004
- Writing UTF-8 Text Files with ColdFusion 13/05/2004
- Top vs. Bottom Posting 09/07/2004
- Local (var) Scope Shortcut 27/12/2004
- Using Apache mod_headers to Change Downloaded Filenames 16/06/2005
- Changing the Working Directory of
<cfexecute>12/07/2005 - Flickr Workshop Review 29/09/2005