My Projects
Search Blog

Categories
Archives
Useful Links
Photo Albums
RSS

Powered by
BlogCFM v1.15

Vivio Technologies CFML Hosting
15 June 2008
Creating IIS Virtual Directories with Coldfusion 8 and .NET integr

Ever had a need to automate the creation of virtual directories in IIS?  Coldfusion 8 can do this quite well using the System.DirectoryServices.DirectoryEntry class in the .NET framework.

After a whole lot of trial and error, this is what I came up with and it seems to work quite nicely:

 

<!--- get the server ID for the specific web site
    from IIS.  The default web site is usually "1"
    --->
<cfset serverid="2017647531">

    <!---
        //  metabasePath is of the form "IIS://<servername>/<service>/<siteID>/Root[/<vdir>]"
        //    for example "IIS://localhost/W3SVC/1/Root"
    --->
<cfset metabasePath = "IIS://localhost/W3SVC/#serverid#/Root">

<!--- name of the virtual directory --->
<cfset vdirName = "vdir001">

<!--- physical path for this virtual directory --->
<cfset physicalPath = "D:\Inetpub\ricktest\realdir">

<!--- full path to the System.DirectoryServices.dll --->
<cfset dllPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.DirectoryServices.dll">

<!--- instantiate a DirectoryEntry .NET object --->
<cfobject
    type=".net"
    class="System.DirectoryServices.DirectoryEntry"
    assembly="#dllPath#"
    name="site">

<!--- initialize the object with the metabase path --->   
<cfset site.init(metabasePath)>

<!--- you need the classname for later --->
<cfset className = site.Get_SchemaClassName()>

<cfif reFind("VirtualDir$",className) gt 0>
    <!--- Get the children so we can add a new child --->
    <cfset vdirs = site.Get_Children()>
    <cftry>
        <!--- add the new virtual directory --->
        <cfset newVDir = vdirs.Add(vDirName, className)>
        <cfcatch type="any">
            <cfoutput><h3>Failed to create #vDirName#</h3></cfoutput>
            <cfif cfcatch.ToString() contains "already exists">
                <p>Another directory with that name already exists.</p>
            <cfelse>
                <cfoutput><p>#cfcatch.ToString()#</p></cfoutput>
            </cfif>
            <cfabort>
        </cfcatch>
    </cftry>
    <Cftry>
        <!--- set the PAth property to the physical directory path --->
        <cfset newVDir.Get_Properties().Get_Item("Path").Set_Value(physicalPath)>
        <!--- commit the changes --->
        <cfset newVDir.CommitChanges()>

        <cfcatch type="any">
            <cfdump var="#cfcatch.ToString()#">
            <cfdump var="#cfcatch#">
            <Cfabort>
        </cfcatch>
    </cftry>
</cfif>


 

 

Posted by rickroot at 9:08 AM | Link | 4 comments
04 June 2008
JavaCSV for creating large CSV and other delmiited files with Coldfusion

In an effort to resolve memory and performance problems with generating large CSV and tab delimited files in an application I wrote at Duke, I started hunting around for solutions.

Initially, I was using the java stringbuffer method, but found that it's really hard to be sure that CF doesn't use String objects, especially when doing things like calling out to an external function to perform formatting (ie, if the field is a string, then surround it with double quotes and escape any internal double quotes).

A simple file drop of 7200 rows and 140 columns took 68 seconds and sucked a lot of memory.  And no, it wasn't the file writing that caused the problem, it was the call out to the formatting function.

If I performed the same drop using the tab delimited format, I didn't have to call out to that function, but the drop still took 30 seconds.  I needed it to be faster because some of the drops my users perform are much much larger.

so I started hunting around for a java-based solution and found the JavaCSV library:

After installing this library in my C:\Jrun4\servers\myInstance\cfusion.ear\cfusion.ear\WEB-INF/cfusion/lib directory and restarting Coldfusion, I was able to use the following code to generate my CSV files:

<cfset var fileOutput = createObject("java","com.csvreader.CsvWriter")>

<cfset fileOutput.init("#expandPath("..")#\drops\#filename#")>

<cfif format eq "TAB">
     <cfset fileOutput.setDelimiter( javacast("char", "     ") )>
</cfif>

<!--- write header --->
<cfloop from="1" to="#numFields#" index="i" step="1">
     <cfset fileOutput.write( fieldsArray[i] ) >
</cfloop>
<!--- end of header row --->
<cfset fileOutput.endRecord()>
<!--- loop through results --->
<cfloop query="resultSet">
     <!--- write record --->
     <cfloop from="1" to="#numFields#" index="i" step="1">
          <cfset fileOutput.write( resultSet[fieldsArray[i]][resultSet.currentRow].toString() )>
     </cfloop>
     <!--- write end of record --->
     <cfset fileOutput.endRecord()>
</cfloop>
<cfset fileOutput.close()>

The same drop which had previously taken 68 seconds now only took 18 seconds - AND used considerably less memory.

As you can see, the code handles both CSV and tab-delimited formats AND handles the proper escaping of strings containing delimiters as well.

Posted by rickroot at 8:03 AM | Link | 1 comment
03 June 2008
cfsavecontent vs. cfset for performance improvement

Many CF programmers out there know that coldfusion uses java string objects to store its variables usually.  And since java strings are "immutable", every time you change it, a new string is created.

If you find yourself doing huge amounts of string concatenations, you'll often see people suggesting that you look up the java StringBuffer object and use that instead.  That would allow you to append to a single StringBuffer object rather than creation a million string objects.

But there's another solution, apparently.

CFSAVECONTENT is so ridiculously fast compared to the old string concatenation method with CFSET that it has got to be using a StringBuffer behind the scenes.  At least, that's what I'm thinking.

Take the following code, for example.  On my local machine, the CFSET method took 64 seconds to complete.  The CFSAVECONTENT method completed in a mere 203ms.

Also, the memory consumption of the CFSET method was significant, while the CFSAVECONTENT method was hardly noticeable.

 

<cfsetting enablecfoutputonly="yes">
<cfsetting requesttimeout="600">
<cfset reps = 100000>

<cfif 1>
     <cfset start = now().gettime()>
     <cfset result = "">
     <cfloop from="1" to="#reps#" step="1" index="i">
          <cfset result = result & i>
     </cfloop>
     <cfset end = now().gettime()>
     <cfoutput><p>#end-start#ms : #len(result)#</p></cfoutput>
<cfelse>
     <cfset start = now().gettime()>
     <cfsavecontent variable="result">
     <cfloop from="1" to="#reps#" step="1" index="i">
          <cfoutput>#i#</cfoutput>
     </cfloop>
     </cfsavecontent>
     <cfset end = now().gettime()>
     <cfoutput><p>#end-start#ms : #len(result)#</p></cfoutput>
</cfif>


 

 

Posted by rickroot at 1:23 PM | Link | 1 comment