I have a function which generates an Excel file (using ColdFusion's spreadsheet functions) and stores the result as ReportContent.
I need to mail that report to a group of people using <cfmail>:
<cfmail from="#From#" to="#To#" subject="#Subject#" type="html" >
<cfmailparam content="#ReportContent#" type="application/vnd.ms-excel" file="#FileName#" >
#Body#
</cfmail>
My problem is that, in testing, I found that the <cfmail> command would often execute before the Excel file was fully rendered, attaching instead an unusable .tmp file.
I tried to handle this by pausing execution for 5 seconds, giving the Excel file time to render:
<cfscript>
thread = CreateObject("java", "java.lang.Thread");
thread.sleep(5000);
</cfscript>
This worked in most cases, but was not effective 100% of the time. I have now kicked up the delay to 15 seconds -- which works for my current tests, but I'm not convinced it is the best strategy.
Is there a way to confirm that the Excel file in ReportContent is fully rendered before calling <cfmail>?
Use a named lock like this, and see if it helps:
<cflock name="some_preferably_unique_lock_name" type="exclusive" timeout="60">
<!--- code that creates and writes the Excel file to disk --->
</cflock>
<cflock name="same_preferably_unique_lock_name" type="exclusive" timeout="60">
<!--- code that mails the Excel file as attachment --->
</cflock>
Related
I tried to run test.bat file using cfexecute. It shows timeout error after loding for sometime. The output file is blank. But when i double click the test.bat file it works fine. My code is this,
<cfexecute name="C:\Windows\System32\cmd.exe" arguments="/C C:\ColdFusion2018\cfusion\wwwroot\test.bat" timeout="60" outputfile="C:\ColdFusion2018\cfusion\wwwroot\log_output1.txt"></cfexecute>
We recommend using CFX_EXEC (Windows) instead of the built-in CFExecute. When running BAT files, we've encountered many cases where we needed to run it under a separate Windows account that had privileges different than the CF Service. CFX_EXEC enabled us to specify the specific account whereas CFExecute doesn't have the option at all. We also use CFX_EXEC for performing IP/DNS look-ups as it's a lot faster than Java, honors TTL and doesn't cache the lookup results "forever".
If you want to run test.bat using cfexecute, test.bat should be the value of the name attribute, not the arguments attribute.
<cfexecute name="C:\ColdFusion2018\cfusion\wwwroot\test.bat"
timeout="60"
arguments ="whatever applies"
outputfile="C:\ColdFusion2018\cfusion\wwwroot\log_output1.txt">
</cfexecute>
Thanks for your response,
The batch file successfully executed after suppressing the 'Press any key to continue..'(pause) in the command line. It makes the cfexecute loading till timeout. That was the issue here.
All I get in my browser is a blank screen. If I don't use IsDefined, I would get an error in the page stating the variable doesn't exists.
If I misspell a command (example: using /bin/bsh instead of /bin/bash), I get an exception stating CF cannot find the program. So it seems to be working. I just want to check if it's really running.
Here's my code:
------
<cfexecute name="/bin/ls" arguments=" -la /" errorVariable="error" variable="result"></cfexecute>
<cfif IsDefined("result")>
<cfdump var="#result#">
</cfif>
<cfif IsDefined("error")>
<cfdump var="#error#">
</cfif>
<cfexecute name="/bin/bash" arguments=" -c '/bin/ls -la /'" errorVariable="error" variable="result"></cfexecute>
<cfif IsDefined("result")>
<cfdump var="#result#">
</cfif>
<cfif IsDefined("error")>
<cfdump var="#error#">
</cfif>
You need to specify a timeout on cfexecute in order to get a valid result/error sequentially.
The default timeout is 0, which is non-blocking, which means your command is executing asynchronously. This means you don't immediately have a result.
I'm not sure whether, to Adobe, "non-blocking" means the variable and error attributes are ignored completely or eventually set. If you're curious you could toss in a cfsleep and find out, just please not in production. :)
You have to specify the Absolute path of the application to execute.On Windows, specify an extension, for example, C:\myapp.exe.
I've run the my sqlCMD by using cfexecute, Here I've passed the absolute path of an MS sql server.
<cfexecute name="C:\Program Files\Microsoft SQL Server2016\Client SDK\ODBC\130\Tools\Binn\SQLCMD.EXE" arguments=" -S localhost -U sa -P sqlPwd#12## -i" timeout="0" errorFile="#logsDir#/#TableSqls.name#_error.txt">
</cfexecute>
I hope it's will help you.
I have the following script in coldfusion 9:
<cfimage action="info" source="E:\....\image.png" structname="local.imageInfo">
The image is on a local drive. This action takes up about 4 seconds. File is about 800kb in size (300 dpi, png). This seems abnormal to me. Is there a way so speed this up? I only need the with and height of the image.
Btw doing a simple read action on the image is performed instantly
<cffile action="read" FILE="E:\....\image.png" VARIABLE="local.imageread">
If you are using Windows and ColdFusion 8+, consider using the free, portable command-line programs Exiv2 and GraphicsMagic. Exiv2 can read/write EXIF data using the command line and is faster than built-in CF functions.
http://www.exiv2.org/
GraphicsMagick is much faster at converting, resizing, cropping, rotating, generating thumbnails, not throwing an error when reading a CMYK image, etc.
http://www.graphicsmagick.org/
I've written ColdFusion 8-2016+ custom tags as wrappers for both portable command-line programs.
http://gamesover2600.tumblr.com/post/139435793234/coldfusion-udf-for-exiv2-faster-exif-image
<CFSET ImageFilePath = "c:\test.jpg">
<CFDUMP VAR="#Exiv2(imageFilePath)#">
http://gamesover2600.tumblr.com/post/125766251344/graphicsmagick-coldfusion-custom-tag
<CFSET ImageIn = "c:\test.jpg">
<!--- Identify - Get basic info (Exiv2 is better/faster) --->
<CF_GraphicsMagick action="Identify" infile="#ImageIn#" result="GM_Identify">
<CFDUMP VAR="#GM_Identify#" label="GM_Identify">
<!--- Optimize (common settings to reduce filesize) --->
<CF_GraphicsMagick action="Optimize" infile="#ImageIn#" outfile="#replace(ImageIn,'.jpg','_optimize.jpg')#" result="GM_Optimize">
<!--- ResizeWidth (Resize to defined width --->
<CF_GraphicsMagick action="ResizeWidth" infile="#ImageIn#" width="200" outfile="#replace(ImageIn,'.jpg','_resizeWidth.jpg')#" result="GM_ResizeWidth">
<!--- AspectCrop (Similar to ImageUtils.cfc) --->
<CF_GraphicsMagick action="AspectCrop" Infile="#ImageIn#" outfile="#replace(ImageIn,'.jpg','_aspectCrop.jpg')#" width="100" height="100" quality="90" result="aspectCrop">
I'm pulling my hair our here and really can't figure out why this code will not work. I need to use <cffile action="write"> to put a document on the server.
I've stripped the code to its bare minimum in an attempt to get the file to write to the server, however it still won't budge. The code I am running is this.
<cffile action = "write"
file = "test.txt"
output = "Content"
>
When I run this code on the server, it does nothing. I get no error messages on-screen, however no file appears on the server either.
I've been searching for a while and the only thing I could seem to come up with was writing the absolute file path, so I've also tried this too
<cffile action = "write"
file = "http://www.my_url.com/test.txt"
output = "Content"
>
Which does get me an error message (see below), however searches for how to sort this error message have been less than useful.
An error occurred when performing a file operation write on file
http://www.my_url.com/test.txt.
The cause of this exception was: java.io.FileNotFoundException:
http://www.my_url.com/test.txt.
I thought this could be a problem with my privileges, however there is no 'access is denied' error on the end of the FileNotFound, so I really am lost as to what to do.
It's doubly infuriating because on this exact site I am also using <cffile action="upload"> which works absolutely fine!
As mentioned above, cffile only operates on the server file system. So you need to use a physical file path, not a url. Also, the documentation says if you use a relative path the file is written to:
"...(a path) relative to the ColdFusion temporary directory, which
is returned by the GetTempDirectory function."
So if you did not receive an error, the file was created, just not where you expected. To avoid this kind of confusion, use absolute paths:
<cffile action="write" file="c:/path/to/test.txt" output="Content">
<cfset LOCAL.cmd = expandPath('..\library\gm.exe') />
<cfset LOCAL.args = "convert image1.jpg image2.jpg" />
<cfexecute variable="gm" errorVariable="error"
name="#LOCAL.cmd#"
timeout="10"
arguments="#local.args#" />
<cfdump var="#gm#" />
This code always results in an empty string in gm. No matter how I execute gm with or without parameters. Other examples work fine like running cmd.exe or netstat.exe as is in the CFDocs example. I get no errors thrown or warnings in errorVariable, it simply does nothing.
I modified the code, this version does not work either:
<cfset LOCAL.cmd = expandPath('..\library\gm.exe') />
<cfset LOCAL.args = "convert ""#variables.uploadDirectory##LOCAL.file.source#"" ""#variables.uploadDirectory#optimal-#LOCAL.file.source#""" />
<cfexecute errorVariable="error"
name="c:\windows\system32\cmd.exe"
timeout="10"
outputFile="#expandPath('.\gm.log')#"
arguments="/C #local.cmd# #LOCAL.args#" />
Permissions problems are the most common cause. However, if you are running CF8, you might also try redirecting the error stream and adding an explicit terminate flag. Just to see if you get any output or see different behavior. Early versions did not capture the error stream, which caused some processes to hang. It was fixed in one of the CF8 updaters.
Update: I just noticed your image paths are relative. Perhaps the program is having difficulty locating them. Try using absolute paths for the images.
Update: I tested it with CF9. It does work when using absolute image paths. Though the "gm" variable is understandably empty, since the output is directed to an image file.
<cfexecute variable="gm"
errorVariable="errorOut"
name="C:\GraphicsMagick-1.3.12-Q16\gm.exe"
timeout="10"
arguments="convert c:\art.gif c:\artCopyFromCF9.gif" />
<cfdump var="#variables#">
Without seeing code or your server setup, I would guess you need to check permissions for the user account CF runs under.
If CF is running under the default user, you may need to create a user with access to whatever it is you are trying to do. Then change the service(s) to run under this user. Alternately, you could assign more liberal permissions to the resource you're trying to access.
I have also encountered this with cfexecute and GraphicsMagick. I think the deal is that GM is operating asynchronously and returns before it completes. Running some tests with outputFile/errorFile instead of their variable equivalents, followed by cffile reading the fileInfo on the output file (which is empty per the test script but observed to have contents when opened), I see that the modified time of the output file with contents is actually after the last modified timestamp yielded by FileInfo.
I think if you output to a session variable or something of the sort that could be picked up by another template you could observe the results of the execution having populated the session variable, provided the other template executes after the variable is actually set.