ColdFusion in Context: Execute

Suppose you have an executable program whose output would help your Web site. Perhaps it communicates with another server via modem. Perhaps it's a specialized interface to a proprietary database. This tip shows how you can get ColdFusion to use that program to your advantage. Along the way, you'll learn how a custom tag's environment can make your life easier.

Set the Stage

To show off this technique, you'll need an executable and something for it to do. This demonstration uses the DOS "find" command to get information from a text file. (Yes, you could do this with ColdFusion directly, but other tasks aren't this easy.) Here's some sample text for the file; I call it facility.csv. (Make this easy on yourself. Paste it into a spreadsheet and save it with comma separated values.)

SQPERMITFACILITYCITYZIP
32AR0035459USA-COE ALPINE RIDGE REC AREAARKADELPHIA71923
33AR0036749ARKADELPHIA HUMAN DEVELOPMENTARKADELPHIA71923
34AR0035751ARKANSAS CITY, CITY OFARKANSAS CITY71630
35AR0046663MG INDUSTRIESARMOREL72310
36AR0045977NUCOR STEEL - ARKANSASARMOREL72310
37AR0049166IPSCO TUBULARS, INC.ARMOREL72310
38AR0046523MAVERICK TUBE CORPORATIONARMOREL72310
39AR0041742ASH FLAT, CITY OFASH FLAT72513
40AR0049379HANSON AGGREGATES WEST, INC.ASHDOWN71822
41AR0048411DOMTAR A.W. CORPORATIONASHDOWN71822

Control the Executable

The cfexecute tag is powerful, but it passes a single argument (or array of arguments) to the executable without using double quotes. This may not be enough for your purposes. The find command in particular refuses to function unless the search string is in double quotes, and cfexecute strips them from the argument string, no matter what you do. However, executing a batch file that provides the quotes to your real target does the trick as shown here.

If you want to find a single word, this code is OK as written. If you expect to search on a string of a maximum of, say, five words, then use "%1 %2 %3 %4 %5" instead of "%1". (Batch files permit a maximum of nine such parameters ; sorry.) This example names the executable, adds an "i" flag to make the search case-insensitive, sets a placeholder for a search string in double quotes, and names the file to be searched. Put this one-line command in a file called try.bat. (Don't give it the same basic name as a .exe file in the path unless you want to be unsure which file will respond.)

find.exe /i "%1" c:\mydirectory\facility.csv

Set Up a Custom Tag Environment

The output of the cfexecute tag goes either to the screen or to a file. You would probably prefer to send it to a variable. One way to do this is to wrap it in a dual custom tag.

When you call a custom tag using separate opening and closing tags (such as <cf_channel> and </cf_channel>), any output that occurs between them is copied to a variable named "ThisTag.GeneratedContent". (Yes, the prefix name needs to be "ThisTag", not the real name of the tag itself.) If you prefix a variable with "caller" (as in "caller.yourvariable", then the calling page can see "yourvariable" (for example) even though it's inside the custom tag. Therefore, calling this one-line tag I've named channel.cfm returns the output of anything it's wrapped around to a variable named "Answer".

<cfset caller.Answer=ThisTag.GeneratedContent>

Call the Executable from ColdFusion

Here's the actual call to the batch file. It names the batch file and sends the search string from the page that calls this one as a single argument to the batch file. Wrapping it in the <pre> tag preserves the linefeeds returned by the find command. (This will make subsequent parsing easier when you decide to do that.) The command is set to time out in two seconds. Name this code find.cfm.

<cfparam name="Question" default="arkadelphia">
<pre>
<cfexecute
name="c:\mydirectory\try.bat"
arguments="#Question#"
timeout="2">
</cfexecute>
</pre>

Put It All Together

This code can be named anything; I named it execute.cfm. If you put the search term "Question" in a form field or in the URL (for example, execute.cfm?Question=arkadelphia, it will override the default search string given here. The string is being sent to find.cfm, not the custom tag itself; so, the attributes prefix usually used to make information from the calling page visible to a custom tag is not needed here. The cf_channel tags put the output of find.cfm into the variable named "Answer". For this code to work, you must put the page named channel.cfm in the current directory or in the directory for custom tags; ColdFusion truncates the "cf_" to find the name of the page containing the custom tag. The cfsilent tags keep the output from reaching the screen. For this demonstation, the variable is then output flanked by exclamation points to prove that what reaches the screen is indeed from a variable that you could choose to parse or make decisions from.

<cfparam name="Question" default="arkadelphia">
<cfsilent>
<cf_channel>
<cfinclude template="find.cfm">
</cf_channel>
</cfsilent>
<cfoutput>!#Answer#!</cfoutput>

In just a few short lines, you can extend ColdFusion through the use of executables. Share ways to use this technique with the rest of us. =Marty=