<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7367794905551891931</id><updated>2012-01-29T03:59:39.623-05:00</updated><category term='Random'/><category term='SubSonic'/><category term='Microsoft'/><category term='tools'/><category term='Outlook'/><category term='SQL Server'/><category term='Cisco'/><category term='Windows'/><category term='Bookmarklets'/><category term='Yamaha FZ1'/><category term='Router'/><category term='Ajax'/><category term='Programming'/><category term='ASP.NET'/><category term='Politics'/><category term='ldap'/><category term='Resources'/><category term='Organization'/><category term='Ruby on Rails'/><category term='NAnt'/><category term='Model-Glue'/><category term='Automation'/><category term='Debuggin'/><category term='charts'/><category term='Updates'/><category term='CSS'/><category term='RegEx'/><category term='Prototype'/><category term='Tracking'/><category term='IIS'/><category term='Google'/><category term='Reactor'/><category term='Motorcyle'/><category term='Web Dev'/><category term='Firefox'/><category term='Cats'/><category term='software'/><category term='Linux'/><category term='ColdSpring'/><category term='Jedi'/><category term='Internet Explorer'/><category term='Ubuntu'/><category term='Free'/><category term='T-SQL'/><category term='JavaScript'/><category term='Wiki'/><category term='ColdFusion'/><category term='Ant'/><category term='.NET'/><category term='Utilities'/><category term='Excel'/><title type='text'>Aaquagua!</title><subtitle type='html'>Tech blog of the Bulgarian</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default?start-index=101&amp;max-results=100'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>124</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2428047450207839904</id><published>2010-08-13T13:00:00.000-04:00</published><updated>2010-08-13T13:01:01.704-04:00</updated><title type='text'>Unobtrusive JavaScript with Prototype.js</title><content type='html'>&lt;div&gt;&lt;script type="text/javascript" id="ZjddVd19tU-qNTyCaR9FYQ" src="http://demo.ensemblevideo.com/plugin/plugin.aspx?embed=true&amp;width=640&amp;height=361"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2428047450207839904?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2428047450207839904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2428047450207839904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2428047450207839904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2428047450207839904'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2010/08/unobtrusive-javascript-with-prototypejs.html' title='Unobtrusive JavaScript with Prototype.js'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6517378848438356849</id><published>2009-10-12T18:26:00.000-04:00</published><updated>2009-10-12T18:27:05.065-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>Useful Function for Type Casting Your Query String Values in ASP.NET</title><content type='html'>&lt;p&gt;Whenever you want to get the query string value in ASP.NET, you usually use Request.QueryString. However, that always gives you a string value that is not type cast to the variable you want. So instead of an integer or a Guid, you always get a string. Here is little function that addresses that and gives you the proper type based on the variable type passed in. It’s used as follows:&lt;/p&gt;  &lt;pre class="vb" name="code"&gt;' Declare a variable of Guid type
Dim assetID As Guid
' Get the value from the query string
getValue(&amp;quot;id&amp;quot;, assetID)

' Declare a variable of Integer type
Dim imageWidth As Integer
' Get the value from the query string
getValue(&amp;quot;imageWidth&amp;quot;, imageWidth)&lt;/pre&gt;

&lt;p&gt;And for the function itself:&lt;/p&gt;

&lt;pre class="vb" name="code"&gt;''' &lt;summary&gt;
''' Gets the value of the query string key specified
''' &lt;/summary&gt;
''' &lt;typeparam name="T"&gt;The data type of the value to be returned&lt;/typeparam&gt;
''' &lt;param name="key" /&gt;The query string key&lt;/param&gt;
''' &lt;param name="value" /&gt;The variable to store the value in&lt;/param&gt;
''' &lt;remarks&gt;&lt;/remarks&gt;
Public Shared Sub getValue(Of T)(ByVal key As String, ByRef value As T)
    If Not String.IsNullOrEmpty(Request.QueryString.Item(key)) Then
		' If the passed in type is Guid
        If GetType(T) Is GetType(Guid) Then
            ' Check the format of the query string for a valid Guid
            If isValidGuid(Convert.ToString(Request.QueryString.Item(key))) Then
                ' Type cast the value from a string to a Guid
                value = DirectCast(CType(New Guid(Convert.ToString(Request.QueryString.Item(key))), Object), T)
            Else
                ' Type cast the an empty guid for the value
                value = DirectCast(CType(Guid.Empty, Object), T)
            End If
        Else
            ' Type cast query string value to the requested type
            value = CType(Convert.ChangeType(Request.QueryString.Item(key).Trim(), GetType(T)), T)
        End If
    End If
End Sub&lt;/pre&gt;

&lt;p&gt;Plus the &amp;quot;isValidGuid&amp;quot; helper function:&lt;/p&gt;

&lt;pre class="vb" name="code"&gt;
Public Shared Function isValidGuid(ByVal guidCandidate As String) As Boolean
    Dim isValidGuidRegEx As New Regex(&amp;quot;^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$&amp;quot;, RegexOptions.Compiled)
    Dim isValid As Boolean = False

    If Not String.IsNullOrEmpty(guidCandidate) Then
        If isValidGuidRegEx.IsMatch(guidCandidate) Then
            isValid = True
        End If
    End If

    Return isValid
End Function&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6517378848438356849?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6517378848438356849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6517378848438356849' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6517378848438356849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6517378848438356849'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2009/10/useful-function-for-type-casting-your.html' title='Useful Function for Type Casting Your Query String Values in ASP.NET'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8857090689717494259</id><published>2008-11-05T23:54:00.001-05:00</published><updated>2008-11-06T00:02:21.260-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>SQL Server Scheduled Backups with NAnt</title><content type='html'>&lt;p&gt;When installing and using production web applications, backup is always a must. I have written about &lt;a href="http://blog.tech-cats.com/2007/10/sql-server-script-to-backup-database-to.html" target="_blank"&gt;SQL Server Backup&lt;/a&gt; before and this post would expend on that. The main goal here is to create a solution that periodically backs up your database. To do this, we’ll use the backup script from the previous post, employ NAnt to execute the script and zip the created backup. Last, we’ll schedule the execution of the NAnt build script through the Windows Task Scheduler or the “at” command. This procedure can backup a local or a remote SQL Server (as long as the remote server is on the same network).&lt;/p&gt;  &lt;h4&gt;Prerequisites&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;Installed and configured version of NAnt (see &lt;a href="http://blog.tech-cats.com/2007/11/getting-started-with-nant-net-build.html" target="_blank"&gt;Getting Started with NAnt - .NET Build Tool&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;Installed NAntContrib tasks (for the SQL task, see &lt;a href="http://nantcontrib.sourceforge.net/" target="_blank"&gt;NAntContrib&lt;/a&gt; on SourceForge) &lt;/li&gt;    &lt;li&gt;Task Scheduler Service enabled in Control Panel/Admin Tools/Services &lt;/li&gt;    &lt;li&gt;SQL login with “dbo” rights to the database (to install the backupDatabase procedure) &lt;/li&gt;    &lt;li&gt;SQL login that has “public” rights to the database (so it can execute the backup) &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Backup SQL Procedure&lt;/h4&gt;  &lt;p&gt;The script below with create the SQL server stored procedure to create a backup file of a given database. It takes two parameters:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;databaseName – The SQL server database to be backed up &lt;/li&gt;    &lt;li&gt;backupDirectory – The directory where the backup file will be created &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;You need to execute it against the database that you will be backing up and give the “public” role execution permissions to the procedure.&lt;/p&gt;  &lt;br /&gt;&lt;strong&gt;Code&lt;/strong&gt;   &lt;br /&gt;  &lt;pre class="sql" name="code"&gt;exec dbo.sp_executesql @statement = N'
/*
Created:
 07.18.2008 by Boyan Kostadinov (boyank@gmail.com)

Dependencies:
 None

Usage:
 exec dbo.backupDatabase ''ensembleVideo'', ''C:\Temp''

Parameters:
 @databaseName - varchar
 - The database to backup

 @backupDirectory - varchar
 - The path to where the database should be
 backed up. This should be an existing directory on
 the SQL Server where the database is located

Description:
 Backsup a given database to the specified directory
*/
create procedure dbo.backupDatabase
	@databaseName varchar(100),
	@backupDirectory varchar(1000)
as
declare @backupFileName varchar(100),
	@databaseDataFilename varchar(100), @databaseLogFilename varchar(100),
	@databaseDataFile varchar(100), @databaseLogFile varchar(100),
	@execSql varchar(1000)

-- If the backup directory does not end with ''\'', append one
if charindex(''\'', reverse(@backupDirectory)) &amp;gt; 1
	set @backupDirectory = @backupDirectory + ''\''

-- Create the backup file name based on the backup directory, the database name and today''s date
set @backupFileName = @backupDirectory + @databaseName + ''-'' + replace(convert(varchar, getdate(), 110), ''-'', ''.'') + ''.bak''

set @execSql = ''
backup database ['' + @databaseName + '']
to disk = '''''' + @backupFileName + ''''''
with
  noformat,
  noinit,
  name = '''''' + @databaseName + '' backup'''',
  norewind,
  nounload,
  skip''

exec(@execSql)'
go&lt;/pre&gt;

&lt;h4&gt;NAnt Backup Script&lt;/h4&gt;

&lt;p&gt;The script is somewhat complex. Here are the list of features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Backup a local SQL Server instance or a SQL Server instance on the same network. The key is that the file system of the networked instance must be available through UNC shares to the machine executing the backup script. &lt;/li&gt;

  &lt;li&gt;Use a specified connection string or read the connection string from a .NET (or other type of XML)configuration file. &lt;/li&gt;
&lt;/ul&gt;

&lt;br /&gt;I will not dive into the script itself since it's properties and flow is documented fairly well. 

&lt;br /&gt;

&lt;br /&gt;&lt;strong&gt;Code&lt;/strong&gt; 

&lt;br /&gt;

&lt;br /&gt;

&lt;pre class="xml" name="code"&gt;&amp;lt;project name=&amp;quot;backupDatabase&amp;quot; default=&amp;quot;run&amp;quot; xmlns=&amp;quot;http://nant.sf.net/release/0.86-beta1/nant.xsd&amp;quot;&amp;gt;
	&amp;lt;!-- Set the name of the backup file that will be created --&amp;gt;
	&amp;lt;property name=&amp;quot;zipFileName&amp;quot; value=&amp;quot;databaseBackup&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the path where the backup file will be finally stored --&amp;gt;
	&amp;lt;property name=&amp;quot;localBackupDirectory&amp;quot; value=&amp;quot;C:\Temp&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the local path (relative to the SQL Server instance) where SQL Server will write the backup file --&amp;gt;
	&amp;lt;!-- This has to always be a local path since SQL server can't write to network paths --&amp;gt;
	&amp;lt;property name=&amp;quot;sqlServerLocalBackupDirectory&amp;quot; value=&amp;quot;C:\Temp&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the UNC path to the above &amp;quot;sqlServerLocalBackupDirectory&amp;quot; local path --&amp;gt;
	&amp;lt;!-- This is only needed if you are backing up SQL server on the network --&amp;gt;
	&amp;lt;property name=&amp;quot;sqlServerUNCBackupDirectory&amp;quot; value=&amp;quot;\\beehive\windows$\Temp&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;
	&amp;lt;!-- For backing up a local SQL Server instance, commented the first &amp;quot;sqlServerUNCBackupDirectory&amp;quot; property --&amp;gt;
	&amp;lt;!-- and uncommented the one below this line, or set the &amp;quot;sqlServerUNCBackupDirectory&amp;quot; property to &amp;quot;&amp;quot; --&amp;gt;
	&amp;lt;!--&amp;lt;property name=&amp;quot;sqlServerUNCBackupDirectory&amp;quot; value=&amp;quot;&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;--&amp;gt;

	&amp;lt;!-- Set the .NET connection string for connecting to the database --&amp;gt;
	&amp;lt;!-- This setting always takes precedence over the config file below --&amp;gt;
	&amp;lt;!-- To use a config file instead, set this property to &amp;quot;&amp;quot; (like so value=&amp;quot;&amp;quot;) --&amp;gt;
	&amp;lt;property name=&amp;quot;connectionString&amp;quot; value=&amp;quot;Data Source=beehive\sql2005;Initial Catalog=ensembleVideo;User ID=test;Password=test;&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Alternatively set the path to where the build script should get the connection string from  --&amp;gt;
	&amp;lt;!-- This is usually a app.config or connectionString.config file --&amp;gt;
	&amp;lt;property name=&amp;quot;connectionStringConfigFilePath&amp;quot; value=&amp;quot;C:\Inetpub\wwwroot\myApp\config\connectionStrings.config&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the XPath expression that will be used to grab the connection string from the config file --&amp;gt;
	&amp;lt;property name=&amp;quot;connectionStringXPath&amp;quot; value=&amp;quot;/connectionStrings/add[@name = 'sqlServerConnection']/@connectionString&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the regular expression that's needed to get the database name from the connection string --&amp;gt;
	&amp;lt;property name=&amp;quot;getDatabaseNameFromConnecionStringRegEx&amp;quot; value=&amp;quot;Initial Catalog=(?'databaseName'.*?);&amp;quot; overwrite=&amp;quot;false&amp;quot; /&amp;gt;

	&amp;lt;property name=&amp;quot;todaysDate&amp;quot; value=&amp;quot;${string::substring(string::replace(datetime::to-string(datetime::now()), '/', '.'), 0, 10)}&amp;quot; /&amp;gt;
	&amp;lt;property name=&amp;quot;todaysLocalBackupDirectory&amp;quot; value=&amp;quot;${path::combine(localBackupDirectory, todaysDate)}&amp;quot; /&amp;gt;

  	&amp;lt;target name=&amp;quot;run&amp;quot;&amp;gt;
		&amp;lt;!-- If the SQL Server UNC directory was not specified and the local backup directory exists --&amp;gt;
		&amp;lt;if test=&amp;quot;${string::get-length(sqlServerUNCBackupDirectory) == 0 and directory::exists(localBackupDirectory)}&amp;quot;&amp;gt;
			&amp;lt;!-- This is a back of a local SQL Server instance --&amp;gt;
			&amp;lt;mkdir dir=&amp;quot;${todaysLocalBackupDirectory}&amp;quot; /&amp;gt;

			&amp;lt;property name=&amp;quot;todaysSqlServerLocalBackupDirectory&amp;quot; value=&amp;quot;${todaysLocalBackupDirectory}&amp;quot; /&amp;gt;
			&amp;lt;property name=&amp;quot;todaysSqlServerUNCBackupDirectory&amp;quot; value=&amp;quot;${todaysLocalBackupDirectory}&amp;quot; /&amp;gt;

			&amp;lt;property name=&amp;quot;localSqlServer&amp;quot; value=&amp;quot;true&amp;quot; /&amp;gt;
		&amp;lt;/if&amp;gt;

		&amp;lt;if test=&amp;quot;${string::get-length(sqlServerUNCBackupDirectory) &amp;gt; 0 and directory::exists(sqlServerUNCBackupDirectory) }&amp;quot; &amp;gt;
			&amp;lt;property name=&amp;quot;todaysSqlServerLocalBackupDirectory&amp;quot; value=&amp;quot;${path::combine(sqlServerLocalBackupDirectory, todaysDate)}&amp;quot; /&amp;gt;
			&amp;lt;property name=&amp;quot;todaysSqlServerUNCBackupDirectory&amp;quot; value=&amp;quot;${path::combine(sqlServerUNCBackupDirectory, todaysDate)}&amp;quot; /&amp;gt;

			&amp;lt;!-- This is a back of a networked SQL Server instance --&amp;gt;
			&amp;lt;mkdir dir=&amp;quot;${todaysSqlServerUNCBackupDirectory}&amp;quot; /&amp;gt;

			&amp;lt;property name=&amp;quot;localSqlServer&amp;quot; value=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;/if&amp;gt;

		&amp;lt;!-- If the connection string is empty,
		the connection string file exists and the XPath to find the connection string is not empty --&amp;gt;
		&amp;lt;if test=&amp;quot;${string::get-length(connectionString) == 0 and file::exists(connectionStringConfigFilePath)
							and string::get-length(connectionStringXPath) &amp;gt; 0}&amp;quot; &amp;gt;
			&amp;lt;!-- Get the connection string to the database from the connection string config file --&amp;gt;
			&amp;lt;xmlpeek
				file=&amp;quot;${connectionStringConfigFilePath}&amp;quot;
				xpath=&amp;quot;${connectionStringXPath}&amp;quot;
				property=&amp;quot;connectionString&amp;quot;&amp;gt;
			&amp;lt;/xmlpeek&amp;gt;
		&amp;lt;/if&amp;gt;

		&amp;lt;!-- If the connectionString property is not empty and the regular expression to get the database name is not empty --&amp;gt;
		&amp;lt;if test=&amp;quot;${string::get-length(connectionString) &amp;gt; 0 and string::get-length(getDatabaseNameFromConnecionStringRegEx) &amp;gt; 0}&amp;quot;&amp;gt;
			&amp;lt;!-- Get the database name from the connection string --&amp;gt;
			&amp;lt;regex pattern=&amp;quot;${getDatabaseNameFromConnecionStringRegEx}&amp;quot; input=&amp;quot;${connectionString}&amp;quot; /&amp;gt;
	
	    		&amp;lt;!-- Execute the stored procedure to bckup the database --&amp;gt;
			&amp;lt;sql connstring=&amp;quot;Provider=SQLOLEDB;${connectionString}&amp;quot; transaction=&amp;quot;false&amp;quot; delimiter=&amp;quot;;&amp;quot; delimstyle=&amp;quot;Normal&amp;quot;&amp;gt;
			exec dbo.backupDatabase '${databaseName}', '${todaysSqlServerLocalBackupDirectory}';
			&amp;lt;/sql&amp;gt;

			&amp;lt;!-- Zip up the created databse backup file --&amp;gt;
			&amp;lt;zip zipfile=&amp;quot;${path::combine(todaysSqlServerUNCBackupDirectory, zipFileName + '-' + todaysDate + '.zip')}&amp;quot; ziplevel=&amp;quot;9&amp;quot;&amp;gt;
				&amp;lt;fileset basedir=&amp;quot;${todaysSqlServerUNCBackupDirectory}&amp;quot;&amp;gt;
					&amp;lt;exclude name=&amp;quot;**/*.zip&amp;quot; /&amp;gt;
					&amp;lt;include name=&amp;quot;*.*&amp;quot; /&amp;gt;
				&amp;lt;/fileset&amp;gt;
			&amp;lt;/zip&amp;gt;

			&amp;lt;!-- Delete all other files in the today's backup directory except for the created zip files --&amp;gt;
			&amp;lt;delete&amp;gt;
				&amp;lt;fileset basedir=&amp;quot;${todaysSqlServerUNCBackupDirectory}&amp;quot;&amp;gt;
					&amp;lt;exclude name=&amp;quot;**/*.zip&amp;quot; /&amp;gt;
					&amp;lt;include name=&amp;quot;*.*&amp;quot; /&amp;gt;
				&amp;lt;/fileset&amp;gt;
			&amp;lt;/delete&amp;gt;

			&amp;lt;!-- Move the contents of today's backup directory to the local backup directory --&amp;gt;
			&amp;lt;move todir=&amp;quot;${localBackupDirectory}&amp;quot;&amp;gt;
				&amp;lt;fileset basedir=&amp;quot;${todaysSqlServerUNCBackupDirectory}&amp;quot;&amp;gt;
					&amp;lt;include name=&amp;quot;*.*&amp;quot; /&amp;gt;
				&amp;lt;/fileset&amp;gt;
			&amp;lt;/move&amp;gt;

			&amp;lt;!-- Delete the &amp;quot;todays&amp;quot; directories --&amp;gt;
			&amp;lt;if test=&amp;quot;${localSqlServer}&amp;quot;&amp;gt;
				&amp;lt;delete dir=&amp;quot;${todaysLocalBackupDirectory}&amp;quot; /&amp;gt;
			&amp;lt;/if&amp;gt;

			&amp;lt;if test=&amp;quot;${not localSqlServer}&amp;quot;&amp;gt;
				&amp;lt;delete dir=&amp;quot;${todaysSqlServerUNCBackupDirectory}&amp;quot; /&amp;gt;
			&amp;lt;/if&amp;gt;
		&amp;lt;/if&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;

&lt;h4&gt;Setting Up Backup Script and Scheduling&lt;/h4&gt;
Review the build script and set following properties to match your setup: 

&lt;br /&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;zipFileName&lt;/strong&gt; – The name of the zip file that will be created for the database backup &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;localBackupDirectory&lt;/strong&gt; – The local directory where the backup will be stored &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;sqlServerLocalBackupDirectory&lt;/strong&gt; - The local path (relative to the SQL Server instance) where SQL Server will write the backup file. This has to always be a local path since SQL server can't write to network paths. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;sqlServerUNCBackupDirectory – &lt;/strong&gt;The UNC path to the above &amp;quot;sqlServerLocalBackupDirectory&amp;quot; local path. This is only needed if you are backing up SQL server on the network. For backing up a local SQL Server instance, set this &amp;quot;”. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;connectionString&lt;/strong&gt; - The .NET connection string for connecting to the database. This setting always takes precedence over the “connectionStringConfigFilePath“ setting. To use a configuration file instead, set this property to &amp;quot;&amp;quot;. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;connectionStringConfigFilePath&lt;/strong&gt; - Alternatively set the path to where the build script should get the connection string from. This is usually a app.config or connectionString.config file. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;connectionStringXPath&lt;/strong&gt; - The XPath expression that will be used to grab the connection string from the configuration file. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;getDatabaseNameFromConnecionStringRegEx&lt;/strong&gt; - The regular expression that's needed to get the database name from the connection string. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  &lt;br /&gt;The next step is to create the schedule with either the Task Scheduler or with “at” command. 

  &lt;br /&gt;

  &lt;br /&gt;&lt;strong&gt;To use the Task Scheduler:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a .bat file with the following: “driveLetter:\path\to\nant.exe /f:pathToNAntBackupScript.build” and of course replace that with the actual path to nant.exe and to the NAnt build script you got here. &lt;/li&gt;

  &lt;li&gt;Go to Control Panel / Scheduled Tasks / Add Scheduled Task &lt;/li&gt;

  &lt;li&gt;Browse for the .bat file you created in #1 &lt;/li&gt;

  &lt;li&gt;Configure the schedule run as often as you would like &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To use the “at” command:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Do the same as #1 above. &lt;/li&gt;

  &lt;li&gt;Open a command prompt and execute the “at” command: 
    &lt;br /&gt;”at 23:00 /every:M,T,W,Th,F pathToBatFileFromStep1.bat” 

    &lt;br /&gt;

    &lt;br /&gt;That will schedule the task to execute every day of the week at 11:00pm. You can get more info on the “at” command from &lt;a href="http://support.microsoft.com/kb/313565" target="_blank"&gt;How To Use the AT Command to Schedule Tasks&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Bonus&lt;/h4&gt;

&lt;p&gt;You don’t have to hard code the values in the NAnt build script. You can pass them from the command line. In that manner you can reuse the same script for different database. You simply need to call the script with –D:propertyName=”value&amp;quot; like so: 
  &lt;br /&gt;

  &lt;br /&gt;path\to\nant.exe /f:pathToNAntBackupScript.build –D:zipFileName=&amp;quot;myDatabase&amp;quot; –D:localBackupDirectory=&amp;quot;D:\Temp&amp;quot;&lt;/p&gt;

&lt;h4&gt;Downloads&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/downloads/sql/procedure-dbo.backupDatabase.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/procedure-dbo.backupDatabase.txt&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://tech-cats.net/blog/nantScripts/backupDatabase.build.txt" target="_blank"&gt;http://tech-cats.net/blog/nantScripts/backupDatabase.build&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://tech-cats.net/blog/nantScripts/backupDatabase.bat.txt" target="_blank"&gt;http://tech-cats.net/blog/nantScripts/backupDatabase.bat&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8857090689717494259?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8857090689717494259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8857090689717494259' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8857090689717494259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8857090689717494259'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/11/sql-server-scheduled-backups-with-nant.html' title='SQL Server Scheduled Backups with NAnt'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-9100605236334981928</id><published>2008-11-03T21:00:00.000-05:00</published><updated>2008-11-06T00:01:04.911-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>Using NAnt to Traverse Directories and Execute SQL</title><content type='html'>&lt;p&gt;In the latest version of &lt;a href="http://ensembleVideo.com" target="_blank"&gt;Ensemble Video&lt;/a&gt; I had a need to migrate the old mechanism of showing content to new way that involved a single page and some URL rewriting (more on that another time). The basics of the old mechanism were that for each publishing point used by the application, a separate directory with specific “index.aspx” was created. That was always a major pain when updates had to be applied since I always had to preserve the old files but still update existing content. Long story short, I got away from that but I still needed to figure out what publishing points were in use so I can set the database flag for the new mechanism. So, the NAnt fanatic that I am, I build a NAnt script to do that. In this example, you will learn:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;How to parse XML for a certain value &lt;/li&gt;    &lt;li&gt;How to traverse directories with NAnt &lt;/li&gt;    &lt;li&gt;How to execute an “if” statement in NAnt &lt;/li&gt;    &lt;li&gt;How to get file and directory names using the NAnt built-in functions &lt;/li&gt;    &lt;li&gt;How to execute SQL script with SQL task from NAntContrib &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The prerequisites are that 1). You have NAnt installed and 2). You have NAntContrib installed.&lt;/p&gt;  &lt;p&gt;So let’s go one by one from the list above and you will see the final script at the end.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;How to parse XML for certain value      &lt;pre class="xml" name="code"&gt;&amp;lt;xmlpeek&lt;br /&gt;file=&amp;quot;${path::combine(path::get-full-path(webApplicationDirectory), 'config\connectionStrings.config')}&amp;quot;
xpath=&amp;quot;/connectionStrings/add[@name = 'ensembleVideoConnection']/@connectionString&amp;quot;
property=&amp;quot;connectionString&amp;quot; /&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;This parses the XML file under webApplicationDirectory\config\connectionStrings.config and uses an XPath expression to get the property of the connectionString with the name ensembleVideoConnection. The value is stored in the NAnt property &amp;quot;connectionString&amp;quot; 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;How to traverse directories with NAnt 
    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;foreach item=&amp;quot;Folder&amp;quot; in=&amp;quot;${sitesDirectory}&amp;quot; property=&amp;quot;orgDirectoryName&amp;quot;&amp;gt;
	&amp;lt;echo message=&amp;quot;${orgDirectoryName}&amp;quot; /&amp;gt;
&amp;lt;/foreach&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;This task traverses through the directories inside the directory specified by &amp;quot;sitesDirectory&amp;quot;, stores the current directory in orgDirectoryName and then echoes the current directory. 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;How to execute an “if” statement in NAnt 
    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;if test=&amp;quot;${string::to-lower(path::get-file-name(orgDirectoryName)) != '_svn'}&amp;quot;&amp;gt;
	&amp;lt;echo message=&amp;quot;${path::get-file-name(orgDirectoryName)}&amp;quot; /&amp;gt;
&amp;lt;/if&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;Here we test if the current directory name is equal to &amp;quot;_svn&amp;quot;. Here is another example where we test if the current directory contains a desired file: 

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;if test=&amp;quot;${file::exists(path::combine(webSiteDirectoryName, 'index.aspx'))}&amp;quot;&amp;gt;
	&amp;lt;property name=&amp;quot;enableQuickPublish&amp;quot; value=&amp;quot;1&amp;quot; /&amp;gt;
&amp;lt;/if&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;How to get file and directory names using the NAnt built-in functions 
    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;-- Get only the directory name --&amp;gt;
path::get-file-name(orgDirectoryName)
&amp;lt;-- Get the directory name from the path --&amp;gt;
path::get-directory-name(orgDirectoryName)
&amp;lt;-- Create a full path based on the directory name and a file name --&amp;gt;
path::combine(webSiteDirectoryName, 'index.aspx')&lt;/pre&gt;

    &lt;br /&gt;You can find out more about NAnt built-in functions at &lt;a href="http://nant.sourceforge.net/release/latest/help/functions/" target="_blank"&gt;NAnt Functions&lt;/a&gt; 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;How to execute SQL script with SQL task from NAntContrib 
    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;sql
  connstring=&amp;quot;Provider=SQLOLEDB;${connectionString}&amp;quot;
  transaction=&amp;quot;true&amp;quot;
  delimiter=&amp;quot;;&amp;quot;
  delimstyle=&amp;quot;Normal&amp;quot;&amp;gt;
	update	dbo.webSites
	set	isQuickPublished = ${enableQuickPublish}
	where	webSiteID = (
			select	webSiteID
			from	dbo.listWebSites
			where	webSafeOrganizationName = '${path::get-file-name(orgDirectoryName)}'
				and webSafeDepartmentName = '${path::get-file-name(departmentDirectoryName)}'
				and webSafeWebSiteName = '${path::get-file-name(webSiteDirectoryName)}'
		);
&amp;lt;/sql&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;There is not much to the SQL statement execution. As you can see you can use NAnt properties and function inside the SQL script. You can check out all of NAntContrib's tasks at &lt;a href="http://nantcontrib.sourceforge.net/release/latest/help/tasks/" target="_blank"&gt;NAntContrib Tasks&lt;/a&gt; 

    &lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;br /&gt;

&lt;p&gt;As promised here is the full contents of the build script: 
  &lt;br /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="xml" name="code"&gt;&amp;lt;project name=&amp;quot;renameSqlToText&amp;quot; default=&amp;quot;run&amp;quot; xmlns=&amp;quot;http://nant.sf.net/release/0.86-beta1/nant.xsd&amp;quot;&amp;gt;
	&amp;lt;!-- Set the path to the web application --&amp;gt;
	&amp;lt;property name=&amp;quot;webApplicationDirectory&amp;quot; value=&amp;quot;D:\_Boyan's Documents\_Projects\_ensembleVideo\trunk\webApplication\app&amp;quot; /&amp;gt;

	&amp;lt;!-- Set the name of the sites directory (under the applicaiton directory) --&amp;gt;
	&amp;lt;property name=&amp;quot;sitesDirectoryName&amp;quot; value=&amp;quot;sites&amp;quot; /&amp;gt;

	&amp;lt;property name=&amp;quot;sitesDirectory&amp;quot; value=&amp;quot;${path::combine(path::get-full-path(webApplicationDirectory), sitesDirectoryName)}&amp;quot; overwrite=&amp;quot;true&amp;quot; /&amp;gt;

	&amp;lt;target name=&amp;quot;run&amp;quot;&amp;gt;
		&amp;lt;!-- Get the database connection string from the web application --&amp;gt;
		&amp;lt;xmlpeek
			file=&amp;quot;${path::combine(path::get-full-path(webApplicationDirectory), 'config\connectionStrings.config')}&amp;quot;
			xpath=&amp;quot;/connectionStrings/add[@name = 'ensembleVideoConnection']/@connectionString&amp;quot;
			property=&amp;quot;connectionString&amp;quot; /&amp;gt;

		&amp;lt;!-- For each directory in the sitesDirectory --&amp;gt;
		&amp;lt;foreach item=&amp;quot;Folder&amp;quot; in=&amp;quot;${sitesDirectory}&amp;quot; property=&amp;quot;orgDirectoryName&amp;quot;&amp;gt;
			&amp;lt;if test=&amp;quot;${string::to-lower(path::get-file-name(orgDirectoryName)) != '_svn'}&amp;quot;&amp;gt;
				&amp;lt;echo message=&amp;quot;${path::get-file-name(orgDirectoryName)}&amp;quot; /&amp;gt;

				&amp;lt;foreach item=&amp;quot;Folder&amp;quot; in=&amp;quot;${orgDirectoryName}&amp;quot; property=&amp;quot;departmentDirectoryName&amp;quot;&amp;gt;
					&amp;lt;echo message=&amp;quot;		${path::get-file-name(departmentDirectoryName)}&amp;quot; /&amp;gt;

					&amp;lt;foreach item=&amp;quot;Folder&amp;quot; in=&amp;quot;${departmentDirectoryName}&amp;quot; property=&amp;quot;webSiteDirectoryName&amp;quot;&amp;gt;
						&amp;lt;echo message=&amp;quot;				${path::get-file-name(webSiteDirectoryName)}&amp;quot; /&amp;gt;

						&amp;lt;!-- Set the 'enableQuickPublish' property to false --&amp;gt;
						&amp;lt;property name=&amp;quot;enableQuickPublish&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;

						&amp;lt;!-- If a index.aspx file exists, set the 'enableQuickPublish' property to true --&amp;gt;
						&amp;lt;if test=&amp;quot;${file::exists(path::combine(webSiteDirectoryName, 'index.aspx'))}&amp;quot;&amp;gt;
							&amp;lt;property name=&amp;quot;enableQuickPublish&amp;quot; value=&amp;quot;1&amp;quot; /&amp;gt;
						&amp;lt;/if&amp;gt;

						&amp;lt;!-- Run a database query to update the flag in the database --&amp;gt;
					      	&amp;lt;sql
						        connstring=&amp;quot;Provider=SQLOLEDB;${connectionString}&amp;quot;
						        transaction=&amp;quot;true&amp;quot;
						        delimiter=&amp;quot;;&amp;quot;
						        delimstyle=&amp;quot;Normal&amp;quot;&amp;gt;
							update	dbo.webSites
							set	isQuickPublished = ${enableQuickPublish}
							where	webSiteID = (
									select	webSiteID
									from		dbo.listWebSites
									where		webSafeOrganizationName = '${path::get-file-name(orgDirectoryName)}'
											and
											webSafeDepartmentName = '${path::get-file-name(departmentDirectoryName)}'
											and
											webSafeWebSiteName = '${path::get-file-name(webSiteDirectoryName)}'
									);
					      &amp;lt;/sql&amp;gt;
					&amp;lt;/foreach&amp;gt;
				&amp;lt;/foreach&amp;gt;
			&amp;lt;/if&amp;gt;
		&amp;lt;/foreach&amp;gt;
	&amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/nantScripts/traverseDirectoriesAndExecuteSQL.build.txt" target="_blank"&gt;http://tech-cats.net/blog/nantScripts/traverseDirectoriesAndExecuteSQL.build&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-9100605236334981928?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/9100605236334981928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=9100605236334981928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9100605236334981928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9100605236334981928'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/11/using-nant-to-traverse-directories-and.html' title='Using NAnt to Traverse Directories and Execute SQL'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-256705850076247450</id><published>2008-10-31T01:12:00.001-04:00</published><updated>2008-10-31T01:12:31.748-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Export UML to XMI from Visio 2003</title><content type='html'>&lt;p&gt;A friend wanted to export his UML diagrams created with Visio to XMI files so then we could run some kind of ColdFusion tool to generate code based on the created diagrams. It appeared however that Visio did not come out of the box a way to do that. Some googling reveled that there is a add-on Microsoft offers but you have to get it, compile it (in Visual C++ non the less) and install it. What a major hassle. So being the problem solver I tend to be, I installed Visual C++ and went at it. About almost an hour later, the procedure below did the trick.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Something to Note: &lt;/strong&gt;The supported UML diagrams are: Static Structure, Component and Deployment diagrams, and State chart (directly from Microsoft’s documentation about the add-on).&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Get the zip file below &lt;/li&gt;    &lt;li&gt;Copy “XMIEXPRT.DLL” to “C:\Program Files\Microsoft Office\Visio11\DLL\” &lt;/li&gt;    &lt;li&gt;Copy “VisioUmlAddon.vsl” to “C:\Program Files\Microsoft Office\Visio11\1033\” &lt;/li&gt;    &lt;li&gt;Open Visio 2003 and:      &lt;ol&gt;       &lt;li&gt;Go to Tools/Options/Security/Macro Security &lt;/li&gt;        &lt;li&gt;Set the Macro Security to “Medium” or “Low” &lt;/li&gt;        &lt;li&gt;Go back to Options and go to Advanced &lt;/li&gt;        &lt;li&gt;Click on “File Paths” and set the “Add-ons” path to          &lt;br /&gt;“C:\Program Files\Microsoft Office\Visio11\1033” &lt;/li&gt;        &lt;li&gt;Restart Visio 2003 &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;Now you should be able to create a UML diagram and go to Tools/Add-Ons and see “XMI Export” all the way on the bottom. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Downloads&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://tech-cats.net/blog/downloads/UML-to-XMI-for-Visio2003.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/UML-to-XMI-for-Visio2003.zip&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-256705850076247450?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/256705850076247450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=256705850076247450' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/256705850076247450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/256705850076247450'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/10/export-uml-to-xmi-from-visio-2003.html' title='Export UML to XMI from Visio 2003'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2638657763418009018</id><published>2008-07-23T12:18:00.000-04:00</published><updated>2008-07-23T18:47:57.301-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Automation'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>Rename All Files in a Directory with NAnt</title><content type='html'>&lt;p&gt;It’s a pretty simple thing to do but I had to spend a few minutes today to figure out how to accomplish it. So here is a quick build file to rename all .sql files in a specified directory (relative to the script run directory) to .txt. Funny enough, this scripts gets called by my automation program before it uploads any SQL scripts to my blog. There is nothing to it and there are comments so here goes:&lt;/p&gt;  &lt;pre class="xml" name="code"&gt;&amp;lt;project name=&amp;quot;renameSqlToText&amp;quot; default=&amp;quot;run&amp;quot; xmlns=&amp;quot;http://nant.sf.net/release/0.86-beta1/nant.xsd&amp;quot;&amp;gt;
 &amp;lt;!-- The relative path to the directory where the files are located --&amp;gt;
 &amp;lt;property name=&amp;quot;sqlDirectory&amp;quot; value=&amp;quot;..\downloads\sql&amp;quot; /&amp;gt;

 &amp;lt;target name=&amp;quot;run&amp;quot;&amp;gt;
  &amp;lt;!-- For each file in the directory --&amp;gt;
  &amp;lt;foreach item=&amp;quot;File&amp;quot; in=&amp;quot;${sqlDirectory}&amp;quot; property=&amp;quot;fileName&amp;quot;&amp;gt;
   &amp;lt;!-- If the file has the .sql extension --&amp;gt;
   &amp;lt;if test=&amp;quot;${string::to-lower(path::get-extension(fileName)) == '.sql'}&amp;quot;&amp;gt;
    &amp;lt;!-- Rename the file to .txt extension --&amp;gt;
    &amp;lt;move file=&amp;quot;${fileName}&amp;quot; tofile=&amp;quot;${path::combine(path::get-directory-name(fileName), path::get-file-name-without-extension(fileName) + '.txt')}&amp;quot; /&amp;gt;
   &amp;lt;/if&amp;gt;
  &amp;lt;/foreach&amp;gt;
 &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/nantScripts/renameSqlToText.build.txt" target="_blank"&gt;http://tech-cats.net/blog/nantScripts/renameSqlToText.build&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2638657763418009018?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2638657763418009018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2638657763418009018' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2638657763418009018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2638657763418009018'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/07/rename-all-files-in-directory-with-nant.html' title='Rename All Files in a Directory with NAnt'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6734146136420226902</id><published>2008-07-22T15:04:00.000-04:00</published><updated>2008-07-22T16:21:16.576-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Silly Little SQL Server Information Schema Helpers</title><content type='html'>&lt;p&gt;If you work with SQL Server like I do, it is often necessary to drop functions and/or procedures through T-SQL. There are two ways to do this:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Using the &lt;strong&gt;sysobjects&lt;/strong&gt; built-in to SQL Server &lt;/li&gt;    &lt;li&gt;Using the information schema &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Microsoft says they do not recommend the &lt;strong&gt;sysobjects&lt;/strong&gt; way since things might change in future version of SQL Server. Regardless, just for reference, here is how to drop a view if it exists:&lt;/p&gt;  &lt;pre class="sql" name="code"&gt;if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[listVideos]') and objectproperty(id, N'IsView') = 1)
drop view [dbo].[listVideos]
go&lt;/pre&gt;

&lt;p&gt;Doing the same with a stored procedure is not really much different:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[addEncoding]') and objectproperty(id, N'IsProcedure') = 1)
drop procedure dbo.addEncoding
go&lt;/pre&gt;

&lt;p&gt;Now for the more recommended way, using the information schema:&lt;/p&gt;

&lt;p&gt;Dropping a view:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if exists (select * from information_schema.views where table_name = 'listVideos')
  drop view dbo.listVideos
go&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Dropping a stored procedure:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if exists (select * from information_schema.routines where routine_name = 'addEncoding' and routine_type = 'procedure')
  drop procedure dbo.addEncoding
go&lt;/pre&gt;

&lt;p&gt;That is all good and swell, but if you are like me, you might hate to write that long SQL statement every time, so I thought I would shorten it a bit. Here is what I came up with for querying the information schema for procedures and functions. The same can be easily applied to views and tables.&lt;/p&gt;

&lt;p&gt;First, we need a single function to check if a procedure or a function exists. I called it “&lt;strong&gt;routineExists&lt;/strong&gt;”. You can download it as a text file from &lt;a href="http://tech-cats.net/blog/downloads/sql/routineExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/routineExistsFunction.txt&lt;/a&gt;. Here is the script to create it in your database:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if exists (select * from information_schema.routines where routine_name = 'routineExists' and routine_type = 'function')
	drop function dbo.routineExists
go

exec dbo.sp_executesql @statement = N'
/*
Created:
 07.22.2008 by Boyan Kostadinov (boyank@gmail.com)

Dependencies:
 information_schema.routines

Parameters:
 @routineName varchar(255)
 - The name of the procedure or function

 @routineType varchar(25)
 - The type of routine (usually ''procudure'' or ''function''

Usage:
 select dbo.routineExists(''getCopyInformation'', ''procedure'')
 select dbo.routineExists(''getCopyInformation'', ''function'')
 if (select dbo.routineExists(''getCopyInformation'', ''procedure'')) = 1 print ''exists''

Returns:
 0 if the routine does not exist
 1 if the routine exists

Description:
 Checks the information schema view for the existance of the routine name passed in
*/
create function dbo.routineExists(@routineName varchar(255), @routineType varchar(25))
	returns bit
as
begin
	declare @routineExists bit
	set @routineExists = 0

	if exists (
		select	routine_name
		from		information_schema.routines
		where		routine_name = @routineName
						and
						routine_type = @routineType
	) set @routineExists = 1
	else set @routineExists = 0

	return @routineExists
end
'&lt;/pre&gt;

&lt;p&gt;The usage is quite simple:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;-- Does the stored procedure 'getCopyInformation' exists, will return 0 or 1
select dbo.routineExists('getCopyInformation', 'procedure')

-- Does the function 'getCopyInformation' exists, will return 0 or 1
select dbo.routineExists('getCopyInformation', 'function')

-- If the procedure 'getCopyInformation' exists, print 'exists'
if (select dbo.routineExists('getCopyInformation', 'procedure')) = 1 print 'exists'&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Better but still not quite satisfactory. Next step is wrap the &amp;quot;&lt;strong&gt;routineExists&lt;/strong&gt;” function in individual functions, one for procedures and one for functions.&lt;/p&gt;

&lt;p&gt;Let’s start with the procedures one. You can download it from &lt;a href="http://tech-cats.net/blog/downloads/sql/procedureExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/procedureExistsFunction.txt&lt;/a&gt;. I creatively called it “&lt;strong&gt;procedureExists&lt;/strong&gt;”:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if (select dbo.routineExists('procedureExists', 'function')) = 1 drop function dbo.procedureExists
go

exec dbo.sp_executesql @statement = N'
/*
Created:
 07.22.2008 by Boyan Kostadinov (boyank@gmail.com)

Dependencies:
 information_schema.routines

Parameters:
 @procedureName varchar(255)
 - The name of the procedure

Usage:
 select dbo.procedureExists(''getCopyInformation'')
 if (select dbo.procedureExists(''getCopyInformation'')) = 1 print ''exists''

Returns:
 0 if the procedure does not exist
 1 if the procedure exists

Description:
 A wrapper for the dbo.routineExists that explicetly checks
 for the existance of the procedure name passed in
*/
create function dbo.procedureExists(@procedureName varchar(255))
	returns bit
as
begin
	return (select dbo.routineExists(@procedureName, ''procedure''))
end
'&lt;/pre&gt;

&lt;p&gt;Usage is pretty much the same as the “&lt;strong&gt;routineExists&lt;/strong&gt;” function without the “routineType” parameter:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;-- Does the stored procedure 'getCopyInformation' exists, will return 0 or 1
select dbo.procedureExists('getCopyInformation')

-- If the procedure 'getCopyInformation' exists, print 'exists'
if (select dbo.procedureExists('getCopyInformation')) = 1 print 'exists'&lt;/pre&gt;

&lt;p&gt;The function one is called “&lt;strong&gt;functionExists&lt;/strong&gt;”. You can download it from &lt;a href="http://tech-cats.net/blog/downloads/sql/functionExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/functionExistsFunction.txt&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;if (select dbo.routineExists('functionExists', 'function')) = 1 drop function dbo.functionExists
go

exec dbo.sp_executesql @statement = N'
/*
Created:
 07.22.2008 by Boyan Kostadinov (boyank@gmail.com)

Dependencies:
 information_schema.routines

Parameters:
 @functionName varchar(255)
 - The name of the function

Usage:
 select dbo.functionExists(''getCopyInformation'')
 if (select dbo.functionExists(''getCopyInformation'')) = 1 print ''exists''

Returns:
 0 if the function does not exist
 1 if the function exists

Description:
 A wrapper for the dbo.routineExists that explicetly checks
 for the existance of the function name passed in
*/
create function dbo.functionExists(@functionName varchar(255))
	returns bit
as
begin
	return (select dbo.routineExists(@functionName, ''function''))
end
'&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Example Usage:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;-- Does the function 'listToTable' exists, will return 0 or 1
select dbo.functionExists('listToTable')

-- If the function 'getCopyInformation' exists, print 'exists'
if (select dbo.functionExists('listToTable')) = 1 print 'exists'&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/downloads/sql/routineExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/routineExistsFunction.txt&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://tech-cats.net/blog/downloads/sql/procedureExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/procedureExistsFunction.txt&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://tech-cats.net/blog/downloads/sql/functionExistsFunction.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/functionExistsFunction.txt&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6734146136420226902?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6734146136420226902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6734146136420226902' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6734146136420226902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6734146136420226902'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/07/silly-little-sql-server-information.html' title='Silly Little SQL Server Information Schema Helpers'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4187664208532171552</id><published>2008-07-11T15:30:00.007-04:00</published><updated>2008-07-11T15:53:27.367-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='SubSonic'/><title type='text'>Using "select  in" with SubSonic</title><content type='html'>While looking for SubSonic related information on something totally unrelated, I came across a post about trying to use the T-SQL "in" keyword to build a SubSonic collection at &lt;a href ="http://www.vitaminzproductions.com/technology-blog/index.php/2008/06/25/subsonic-select-where-in-solution"&gt;http://www.vitaminzproductions.com/technology-blog/index.php/2008/06/25/subsonic-select-where-in-solution&lt;/a&gt;. If that sounds confusing, imagine that you would like to have SubSonic return data that you would usually get with the following T-SQL statement:
&lt;br /&gt;
&lt;pre class="sql" name="code"&gt;
select *
from MyTable 
where id in ('val1', 'val2', 'val3')
&lt;/pre&gt;
&lt;br /&gt;
The author of the blog post had a solution but it was not one I liked. It seemed like a hack and I hate hacks. So, I took a few minutes and here is the result. The key is using the new SubSonic.Select query available in SubSonic v2.1. The code offers 3 different ways to accomplish the task.
&lt;br /&gt;
C# Code:

&lt;pre class="csharp" name="code"&gt;
// Define your collection object
MyTableCollection MyTableQuery;

// Define an array list for the first example
ArrayList ids = new ArrayList();
// Add some Guid values to the array list
ids.Add(new Guid("80FB189C-C3EA-4774-B15E-018DA88D3FE2"));
ids.Add(new Guid("88DE9C1D-26A7-4545-AA1E-01BDAEFF0588"));
    
// Poplulate the collection using an array list
MyTableQuery = new SubSonic.Select()
 .From(MyTable.Schema)
 .Where(MyTable.Columns.Id)
 .In(ids)
 .ExecuteAsCollection&lt;MyTableCollection&gt;();

// Poplulate the collection using an array of strings
MyTableQuery = new SubSonic.Select()
 .From(MyTable.Schema)
 .Where(MyTable.Columns.Id)
 .In(new string[] {
  "80FB189C-C3EA-4774-B15E-018DA88D3FE2",
  "88DE9C1D-26A7-4545-AA1E-01BDAEFF0588"})
 .ExecuteAsCollection&lt;MyTableCollection&gt;();
    
// Poplulate the collection using an inline select statement
MyTableQuery = new SubSonic.Select()
 .From(MyTable.Schema)
 .Where(MyTable.Columns.Id)
 .In(new SubSonic.Select(MyTable.Columns.Id)
 .Top("3")
 .From(MyTable.Schema))
 .ExecuteAsCollection&lt;MyTableCollection&gt;();
&lt;/pre&gt;

VB.NET Code:

&lt;pre class="vb" name="code"&gt;
' Define your collection object
Dim MyTableQuery As MyTableCollection

' Define an array list for the first example
Dim ids As New ArrayList

' Define an array list for the first example
ids.Add(New Guid("80FB189C-C3EA-4774-B15E-018DA88D3FE2"))
ids.Add(New Guid("88DE9C1D-26A7-4545-AA1E-01BDAEFF0588"))

' Poplulate the collection using an array list
MyTableQuery = New SubSonic.Select() _
    .From(MyTable.Schema) _
    .Where(MyTable.Columns.Id) _
    .In(ids).ExecuteAsCollection(Of MyTableCollection)()

' Poplulate the collection using an array of strings
MyTableQuery = New SubSonic.Select() _
    .From(MyTable.Schema) _
    .Where(MyTable.Columns.Id) _
    .In(New String() {"80FB189C-C3EA-4774-B15E-018DA88D3FE2", "88DE9C1D-26A7-4545-AA1E-01BDAEFF0588"}) _
    .ExecuteAsCollection(Of MyTableCollection)()

' Poplulate the collection using an inline select statement
MyTableQuery = New SubSonic.Select() _
    .From(MyTable.Schema) _
    .Where(MyTable.Columns.Id) _
    .In(New SubSonic.Select(MyTable.Columns.Id) _
    .Top("3") _
    .From(MyTable.Schema)) _
    .ExecuteAsCollection(Of MyTableCollection)()
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4187664208532171552?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4187664208532171552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4187664208532171552' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4187664208532171552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4187664208532171552'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/07/using-select-in-with-subsonic.html' title='Using &quot;select  in&quot; with SubSonic'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2183984287986841890</id><published>2008-04-10T15:59:00.001-04:00</published><updated>2008-04-10T16:00:21.138-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Automation'/><category scheme='http://www.blogger.com/atom/ns#' term='SubSonic'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Code Camp 9 Presentations</title><content type='html'>&lt;p&gt;This past weekend, I attended Code Camp 9 in Waltham, MA and gave two presentation:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;No Pain Database Access with Subsonic &lt;/li&gt;    &lt;li&gt;Windows and Development Automation with NAnt &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I am finally getting around to posting the presentation materials and supporting files here. So here goes.&lt;/p&gt;  &lt;h3&gt;No Pain Database Access with Subsonic&lt;/h3&gt;  &lt;p&gt;While I was disappointed with the turnout for this presentation and with my preparation, I learned a couple of things:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;I know very little about SubSonic. It's far from only an ORM framework, it's much more, and I don't know didly about it. &lt;/li&gt;    &lt;li&gt;I got to stop procrastinating &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The presentation is available in two forms:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Online at Google Docs:     &lt;br /&gt;&lt;a title="http://docs.google.com/Present?docid=dcz9szc5_25cz3xbtcx&amp;amp;skipauth=true" href="http://docs.google.com/Present?docid=dcz9szc5_25cz3xbtcx&amp;amp;skipauth=true" target="_blank"&gt;http://docs.google.com/Present?docid=dcz9szc5_25cz3xbtcx&amp;amp;skipauth=true&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;PDF format:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/NoPainDatabaseAccessWithSubSonic.pdf" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/NoPainDatabaseAccessWithSubSonic.pdf" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/NoPainDatabaseAccessWithSubSonic.pdf&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Support files are also available in two forms:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Online at Google Docs:     &lt;br /&gt;&lt;a title="http://docs.google.com/View?docid=dcz9szc5_28f8wb97fc" href="http://docs.google.com/View?docid=dcz9szc5_28f8wb97fc" target="_blank"&gt;http://docs.google.com/View?docid=dcz9szc5_28f8wb97fc&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;HTML version:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/No_Pain_Database_Access.html" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/No_Pain_Database_Access.html" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/No_Pain_Database_Access.html&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Downloads&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Database create script     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/createDB.txt" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/createDB.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/createDB.txt&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Example web site     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/subSonicWeb.zip" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/subSonicWeb.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/subSonicWeb.zip&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Windows and Development Automation with NAnt&lt;/h3&gt;  &lt;p&gt;I love NAnt. This presentation turned out great. I was prepared, I had lots of examples and people were interested - cool!&lt;/p&gt;  &lt;p&gt;Again, the presentation is available in two forms:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Online at Google Docs:     &lt;br /&gt; &lt;a title="http://docs.google.com/Present?docid=dcz9szc5_24fzjs9zgc&amp;amp;skipauth=true" href="http://docs.google.com/Present?docid=dcz9szc5_24fzjs9zgc&amp;amp;skipauth=true" target="_blank"&gt;http://docs.google.com/Present?docid=dcz9szc5_24fzjs9zgc&amp;amp;skipauth=true&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;PDF format:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/WindowsAndDevelopmentAutomationWithNAnt.pdf" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/WindowsAndDevelopmentAutomationWithNAnt.pdf" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/WindowsAndDevelopmentAutomationWithNAnt.pdf&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Support Files:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Online at Google Docs:     &lt;br /&gt;&lt;a title="http://docs.google.com/Doc?id=dcz9szc5_26gnfrmkfv" href="http://docs.google.com/Doc?id=dcz9szc5_26gnfrmkfv" target="_blank"&gt;http://docs.google.com/Doc?id=dcz9szc5_26gnfrmkfv&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;HTML version:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/Windows_and_Development.html" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/Windows_and_Development.html" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/Windows_and_Development.html&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Downloads&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;NAnt Examples:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntExamples.zip" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntExamples.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntExamples.zip&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Sample .NET Project:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/databaseInstaller.zip" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/databaseInstaller.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/databaseInstaller.zip&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;NAnt binaries (v0.85):     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAnt.zip" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAnt.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAnt.zip&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;NAnt docs:     &lt;br /&gt;&lt;a title="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntDocs.zip" href="http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntDocs.zip" target="_blank"&gt;http://tech-cats.net/blog/downloads/dotnet/codeCamp9/nantAutomation/NAntDocs.zip&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2183984287986841890?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2183984287986841890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2183984287986841890' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2183984287986841890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2183984287986841890'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/04/code-camp-9-presentations.html' title='Code Camp 9 Presentations'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4731877852153318350</id><published>2008-03-27T15:57:00.002-04:00</published><updated>2008-03-27T17:09:45.559-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Hey WMI, Where Can I Print</title><content type='html'>&lt;p&gt;Windows Management Instrumentation, or WMI for short, is a very powerful and often under used technology. I am simply fascinated by how much you can accomplish using WMI. It is mostly intended for computer management tasks but it can be used for much more. Some examples include getting all kinds of computer information, managing system services and application. This article will cover a possible solution for listing all available printers on a particular computer and show you to get this information through ColdFusion. WMI can be used through VBScript, C++ and .NET. However since part of my current work is done in .NET, the solution relies on .NET and IIS. Further more, here are the requirements that the we will satisfy:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;List all available printers including shared printers &lt;/li&gt;    &lt;li&gt;Allow for filtering the list of printers by the printer name &lt;/li&gt;    &lt;li&gt;Be language independent &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Accomplishing the first two tasks is fairly easy with WMI. So lets get started.&lt;/p&gt;  &lt;h2&gt;List All Available Printers&lt;/h2&gt;  &lt;p&gt;This is pretty straight forward using C# provided that you reference the System.Management namespace and add the appropriate &amp;quot;using&amp;quot; directive:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt;using System.Management;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;Next, we need to declare some variable to query WMI:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;ObjectQuery oq;
ConnectionOptions co;
ManagementScope ms;
ManagementObjectSearcher mos;
ManagementObjectCollection moc;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;Set the connection options:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;co = new System.Management.ConnectionOptions();
co.Authentication = System.Management.AuthenticationLevel.Default;
co.Impersonation = System.Management.ImpersonationLevel.Impersonate;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;Connect to the local machine:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;// Set the management scope to the local computer
ms = new ManagementScope(&amp;quot;\\\\&amp;quot; + Environment.MachineName, co);&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;And get the list of printers:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;// Create an object query to get the printer list
oq = new ObjectQuery(&amp;quot;select * from Win32_Printer&amp;quot;);

mos = new ManagementObjectSearcher(ms, oq);
moc = mos.Get();&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;What is left to do is just loop through the management objects found and display/aggregate the printer properties:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;if (moc != null)
{
    // Loop through the found printers and collect the information
    foreach (ManagementObject mo in moc)
    {
         // Do something with the printer name
         // mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString();
    }
}&lt;/pre&gt;

&lt;br /&gt;

&lt;h2&gt;Filtering By Printer Name&lt;/h2&gt;

&lt;p&gt;There is two ways that this can be accomplished. Let's explore both.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Using WMI query clause. 
    &lt;br /&gt;WMI on Windows XP or newer supports the &amp;quot;like&amp;quot; operator so filtering the printer list by the printer name or a partial printer name is very trivial: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;// Create an object query to get the printer list
oq = new ObjectQuery(&amp;quot;select * from Win32_Printer where Name like \&amp;quot;%myPrinterName%\&amp;quot;&amp;quot;);&lt;/pre&gt;

    &lt;br /&gt;Where &amp;quot;myPrinterName&amp;quot; is the full name or part of the name of the printer. Notice to use of &amp;quot;%&amp;quot; as those work as a wildcard.&amp;#160; &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Using simple string compare. 
    &lt;br /&gt;Since there are plenty of servers still using Windows 2000 the string compare method is more compatible: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;if (moc != null)
{
    // Loop through the found printers and collect the information
    foreach (ManagementObject mo in moc)
    {
         if (mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString().ToLower().Contains(&amp;quot;myPrinterName&amp;quot;))
         {
              // Do something with the printer name
              // mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString();
         }
    }
}&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Language Independence&lt;/h2&gt;

&lt;p&gt;A simple way to implement languages independence is through a web service. So we take the code above and wrap it in a web service. The two addition are the separation of the code in two functions (&lt;strong&gt;&lt;em&gt;getPrinters()&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;getPrintersWithNameFilter()&lt;/em&gt;&lt;/strong&gt;) and the addition of a small helper function called &lt;strong&gt;&lt;em&gt;saveProperties() . &lt;/em&gt;&lt;/strong&gt;Here is the final result:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Management;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;

namespace systemInfo
{
    /// &amp;lt;summary&amp;gt;
    /// Contains system related functions
    /// &amp;lt;/summary&amp;gt;
    [WebService(Namespace = &amp;quot;http://webapps/systemInfo&amp;quot;)]
    [Description(&amp;quot;Contains a set of printer related functions&amp;quot;)]
    public class systemInfo : System.Web.Services.WebService
    {
        /// &amp;lt;summary&amp;gt;
        /// Returns a list of available printers
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;systemData object serialized to XML&amp;lt;/returns&amp;gt;
        [WebMethod]
        [Description(&amp;quot;Returns a list of available printers&amp;quot;)]
        public systemData getPrinters()
        {
            return getPrintersWithNameFilter(null);
        }

        /// &amp;lt;summary&amp;gt;
        /// Returns a list of available printers filtered by the name specified
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&amp;quot;nameFilter&amp;quot;&amp;gt;The name of the printer to filter by&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;systemData object seralized to XML&amp;lt;/returns&amp;gt;
        [WebMethod(MessageName = &amp;quot;getPrintersWithNameFilter&amp;quot;)]
        [Description(&amp;quot;Returns a list of available printers filtered by the name specified&amp;quot;)]
        public systemData getPrintersWithNameFilter(string nameFilter)
        {
            ObjectQuery oq;
            ConnectionOptions co;
            ManagementScope ms;
            ManagementObjectSearcher mos;
            ManagementObjectCollection moc;
            int counter = 0;
            ArrayList properties = null;
            systemDataPrinter printer = null;
            systemData systemDataInstance = new systemData();

            if (!String.IsNullOrEmpty(nameFilter))
            {
                nameFilter = nameFilter.ToLower();
            }

            co = new System.Management.ConnectionOptions();
            co.Authentication = System.Management.AuthenticationLevel.Default;
            co.Impersonation = System.Management.ImpersonationLevel.Impersonate;

            // Set the management scope to the local computer
            ms = new ManagementScope(&amp;quot;\\\\&amp;quot; + Environment.MachineName, co);

            // Create an object query to get the printer list
            oq = new ObjectQuery(&amp;quot;select * from Win32_Printer&amp;quot;);

            mos = new ManagementObjectSearcher(ms, oq);
            moc = mos.Get();

            if (moc != null)
            {
                // Create an array of printer objects to store the printer data
                systemDataInstance.printer = new systemDataPrinter[moc.Count];

                // Loop through the found printers and collect the information
                foreach (ManagementObject mo in moc)
                {
                    properties = new ArrayList();
                    properties.Add(mo.Properties[&amp;quot;Name&amp;quot;]);
                    properties.Add(mo.Properties[&amp;quot;Location&amp;quot;]);
                    properties.Add(mo.Properties[&amp;quot;ShareName&amp;quot;]);
                    properties.Add(mo.Properties[&amp;quot;Description&amp;quot;]);
                    properties.Add(mo.Properties[&amp;quot;Caption&amp;quot;]);

                    if (!String.IsNullOrEmpty(nameFilter))
                    {
                        // Filter the printers returned by the name filter specified
                        // Also, exclude printers that start with &amp;quot;__&amp;quot; since those are printer sessions
                        if (mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString().ToLower().Contains(nameFilter)
                        &amp;amp;&amp;amp; !mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString().StartsWith(&amp;quot;__&amp;quot;))
                        {
                            printer = new systemDataPrinter();

                            // Save all the properties from the array list
                            // to the printer object
                            saveProperties(properties, ref printer);

                            // Add the current printer object to the array of printers
                            systemDataInstance.printer[counter] = printer;

                            counter++;
                        }
                    }
                    // Exclude printers that start with &amp;quot;__&amp;quot; since those are printer sessions
                    else if (!mo.Properties[&amp;quot;Name&amp;quot;].Value.ToString().StartsWith(&amp;quot;__&amp;quot;))
                    {
                        printer = new systemDataPrinter();

                        // Save all the properties from the array list
                        // to the printer object
                        saveProperties(properties, ref printer);

                        // Add the current printer object to the array of printers
                        systemDataInstance.printer[counter] = printer;

                        counter++;
                    }
                }
            }

            return systemDataInstance;
        }

        /// &amp;lt;summary&amp;gt;
        /// Saves the properties passed by the ManagementObject into
        /// an instance of the printer object
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&amp;quot;properties&amp;quot;&amp;gt;A list of printer properties&amp;lt;/param&amp;gt;
        /// &amp;lt;param name=&amp;quot;printer&amp;quot;&amp;gt;The printer object where the properties will be stored&amp;lt;/param&amp;gt;
        private void saveProperties(ArrayList properties, ref systemDataPrinter printer)
        {
            PropertyInfo pi = null;
            string value = String.Empty;

            foreach (PropertyData prop in properties)
            {
                value = Convert.ToString(prop.Value);

                // Get the printer property corresponding to the current property name
                pi = printer.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

                if (pi != null)
                {
                    // Set the value of the current property through reflextion
                    pi.SetValue(printer, value, null);
                }
            }
        }
    }
}&lt;/pre&gt;

&lt;br /&gt;

&lt;h2&gt;Consuming with ColdFusion&lt;/h2&gt;

&lt;p&gt;Getting the information from the web service and into ColdFusion readable format is as easy as calling any other web service. First you create a web service object and point it to the WSDL URL:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;cfset systemInfoService = createObject(&amp;quot;webservice&amp;quot;, &amp;quot;http://webapps/systemInfo/systemInfo.asmx?WSDL&amp;quot;) /&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;Next, you call the &lt;strong&gt;&lt;em&gt;getPrinters()&lt;/em&gt;&lt;/strong&gt; function to get a list of all the printers installed on the computer:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;cfset printersArray = systemInfoService.getPrinters().getPrinter() /&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;the &lt;strong&gt;&lt;em&gt;getPrinter()&lt;/em&gt;&lt;/strong&gt; on the end returns an array of printer objects:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/getPrintersCFDump.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="620" alt="getPrintersCFDump" src="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/getPrintersCFDump_thumb.png" width="449" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you like to filter the list of printers and get only the printers that are installed on a different server but shared locally, you just need to pass a string containing part of the server name:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;cfset printersArray = systemInfoService.getPrintersWithNameFilter(nameFilter = &amp;quot;\\ntserver_hq5&amp;quot;).getPrinter() /&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;Where &amp;quot;ntserver_hq5&amp;quot; is the name of the server where the printer is actually installed. For network printers installed locally, WMI returns the server name as part of the printer name.&lt;/p&gt;

&lt;p&gt;Once you perform the web service call, you simply output the printers array as follows:&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;cfoutput&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;cfloop from=&amp;quot;1&amp;quot; to=&amp;quot;#arraylen(printersArray)#&amp;quot; index=&amp;quot;i&amp;quot;&amp;gt;
 &amp;lt;li&amp;gt;
   #printersArray[i].getName()#
    &amp;lt;ol&amp;gt;
      &amp;lt;li&amp;gt;
      Location: #printersArray[i].getLocation()#
      &amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;
      ShareName: #printersArray[i].getShareName()#
      &amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;
      Description: #printersArray[i].getDescription()#
      &amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;
      Caption: #printersArray[i].getCaption()#
      &amp;lt;/li&amp;gt;
    &amp;lt;/ol&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;/cfloop&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;/cfoutput&amp;gt;&lt;/pre&gt;
&lt;a href="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/getPrintersWithNameFilterOutput.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="118" alt="getPrintersWithNameFilterOutput" src="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/getPrintersWithNameFilterOutput_thumb.png" width="363" border="0" /&gt;&lt;/a&gt; 

&lt;br /&gt;

&lt;h2&gt;Implementation Details&lt;/h2&gt;

&lt;p&gt;The service returns four properties for each printer. Here is an example XML:&lt;/p&gt;

&lt;pre class="xml" name="code"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;systemData xmlns:xs=&amp;quot;http://webapps/systemInfo&amp;quot;&amp;gt;
  &amp;lt;printer&amp;gt;
    &amp;lt;name&amp;gt;t&amp;lt;/name&amp;gt;
    &amp;lt;location&amp;gt;t&amp;lt;/location&amp;gt;
    &amp;lt;shareName&amp;gt;t&amp;lt;/shareName&amp;gt;
    &amp;lt;description&amp;gt;t&amp;lt;/description&amp;gt;
    &amp;lt;caption&amp;gt;t&amp;lt;/caption&amp;gt;
  &amp;lt;/printer&amp;gt;
  &amp;lt;printer&amp;gt;
    &amp;lt;name&amp;gt;t&amp;lt;/name&amp;gt;
    &amp;lt;location&amp;gt;t&amp;lt;/location&amp;gt;
    &amp;lt;shareName&amp;gt;t&amp;lt;/shareName&amp;gt;
    &amp;lt;description&amp;gt;t&amp;lt;/description&amp;gt;
    &amp;lt;caption&amp;gt;t&amp;lt;/caption&amp;gt;
  &amp;lt;/printer&amp;gt;
&amp;lt;/systemData&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;WMI actually returns quite a few properties for each printer. However, I chose only the &lt;strong&gt;Name&lt;/strong&gt;, &lt;strong&gt;Location&lt;/strong&gt;, &lt;strong&gt;ShareName&lt;/strong&gt;, &lt;strong&gt;Description&lt;/strong&gt; and &lt;strong&gt;Caption &lt;/strong&gt;as relevant.&lt;/p&gt;

&lt;p&gt;Once the sample XML is defined, Visual Studio makes it pretty easy to generate a XML Schema from your sample XML by going to the &amp;quot;XML&amp;quot; menu and clicking on &amp;quot;Create Schema&amp;quot;&lt;/p&gt;

&lt;p&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="createXMLSchema" src="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/createXMLSchema.jpg" width="546" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;You end up with the following schema:&lt;/p&gt;

&lt;pre class="xml" name="code"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;schema xmlns:xs=&amp;quot;http://webapps/systemInfo&amp;quot; attributeFormDefault=&amp;quot;unqualified&amp;quot; elementFormDefault=&amp;quot;qualified&amp;quot; xmlns=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&amp;gt;
  &amp;lt;element name=&amp;quot;systemData&amp;quot;&amp;gt;
    &amp;lt;complexType&amp;gt;
      &amp;lt;sequence&amp;gt;
        &amp;lt;element maxOccurs=&amp;quot;unbounded&amp;quot; name=&amp;quot;printer&amp;quot;&amp;gt;
          &amp;lt;complexType&amp;gt;
            &amp;lt;sequence&amp;gt;
              &amp;lt;element name=&amp;quot;name&amp;quot; type=&amp;quot;string&amp;quot; /&amp;gt;
              &amp;lt;element name=&amp;quot;location&amp;quot; type=&amp;quot;string&amp;quot; /&amp;gt;
              &amp;lt;element name=&amp;quot;shareName&amp;quot; type=&amp;quot;string&amp;quot; /&amp;gt;
              &amp;lt;element name=&amp;quot;description&amp;quot; type=&amp;quot;string&amp;quot; /&amp;gt;
              &amp;lt;element name=&amp;quot;caption&amp;quot; type=&amp;quot;string&amp;quot; /&amp;gt;
            &amp;lt;/sequence&amp;gt;
          &amp;lt;/complexType&amp;gt;
        &amp;lt;/element&amp;gt;
      &amp;lt;/sequence&amp;gt;
    &amp;lt;/complexType&amp;gt;
  &amp;lt;/element&amp;gt;
&amp;lt;/schema&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;To convert the schema to a C# class so we can populate it at runtime, serialize it and return it we can use the xsd.exe utility with the following arguments:&lt;/p&gt;

&lt;pre class="xml" name="code"&gt;C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\xsd.exe &amp;quot;path\to\schema.xsd&amp;quot; /classes /nologo /out:&amp;quot;path/to/output.cs&amp;quot;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;This way we end up with a serializable C# class which can be populated at runtime and still be serialized as our example XML. I called mine &lt;strong&gt;&lt;em&gt;systemData &lt;/em&gt;&lt;/strong&gt;and used it above as:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;// Create new instance of the systeData class
systemData systemDataInstance = new systemData();

// Create a new instance of the systemDataPrinter class
systemDataPrinter printer = null;

// Create an array of printer objects to store the printer data
systemDataInstance.printer = new systemDataPrinter[moc.Count];&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;where &lt;strong&gt;&lt;em&gt;moc.Count &lt;/em&gt;&lt;/strong&gt;is the number of WMI &lt;strong&gt;&lt;em&gt;ManagementObject &lt;/em&gt;&lt;/strong&gt;that was returned for the WMI query&lt;strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The last point worth mentioning is inside the &lt;strong&gt;&lt;em&gt;saveProperties() &lt;/em&gt;&lt;/strong&gt;function. The function takes an array list of properties, loops over them and for each one sets the according property in the systemDataPrinter class. It does so by using reflextion:&lt;/p&gt;

&lt;pre class="csharp" name="code"&gt;// Get the printer property corresponding to the current property name
pi = printer.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

if (pi != null)
{
    // Set the value of the current property through reflextion
    pi.SetValue(printer, value, null);
}&lt;/pre&gt;

&lt;h2&gt;Gotchas&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;To get network printers listed you have to have the printer installed on the machine under a local account and configure the web service to use the account when performing the query. You use the &amp;quot;&lt;strong&gt;&lt;em&gt;impersonate&lt;/em&gt;&lt;/strong&gt;&amp;quot; tag and specify the user and the password: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;identity impersonate=&amp;quot;true&amp;quot; userName=&amp;quot;user@domain.com&amp;quot; password=&amp;quot;password&amp;quot; /&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Once you use xsd.exe to generated the C# serializable class, you have to edit it and add the &lt;strong&gt;&lt;em&gt;namespace&lt;/em&gt;&lt;/strong&gt; for the root node attribute: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;[System.Xml.Serialization.XmlRootAttribute(Namespace = &amp;quot;http://webapps/systemInfo&amp;quot;, IsNullable = false)]&lt;br /&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;The web service has to be setup in IIS by creating an application and setting the directory security to allow anonymous access. 
    &lt;br /&gt;&lt;a href="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/iisCreateApplication.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="238" alt="iisCreateApplication" src="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/iisCreateApplication_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;a href="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/iisSetDirectorySecurity.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="145" alt="iisSetDirectorySecurity" src="http://tech-cats.net/blog/images/HeyWMIWhereCanIPrint_C69A/iisSetDirectorySecurity_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;The web service has to be configured to allow calls through HTTP get inside the &lt;strong&gt;&lt;em&gt;Web.config&lt;/em&gt;&lt;/strong&gt;: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;webServices&amp;gt;
  &amp;lt;protocols&amp;gt;
    &amp;lt;add name=&amp;quot;HttpGet&amp;quot;/&amp;gt;
  &amp;lt;/protocols&amp;gt;
&amp;lt;/webServices&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Downloads&lt;/h2&gt;

&lt;p&gt;Web Service Implementation: &lt;a title="systemInfo.printer.zip" href="http://tech-cats.net/blog/downloads/dotnet/systemInfo.printers.zip" target="_blank"&gt;systemInfo.printer.zip&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4731877852153318350?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4731877852153318350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4731877852153318350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4731877852153318350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4731877852153318350'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/hey-wmi-where-can-i-print.html' title='Hey WMI, Where Can I Print'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8233847349455894030</id><published>2008-03-24T15:34:00.001-04:00</published><updated>2008-03-24T15:34:21.040-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Simple Logging in Your .NET Application</title><content type='html'>&lt;p&gt;Logging can be a very useful tool when developing any application. Furthermore, logging is a must when deploying applications to a production environment. Keeping track of errors and informational messages can help you greatly reduce the time it takes to debug and fix a problem. As in any language, there is more than one way to enable logging in .NET. This article will cover getting started with logging using the free &lt;a title="http://logging.apache.org/log4net" href="http://logging.apache.org/log4net/" target="_blank"&gt;log4net&lt;/a&gt; framework.&lt;/p&gt;  &lt;h2&gt;To Get Started&lt;/h2&gt;  &lt;ol&gt;   &lt;li&gt;Get log4net from &lt;a title="http://logging.apache.org/log4net/download.html" href="http://logging.apache.org/log4net/download.html" target="_blank"&gt;http://logging.apache.org/log4net/download.html&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Create a sample .NET application that and call it &amp;quot;sampleLoggingApp&amp;quot; &lt;/li&gt;    &lt;li&gt;Create a place to store the log4net DLL, I usually create a &amp;quot;dependencies&amp;quot; directory &lt;/li&gt;    &lt;li&gt;Copy the extracted log4net DLL from &amp;quot;bin\net\2.0\release\log4net.dll&amp;quot; to your &amp;quot;dependencies&amp;quot; directory &lt;/li&gt;    &lt;li&gt;Set your Visual Studio to show all files, include the log4net DLL in your project and add a reference to it in your project &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;The Fun Stuff&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create your log4net configuration file, we will call it log4net.config to keep appending to the same file:      &lt;br /&gt;      &lt;br /&gt;      &lt;pre class="xml" name="code"&gt;&amp;lt;log4net&amp;gt;
  &amp;lt;appender name=&amp;quot;RollingLogFileAppender&amp;quot; type=&amp;quot;log4net.Appender.RollingFileAppender&amp;quot;&amp;gt;
    &amp;lt;file value=&amp;quot;sampleLog.log&amp;quot; /&amp;gt;
    &amp;lt;layout type=&amp;quot;log4net.Layout.PatternLayout&amp;quot;&amp;gt;
      &amp;lt;conversionPattern value=&amp;quot;%date [%thread] %-5level %logger [%ndc] - %message%newline&amp;quot; /&amp;gt;
    &amp;lt;/layout&amp;gt;
  &amp;lt;/appender&amp;gt;

  &amp;lt;root&amp;gt;
    &amp;lt;level value=&amp;quot;DEBUG&amp;quot; /&amp;gt;
    &amp;lt;appender-ref ref=&amp;quot;RollingLogFileAppender&amp;quot; /&amp;gt;
  &amp;lt;/root&amp;gt;
&amp;lt;/log4net&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Set the path to the log4net.config file: 
    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;private static String m_log4netConfigFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), &amp;quot;log4net.config&amp;quot;);&lt;/pre&gt;

    &lt;br /&gt;This sets the path of the log4net.config file to be in the same directory are your executable. 

    &lt;br /&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Create a static log instance: 
    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;private static readonly ILog m_log = LogManager.GetLogger(typeof(Form1));&lt;/pre&gt;

    &lt;br /&gt;Where &amp;quot;Form1&amp;quot; is the name of your application instance. 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Set a build event in Visual Studio that will copy the log4net configuration file in the output directory on every build: 
    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;xcopy /y &amp;quot;$(ProjectDir)log4net.config&amp;quot; &amp;quot;$(TargetDir)&amp;quot;&lt;/pre&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Write some information to the log: 
    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="csharp" name="code"&gt;m_log.Debug(&amp;quot;Inside Form1_Load&amp;quot;);&lt;/pre&gt;

    &lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;More Information&lt;/h2&gt;

&lt;p&gt;I have covered the basics of getting started. However, log4net has quite a few more possible configurations such as&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Log to a database table &lt;/li&gt;

  &lt;li&gt;Log to the console &lt;/li&gt;

  &lt;li&gt;Log to the event log &lt;/li&gt;

  &lt;li&gt;Log to an email address &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information for each configuration can be found at &lt;a title="http://logging.apache.org/log4net/release/config-examples.html" href="http://logging.apache.org/log4net/release/config-examples.html" target="_blank"&gt;http://logging.apache.org/log4net/release/config-examples.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Downloads&lt;/h2&gt;

&lt;p&gt;&lt;a title="sampleLoggingApp.zip" href="http://tech-cats.net/blog/examples/dotnet/sampleLoggingApp.zip" target="_blank"&gt;sampleLoggingApp.zip&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8233847349455894030?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8233847349455894030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8233847349455894030' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8233847349455894030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8233847349455894030'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/simple-logging-in-your-net-application.html' title='Simple Logging in Your .NET Application'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-66864684144386641</id><published>2008-03-20T14:34:00.001-04:00</published><updated>2008-03-20T14:34:37.672-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Model-Glue Tips and Tricks</title><content type='html'>&lt;ol&gt;   &lt;li&gt;     &lt;h2&gt;&lt;b&gt;Turn off automatic reloading of your application&lt;/b&gt; &lt;/h2&gt;      &lt;br /&gt;This will greatly reduce the time the application needs to process all request. This is the way I develop Model-Glue applications. In your Model-Glue configuration (the &amp;quot;&lt;b&gt;&lt;i&gt;modelGlueConfiguration&lt;/i&gt;&lt;/b&gt;&amp;quot; bean in ColdSpring.xml), look for the &amp;quot;&lt;b&gt;&lt;i&gt;reload&lt;/i&gt;&lt;/b&gt;&amp;quot; property and set it to false:       &lt;br /&gt;      &lt;br /&gt;      &lt;pre class="xml" name="code"&gt;&amp;lt;property name=&amp;quot;reload&amp;quot;&amp;gt;&lt;br /&gt;	&amp;lt;value&amp;gt;false&amp;lt;/value&amp;gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;Keep in mind that changes made to anything else but your views will require an application reload. For my approach to that, read the next tip. &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Use two browsers&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;The basics of this point has to do with using one browser for your development and one for reloading the application. I suggest this since if your application keep session state, reloading the application from the same browser will reset the session while reloading the application from a different browser will not. If you turn the Model-Glue automatic reload, your application will run faster but you will not be able to see any changes made in your controllers or model. Once you made a change you will need to manually reload the application by invoking the &amp;quot;&lt;b&gt;&lt;i&gt;reloadKey&lt;/i&gt;&lt;/b&gt;&amp;quot; with the &amp;quot;&lt;b&gt;&lt;i&gt;reloadPassword&lt;/i&gt;&lt;/b&gt;&amp;quot; as defined in the ColdSpring.xml file. By default the &amp;quot;&lt;b&gt;&lt;i&gt;reloadKey&lt;/i&gt;&lt;/b&gt;&amp;quot; is set to &amp;quot;&lt;b&gt;&lt;i&gt;init&lt;/i&gt;&lt;/b&gt;&amp;quot; and the &amp;quot;&lt;b&gt;&lt;i&gt;reloadPassword&lt;/i&gt;&lt;/b&gt;&amp;quot; is set to &amp;quot;true&amp;quot;. So you would reload by invoking &amp;quot;&lt;strong&gt;&lt;em&gt;index.cfm?init=true&lt;/em&gt;&lt;/strong&gt;&amp;quot;. To take this further I add the following code to my &lt;b&gt;&lt;i&gt;onRequestStart&lt;/i&gt;&lt;/b&gt; inside Application.cfc to reload the application if you simply go to &lt;b&gt;&lt;i&gt;&amp;quot;/yourApplication/?init&lt;/i&gt;&lt;/b&gt;&amp;quot;: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;&amp;lt;cffunction name=&amp;quot;OnRequestStart&amp;quot; output=&amp;quot;no&amp;quot;&amp;gt;&lt;br /&gt;	&amp;lt;cfif structKeyExists(url, &amp;quot;init&amp;quot;)&amp;gt;&lt;br /&gt;		&amp;lt;cfset structclear(Application) /&amp;gt;&lt;br /&gt;		&amp;lt;cfset structclear(Session) /&amp;gt;&lt;br /&gt;&lt;br /&gt;		&amp;lt;cfset onApplicationStart() /&amp;gt;&lt;br /&gt;	&amp;lt;/cfif&amp;gt;&lt;br /&gt;&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Turn on debugging&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;Debugging is enabled by default but to turn it on or off you change the &amp;quot;true/false&amp;quot; value inside the &amp;quot;modelGlueConfiguration&amp;quot; bean in your ColdSpring.xml&amp;quot; file: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;property name=&amp;quot;debug&amp;quot;&amp;gt;&lt;br /&gt;	&amp;lt;value&amp;gt;true&amp;lt;/value&amp;gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Use a custom ColdSpring bean for your configuration settings&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;To store your own configuration values to be used throughout the application you can take advantage of Model-Glues &amp;quot; &lt;strong&gt;&lt;em&gt;SimpleConfig&lt;/em&gt;&lt;/strong&gt; bean. This bean configuration will go in your ColdSpring.xml file and look something like: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;bean id=&amp;quot;applicationConfiguration&amp;quot; class=&amp;quot;ModelGlue.Bean.CommonBeans.SimpleConfig&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;property name=&amp;quot;config&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;map&amp;gt;&lt;br /&gt;	&amp;lt;!-- The network path where the bartender templates are stored --&amp;gt;&lt;br /&gt;	&amp;lt;entry key=&amp;quot;networkPathToLabelTemplates&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;\\larry\indium\Production\labelGeneration&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/entry&amp;gt;&lt;br /&gt;&amp;lt;/map&amp;gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/config&amp;gt;&lt;br /&gt;&lt;/pre&gt;

    &lt;br /&gt;To access your &lt;b&gt;&lt;i&gt;applicationConfiguration&lt;/i&gt;&lt;/b&gt; bean, you would use: 

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;getModelGlue().getBean(&amp;quot;applicationConfiguration&amp;quot;, true)&lt;/pre&gt;

    &lt;br /&gt;I usually do this inside the &amp;quot;&lt;b&gt;&lt;i&gt;init&lt;/i&gt;&lt;/b&gt;&amp;quot; method of my controller: 

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;&amp;lt;cfset variables.appConfig = getModelGlue().getBean(&amp;quot;applicationConfiguration&amp;quot;, true) /&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;And use it later on with: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;&amp;lt;!--- Get the path to the label templates from the configuration ---&amp;gt;&lt;br /&gt;&amp;lt;cfset var networkPathToLabelTemplates = variables.appConfig.getConfigSetting(&amp;quot;networkPathToLabelTemplates&amp;quot;) /&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Take advantage of an ORM framework such as Reactor&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;Initial versions Model-Glue used to come with Reactor but do no longer. I found it is a little difficult for a novice to start using Reactor with Model-Glue. To take advantage of Reactor, you have to &lt;a href="http://trac.reactorframework.com" target="_blank"&gt;download&lt;/a&gt; it, unzip it and create a ColdFusion mapping called &amp;quot;reactor&amp;quot; that points to your Reactor directory. Next comes the Model-Glue configuration. You need to add the following bean definitions to your ColdSpring.xml: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;bean id=&amp;quot;ormAdapter&amp;quot; class=&amp;quot;ModelGlue.unity.orm.ReactorAdapter&amp;quot;&amp;gt;
	&amp;lt;constructor-arg name=&amp;quot;framework&amp;quot;&amp;gt;
		&amp;lt;ref bean=&amp;quot;ModelGlue&amp;quot; /&amp;gt;
	&amp;lt;/constructor-arg&amp;gt;
&amp;lt;/bean&amp;gt;

&amp;lt;bean id=&amp;quot;ormService&amp;quot; class=&amp;quot;reactor.reactorFactory&amp;quot;&amp;gt;
	&amp;lt;constructor-arg name=&amp;quot;configuration&amp;quot;&amp;gt;
		&amp;lt;ref bean=&amp;quot;reactorConfiguration&amp;quot; /&amp;gt;
&amp;lt;/constructor-arg&amp;gt;
&amp;lt;/bean&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;

    &lt;br /&gt;And of course you need the &amp;quot;reactorConfiguraiton&amp;quot; bean: 

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;bean id=&amp;quot;reactorConfiguration&amp;quot; class=&amp;quot;reactor.config.config&amp;quot;&amp;gt;&lt;br /&gt;	&amp;lt;constructor-arg name=&amp;quot;pathToConfigXml&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;/labelGeneration/config/Reactor.xml&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/constructor-arg&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;property name=&amp;quot;project&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;labelGeneration&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;property name=&amp;quot;dsn&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;labelGeneration&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;property name=&amp;quot;type&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;mssql&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;property name=&amp;quot;mapping&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;/labelGeneration/model&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;property name=&amp;quot;mode&amp;quot;&amp;gt;&lt;br /&gt;		&amp;lt;value&amp;gt;production&amp;lt;/value&amp;gt;&lt;br /&gt;	&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;
Now you can take advantage of Model-Glue's built in scaffolding and generic messages (&lt;b&gt;&lt;i&gt;genericList&lt;/i&gt;&lt;/b&gt;, &lt;b&gt;&lt;i&gt;genericRead&lt;/i&gt;&lt;/b&gt;, &lt;b&gt;&lt;i&gt;genericCommit&lt;/i&gt;&lt;/b&gt; and &lt;b&gt;&lt;i&gt;genericDelete&lt;/i&gt;&lt;/b&gt;). &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Use event beans&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;Event bean is a predefined CFC that will store values form your form. It works by creating a one to one relationship between your form values and getters/setters in your CFC. Once you have your event bean created you can populate it from everything in the form scope by using the &lt;b&gt;&lt;i&gt;makeEventBean&lt;/i&gt;&lt;/b&gt; function: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;&amp;lt;!--- Create an instance of the bean ---&amp;gt;&lt;br /&gt;&amp;lt;cfset var completePrintJobFormBean = getModelGlue().getBean(&amp;quot;completePrintJobFormBean&amp;quot;) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset arguments.event.makeEventBean(completePrintJobFormBean) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Trace the label data id field ---&amp;gt;&lt;br /&gt;&amp;lt;cfset arguments.event.trace(&amp;quot;labelDataID&amp;quot;, completePrintJobFormBean.getLabelDataID()) /&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;Creating event beans has to do with defining getters/setters and local variables for each one of your form fields. It can be a tedious process but thankfully there is the &lt;a title="Rooibos Generation" href="http://rooibos.maestropublishing.com/" target="_blank"&gt;Rooibos Generation&lt;/a&gt; to do it for you by simply taking the names of your form fields and generating all the code for your. You can learn more about this at Dan Wilson's blog article about &lt;a title="So you want to create a ModelGlue:Unity application? ( Part 3 )" href="http://www.nodans.com/index.cfm/2007/1/21/So-you-want-to-create-a-ModelGlueUnity-application--Part-3-#more"&gt;So you want to create a ModelGlue:Unity application? ( Part 3 )&lt;/a&gt;. 

    &lt;br /&gt;

    &lt;br /&gt;To use your newly generated bean, you will have to add the bean definition to your ColdSpring.xml file: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;bean id=&amp;quot;completePrintJobFormBean&amp;quot;&lt;br /&gt;	class=&amp;quot;labelGeneration.model.completePrintJobFormBean&amp;quot;&lt;br /&gt;	singleton=&amp;quot;false&amp;quot; /&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;Keep in mind that if your form changes, you have to regenerate the bean. If you do not care about reusing your beans through external consumers, such as Flex, I have written about an alternative approach in &amp;quot;&lt;a title="Get All Form Fields in ModelGlue the Elegant Way" href="/news/get-all-form-fields-modelglue-" target="_blank"&gt;Get All Form Fields in ModelGlue the Elegant Way&lt;/a&gt;&amp;quot;. &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;&lt;b&gt;Use tracing to debug the value of your variables&lt;/b&gt; &lt;/h2&gt;

    &lt;br /&gt;Once you have debugging enabled, you can add values to your debug output by using the event.trace() method: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="cf" name="code"&gt;&amp;lt;cfset arguments.event.trace(&amp;quot;myVariableValue&amp;quot;, myVariable) /&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h2&gt;Split your configuration in multiple files &lt;/h2&gt;

    &lt;br /&gt;You can tell ModelGlue to include different configuration files by using the &amp;quot;include template&amp;quot; directive. I use this approach to separate my events based on the action they are related to: 

    &lt;br /&gt;

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;modelglue&amp;gt;&lt;br /&gt;	&amp;lt;include template=&amp;quot;./config/events/labelEvents.xml&amp;quot;/&amp;gt;&lt;br /&gt;	....&lt;br /&gt;&amp;lt;/modelglue&amp;gt;&lt;/pre&gt;

    &lt;br /&gt;Here is what the included files looks like: 

    &lt;br /&gt;

    &lt;pre class="xml" name="code"&gt;&amp;lt;modelglue&amp;gt;&lt;br /&gt;&amp;lt;event-handlers&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;event-handler name=&amp;quot;overRideLabelData&amp;quot;&amp;gt;&lt;br /&gt;	&amp;lt;views&amp;gt;&lt;br /&gt;		&amp;lt;view name=&amp;quot;body&amp;quot; template=&amp;quot;frmOverRideLabelData.cfm&amp;quot; /&amp;gt;&lt;br /&gt;	&amp;lt;/views&amp;gt;&lt;br /&gt;&lt;br /&gt;	&amp;lt;results&amp;gt;&lt;br /&gt;		&amp;lt;result do=&amp;quot;strippedApplicationTemplate&amp;quot; /&amp;gt;&lt;br /&gt;	&amp;lt;/results&amp;gt;&lt;br /&gt;&amp;lt;/event-handler&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/event-handlers&amp;gt;&lt;br /&gt;&amp;lt;/modelglue&amp;gt; &lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-66864684144386641?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/66864684144386641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=66864684144386641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/66864684144386641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/66864684144386641'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/model-glue-tips-and-tricks.html' title='Model-Glue Tips and Tricks'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3928590161888303243</id><published>2008-03-17T15:45:00.001-04:00</published><updated>2008-03-17T16:01:34.964-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Querying the File System - From ColdFusion to SQL Server</title><content type='html'>&lt;p&gt;While looking for a solution of a different problem, I realized that SQL Server has a feature called extended stored procedures. Extended stored procedures, at least in SQL Server 2000, have to be written in C++ and compiled to a DLL. A good example of such a procedure is my previous article on &lt;a href="http://blog.tech-cats.com/2007/09/using-regular-expression-in-sql-server.html"&gt;Using Regular Expression in SQL Server&lt;/a&gt;. I am not going to get into how to write extended stored procedures in this article since my C++ skills are rusty at best. Instead, I will talk about using an existing stored procedure to query the file system and how to move from using ColdFusion to using SQL Server.&lt;/p&gt;  &lt;h3&gt;Using ColdFusion&lt;/h3&gt;  &lt;p&gt;Getting a list of files is pretty trivial in ColdFusion. All you have to do is use the &amp;quot;&amp;lt;cfdirectory&amp;gt;&amp;quot; tag like so:&lt;/p&gt;  &lt;pre class="cf" name="code"&gt;&amp;lt;cfset localDirectoryPath = &amp;quot;C:\Temp&amp;quot; /&amp;gt;

&amp;lt;cfdirectory
	name=&amp;quot;textFiles&amp;quot;
	action=&amp;quot;list&amp;quot;
	filter=&amp;quot;*.txt&amp;quot;
	directory=&amp;quot;#localDirectoryPath#&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;That will get a list of all files with the &amp;quot;.txt&amp;quot; extension in the &amp;quot;C:\Temp&amp;quot; directory.&lt;/p&gt;

&lt;p&gt;Getting a list of files from a network drive is not any different except for specifying the networks path as UNC path (and a little service configuration):&lt;/p&gt;

&lt;pre class="cf" name="code"&gt;&amp;lt;cfset networkDirectoryPath = &amp;quot;\\larry\share&amp;quot; /&amp;gt;

&amp;lt;cfdirectory
	name=&amp;quot;textFiles&amp;quot;
	action=&amp;quot;list&amp;quot;
	filter=&amp;quot;*.txt&amp;quot;
	directory=&amp;quot;#networkDirectoryPath#&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;br /&gt;As stated above, this will not work if you do not have the ColdFusion service configured to use a specific account that has access to your network path.&lt;/p&gt;

&lt;p&gt;The typical ColdFusion service setup looks like the following screen shot when accessed through the &amp;quot;Services&amp;quot; configuration in Windows:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/coldFusionServiceNoUser.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="coldFusionServiceNoUser" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/coldFusionServiceNoUser_thumb.jpg" width="216" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To be able to query a network path, you need to specify a user that has access to that network path:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/coldFusionServiceUser.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="coldFusionServiceUser" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/coldFusionServiceUser_thumb.jpg" width="216" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;Using SQL Server&lt;/h3&gt;

&lt;p&gt;The setup for using SQL Server for querying network paths is the same as the one for ColdFusion:&lt;/p&gt;

&lt;p&gt;Default Setup &lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerServiceNoUser.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="sqlServerServiceNoUser" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerServiceNoUser_thumb.jpg" width="216" border="0" /&gt;&lt;/a&gt; But should be something like &lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerServiceUser.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="sqlServerServiceUser" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerServiceUser_thumb.jpg" width="216" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you do not setup the SQL Server to run as the appropriate user, trying to query a network path with the method provided here, you will an access denied error:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerAccessDenied.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="52" alt="sqlServerAccessDenied" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/sqlServerAccessDenied_thumb.jpg" width="181" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;With that aside, I have written a custom stored procedures based on the built-in extended stored procedure &amp;quot;xp_cmdshell&amp;quot;. This procedure will return a query with the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;fileID - unique auto incremented integer value &lt;/li&gt;

  &lt;li&gt;fileName - the name of the file &lt;/li&gt;

  &lt;li&gt;lastModifiedOn - the date the file was last modified &lt;/li&gt;

  &lt;li&gt;fileSize - the size of the file in bytes &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the results of querying the local path &amp;quot;C:\Temp&amp;quot; without a file extensions filter:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;exec dbo.getDirectoryFileList 'c:\temp', null&lt;/pre&gt;

&lt;p&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="390" alt="queryingFileSystemNoFilter" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/queryingFileSystemNoFilter.jpg" width="698" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;Once configured the procedure can also work on network drives like so to return only files with the &amp;quot;.btw&amp;quot; extension:&lt;/p&gt;

&lt;pre class="sql" name="code"&gt;exec dbo.getDirectoryFileList '\\larry\indium\Production\labelGeneration', '*.btw'&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/queryingFileSystemWithFilter.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="104" alt="queryingFileSystemWithFilter" src="http://tech-cats.net/blog/images/QueryingtheFileSystemwithSQLServer_DC43/queryingFileSystemWithFilter_thumb.jpg" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;Show Me the Code&lt;/h3&gt;

&lt;pre class="sql" name="code"&gt;/*
Type:		Stored Procedure
Name:		dbo.getDirectoryFileList
Author:		Boyan Kostadinov
Created:	03.17.2008
Dependencies:	master.dbo.xp_cmdshell
Usage:		exec dbo.getDirectoryFileList 'c:\temp', null
		exec dbo.getDirectoryFileList '\\larry\indium\Production\labelGeneration', '*.btw'
Parameters:	@directoryPath varchar(255)
		- The path of the local or network directory

		@fileExtensionFilter varchar(10) - Optional
		- The file extension to filter the file list by
Returns:	A list of files found on the file system
*/
create procedure dbo.getDirectoryFileList
	@directoryPath varchar(255),
	@fileExtensionFilter varchar(10) = null
as

set nocount on

-- Declare and initialize local variables
declare @dosCommand varchar(5000)
set @dosCommand = ''

-- If the file extension fileter was empty, set it to all files
if @fileExtensionFilter is null or ltrim(rtrim(@fileExtensionFilter)) = ''
	set @fileExtensionFilter = '*.*'

-- If the directory path does not have an ending '\', append one
if substring(@directoryPath, len(@directoryPath), 1) &amp;lt;&amp;gt; '\'
	set @directoryPath = @directoryPath + '\'

-- Build the dos command to get a list of files
select @dosCommand =
	'insert into #tempFileList(fileListRow) ' +
	'exec master.dbo.xp_cmdshell ''dir ' + @directoryPath + + @fileExtensionFilter + ''''

-- Create a temporary table to store the file list
create table #tempFileList (
	fileListRow varchar(1000) null
)

-- Create the #fileList temporary table to store the file list
create table #fileList (
	fileID int primary key identity(1,1) not null,
	[fileName] varchar(255) not null,
	lastModifiedOn datetime not null,
	fileSize bigint not null,
)

exec(@dosCommand)

-- 8 - Delete unneeded data from the #OriginalFileList
delete from #tempFileList
where fileListRow is null

delete from #tempFileList
where fileListRow like '%Volume%'

delete from #tempFileList
where fileListRow like '%Directory%'

delete from #tempFileList
where fileListRow like '%&amp;lt;DIR&amp;gt;%'

delete from #tempFileList
where fileListRow like '%bytes%'

if not exists (select * from #tempFileList where fileListRow like '%access is denied%')
begin
	-- Populate the #fileList table with the final data
	insert into #fileList(lastModifiedOn, fileSize, [fileName])
	select	ltrim(substring(fileListRow, 1, 10))
		+
		' '
		+
		rtrim(ltrim(substring(fileListRow, 11, 15)))
		+
		'm'
		as 'lastModifiedOn',
		replace(ltrim(substring(fileListRow, 21, 18)), ',', '') as 'fileSize',
		ltrim(substring(fileListRow, 40, 1000)) as 'fileName'
	from	#tempFileList

	select * from #fileList
end
else
	select fileListRow as errorMessage from [#tempFileList] as e

-- Drop the temporary tables
drop table #tempFileList
drop table #fileList

set nocount off
go&lt;/pre&gt;

&lt;h3&gt;Download&lt;/h3&gt;

&lt;p&gt;You can download the stored procedure from &lt;a title="http://tech-cats.net/blog/downloads/sql/getDirectoryFileList.txt" href="http://tech-cats.net/blog/downloads/sql/getDirectoryFileList.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/getDirectoryFileList.txt&lt;/a&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;References&lt;/strong&gt; &lt;/h3&gt;

&lt;p&gt;&lt;a title="Accessing the Windows File System from SQL Server" href="http://www.mssqltips.com/tip.asp?tip=1263" target="_blank"&gt;Accessing the Windows File System from SQL Server&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3928590161888303243?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3928590161888303243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3928590161888303243' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3928590161888303243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3928590161888303243'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/querying-file-system-from-coldfusion-to.html' title='Querying the File System - From ColdFusion to SQL Server'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3762210943246292449</id><published>2008-03-11T15:46:00.001-04:00</published><updated>2008-03-11T16:00:06.268-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Object Oriented Programming with Prototype.js</title><content type='html'>&lt;p&gt;Object oriented programming has been around for quite some time and was made popular by C++ back in the day. Nowadays, even web scripting languages support the paradigm. JavaScript does not have true OO but allows you to use the design pattern in your code. Today, we will dive into using object oriented programming with the popular JavaScript framework Prototype.&lt;/p&gt; &lt;p&gt;Prototype makes it easy to declare your own objects by using the "Class.create()" method:&lt;/p&gt;&lt;pre class="js" name="code"&gt;var sampleObject = Class.create();
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;Once you do that you can start writing your class specific methods and properties inside the "prototype" object:&lt;/p&gt;&lt;pre class="js" name="code"&gt;sampleObject.prototype = {
}
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;To declare private properties you simply specify the name of the property followed by a colon and the value:&lt;/p&gt;&lt;pre class="js" name="code"&gt;sampleObject.prototype = {
	linkIDs: ['mainPageLink', 'cdmScreenLink', 'adminLink', 'helpLink'],
	statusMessage: '',
	currentLinkID: 'myLink'
}
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;The important thing to remember is that each property needs to be separated from the next by a comma. As shown above, property values can be a array, a number, a string but cannot be empty value. While:&lt;/p&gt;&lt;pre class="js" name="code"&gt;currentLinkID: 'myLink',
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;is valid while&lt;/p&gt;&lt;pre class="js" name="code"&gt;currentLinkID:,
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;is not.&lt;/p&gt;
&lt;p&gt;Declaring your own functions is not any different. Before we look into functions however, there is one function that requires special attention: the "initialize" function:&lt;/p&gt;&lt;pre class="js" name="code"&gt;initialize: function() {
}
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;The initialize function is what JavaScript calls automatically when you create an instance of your object. If you are familiar with OO, this function is the constructor of your object. Any setup and initial requirements for using your object should be done in here.&lt;/p&gt;
&lt;p&gt;So to get back to regular functions, they are declared in the format functionName: function() {} as in:&lt;/p&gt;&lt;pre class="js" name="code"&gt;doSomething: function() {
}
&lt;/pre&gt;&lt;br&gt;
&lt;p&gt;So far your object should like like this:&lt;/p&gt;&lt;pre class="js" name="code"&gt;var sampleObject = Class.create();
sampleObject.prototype = {
	linkIDs: ['mainPageLink', 'cdmScreenLink', 'adminLink', 'helpLink'],
	statusMessage: '',
	currentLinkID: 'myLink',
	initialize: function() {
	},
	doSomething: function() {
	}
}
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;Big deal right, including that in your html page and/or a separate JavaScript file does not do anything for you. The next step in making it of any use is to actually create an instance of the object like so:&lt;/p&gt;&lt;pre class="js" name="code"&gt;var sampleObjectInstance = new sampleObject();
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;Creating an instance of the object automatically calls all your code inside the "initialize" function. Here, a good practice is to wrap the creation of your object inside the windows load or dom:loaded (Prototype v1.6) event like:&lt;/p&gt;&lt;pre class="js" name="code"&gt;Event.observe(window, 'load', function() {
	var sampleObjectInstance = new sampleObject();
});
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;Or&lt;/p&gt;&lt;pre class="js" name="code"&gt;document.observe("dom:loaded", function() {
	var sampleObjectInstance = new sampleObject();
});
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;To expand on using properties inside your object, whenever you want to access a property such as "currentLinkID", you have to prefix it with "this" as in:&lt;/p&gt;&lt;pre class="js" name="code"&gt;this.statusMessage = 'Who Am I?';
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;That is because inside your object's function, without "this", the code does not know about the property. The same applies to using function so you cannot simply called the "doSomething" function with:&lt;/p&gt;&lt;pre class="js" name="code"&gt;doSomething();
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;but instead if you have to use:&lt;br&gt;&lt;pre class="js" name="code"&gt;this.doSomething();&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;This can get a little more complicated when it comes to using event listeners inside your code. Let me elaborate. To tie an event observer that will call the "doSomething" function when a users clicks the link with ID 'myLink', you would usually do:&lt;/p&gt;&lt;pre class="js" name="code"&gt;$(this.currentLinkID).observe('click', this.doSomething);
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;While that will work, if you try to access any class properties (such as "statusMessage") inside the "doSomething" function, you will get "undefined" for their values. That is because, again as pointed out above, the function is not aware that it belongs to an object so it does not know that the object has properties. The remedy is simple, simply append .bind(this) to the function when it is tied to the event as in:&lt;/p&gt;&lt;pre class="js" name="code"&gt;$(this.currentLinkID).observe('click', this.doSomething.bind(this));
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;A similar approach needs to be applied when using the prototype built-in Ajax object. If you want to tie your custom functions to the "onFailure", "onComplete" or "onSuccess" functions, you need to use the "bindAsEventListener" function:&lt;/p&gt;&lt;pre class="js" name="code"&gt;onSuccess: this.showContent.bindAsEventListener(this)
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;"Bind" also needs to be used whenever you employ the "each" construct as described in &lt;a title="" href="http://ajax.dzone.com/tips/using-bind-arrays-gotcha-under" target="_blank"&gt;Gotcha with Prototype.Bind and Arrays&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Below is the full class:&lt;/p&gt;&lt;pre class="js" name="code"&gt;var sampleObject = Class.create();
sampleObject.prototype = {
	linkIDs: ['mainPageLink', 'cdmScreenLink', 'adminLink', 'helpLink'],
	statusMessage: '',
	currentLinkID: 'myLink',
	initialize: function() {
		this.statusMessage = 'Who Am I?';

		$(this.currentLinkID).observe('click', this.doSomething.bind(this));
	},
	doSomething: function() {
		alert(this.statusMessage);

		new Ajax.Request(
			$(this.currentLinkID).href,
			{
			method: 'get',
			onSuccess: this.processContent.bindAsEventListener(this),
			evalScripts: true
			}
		);
	},
	processContent: function(request) {
	}
}

Event.observe(window, 'load', function() {
	var sampleObjectInstance = new sampleObject();
});
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;To call the functions of the sampleObject from outside you would simply do:&lt;/p&gt;&lt;pre class="js" name="code"&gt;sampleObjectInstance.doSomething();
&lt;/pre&gt;
&lt;p&gt;While you can access it's properties with the syntax:&lt;/p&gt;&lt;pre class="js" name="code"&gt;alert(sampleObjectInstance.statusMessage);
&lt;/pre&gt;&lt;br&gt;
&lt;p&gt;That concludes the basic guide to using object oriented programming with Prototype. Did I miss anything to get you started?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3762210943246292449?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3762210943246292449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3762210943246292449' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3762210943246292449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3762210943246292449'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/object-oriented-programming-with.html' title='Object Oriented Programming with Prototype.js'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3741527017700736921</id><published>2008-03-06T18:53:00.003-05:00</published><updated>2009-04-17T12:12:54.673-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>How to Extract Video Still Frames with MPlayer</title><content type='html'>&lt;p&gt;While working on a video content management system, I was in need of capturing frames from video files so they can be used as a preview for video. The system already had some code in place but it only worked for video encoding in Windows Media format (.wmv extension). That would not do, I thought, not in this day and age when we have so many file formats and video codecs. So I need to able to:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Capture video frames from within .NET code  &lt;li&gt;Capture images from all kinds of different video formats  &lt;li&gt;Not reinvent the wheel while satisfying #1 and #2&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Enter MPlayer&lt;/h3&gt; &lt;p&gt;Stolen directly from the &lt;a title="" href="http://www.mplayerhq.hu/design7/info.html" target="_blank"&gt;Information&lt;/a&gt; page of MPlayer, "MPlayer is a movie player which runs on many systems (see the documentation). It plays most MPEG/VOB, AVI, Ogg/OGM, VIVO, ASF/WMA/WMV, QT/MOV/MP4, RealMedia, Matroska, &lt;a href="http://www.nut-container.org"&gt;NUT&lt;/a&gt;, NuppelVideo, FLI, YUV4MPEG, FILM, RoQ, PVA files, supported by many native, XAnim, and Win32 DLL codecs. You can watch VideoCD, SVCD, DVD, 3ivx, DivX 3/4/5 and even WMV movies..". To add my own description, MPlayer is an open source command line video player.&lt;/p&gt; &lt;h3&gt;So What&lt;/h3&gt; &lt;p&gt;Metallica has an old song called "So What", great tune for the metal heads in all of us. The answer is simple, MPlayer can do a lot more than play video. It can capture images, stream video over http and even transcode video from one format to another (but the last feature is grounds for another article).&lt;/p&gt; &lt;h3&gt;Putting It Together&lt;/h3&gt; &lt;p&gt;You will need:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;1 download of MPlayer Windows executable from &lt;a title="" href="http://www.mplayerhq.hu/design7/dload.html" target="_blank"&gt;http://www.mplayerhq.hu/design7/dload.html&lt;/a&gt;  &lt;li&gt;1 download of the MPlayer Windows binary codecs package from &lt;a title="" href="http://www.mplayerhq.hu/design7/dload.html" target="_blank"&gt;http://www.mplayerhq.hu/design7/dload.html&lt;/a&gt;  &lt;li&gt;1 MPlayer .NET wrapper provided in this article&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Setup&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Extract the mPlayer executable (mplayer.exe)  &lt;li&gt;Extract the mPlayer codecs in a directory called "codecs" in the same directory as the mPlayer executable  &lt;li&gt;Add a reference to the mPlayerWrapper project or compiled DLL&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Usage&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Capture with default arguments&lt;br&gt;&lt;br&gt;in C# &lt;br&gt;&lt;pre class="csharp" name="code"&gt;// Specify the path to the video file
string videoFilePath = @"drive letter:\path\to\myVideo.mpg";
// Declare the mplayer instance with the mplayer executable residing in the
// same directory as your executable
mPlayerWrapper mPlayerInstance = new mPlayerWrapper();
// Capture frames
mPlayerInstance.captureFrames(videoFilePath);
&lt;/pre&gt;&lt;br&gt;in VB.NET &lt;br&gt;&lt;pre class="vb" name="code"&gt;' Specify the path to the video file
dim videoFilePath As String = "drive letter:\path\to\myVideo.mpg"
' Declare the mplayer instance with the mplayer executable residing in the
' same directory as your executable
dim mPlayerInstance As new mPlayerWrapper()
' Capture frames
mPlayerInstance.captureFrames(videoFilePath)
&lt;/pre&gt;&lt;br&gt;This will capture 12 frames with 5 second interval between each frame and put them in the same directory as your video file. The filename of each frame will be "myVideo_thumb01.jpg" to "myVideo_thumb12.jpg". Each frame will be scaled to 270x200.&lt;br&gt;
&lt;li&gt;Capture arguments 
&lt;ul&gt;
&lt;li&gt;mPlayerPath - sets the path where the mPlayer executable (mplayer.exe) is located. The default is in the same directory as your code is executing. 
&lt;li&gt;currentFilePath - sets the file path to the video file you are using 
&lt;li&gt;cleanOutputDirectory - deletes all the "jpg" images in the capture output directory before capturing 
&lt;li&gt;captureInterval - sets the interval at which frames will be captured. Only applicable if using a time interval capture method (as outlined below) 
&lt;li&gt;numberOfFramesToCapture - the number of frames to be captured 
&lt;li&gt;captureExactNumberOfFrames - tells the wrapper to attempt to capture the exact number of frames as specified by the "numberOfFramesToCapture" property. This can be used if a file has too few frames but you still want to capture an exact number 
&lt;li&gt;useTimeSeekToCapture - used to set the wrapper method of capture to seeking through the file instead of capturing a frame at an interval 
&lt;li&gt;thumbnailPrefix - the prefix to be used when creating the filenames for captured frames. The default is the name of the video with "_thumb" append to it as in "myVideo_thumb01.jpg" 
&lt;li&gt;capturedFrameWidthHeight - the width:height that each frame will be scaled to. The default is 270:200 
&lt;li&gt;scaleCapturedFrames - used in conjunction with the "capturedFrameWidthHeight" property to scale down the captured frames. Set to true by default&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Capture in a different output directory &lt;br&gt;in C# &lt;br&gt;&lt;pre class="csharp" name="code"&gt;// Specify the path to the video file
string videoFilePath = @"drive letter:\path\to\myVideo.mpg";
// Specify the output directory
string outputPath = @"drive letter:\path\to\output directory";
// Declare the mplayer instance with the mplayer executable residing in the
// same directory as your executable
mPlayerWrapper mPlayerInstance = new mPlayerWrapper();
// Capture frames
mPlayerInstance.captureFrames(videoFilePath, outputPath);
&lt;/pre&gt;&lt;br&gt;in VB.NET &lt;br&gt;&lt;pre class="vb" name="code"&gt;' Specify the path to the video file
dim videoFilePath As String = "drive letter:\path\to\myVideo.mpg"
' Specify the output directory
dim outputPath As String = @"drive letter:\path\to\output directory"
' Declare the mplayer instance with the mplayer executable residing in the
' same directory as your executable
dim mPlayerInstance As new mPlayerWrapper()
' Capture frames
mPlayerInstance.captureFrames(videoFilePath, outputDirectory)
&lt;/pre&gt;
&lt;li&gt;Using distinct capture methods: 
&lt;ol&gt;
&lt;li&gt;captureFramesWithInterval - by default captures a frame every 5 seconds with up to 12 frames 
&lt;li&gt;captureFramesWithTimeSeek - by default captures 1 frame each second with up to 12 frames by seeking through the file&lt;/li&gt;&lt;/ol&gt;
&lt;li&gt;&lt;strong&gt;Bonus&lt;/strong&gt; 
&lt;ul&gt;
&lt;li&gt;getFileProperties - returns a SortedList of video and audio properties for the file 
&lt;li&gt;getAudioProperties - returns a SortedList of audio properties for the file 
&lt;li&gt;getVideoProperties - returns a SortedList of video properties for the file&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Downloads&lt;/h3&gt;
&lt;p&gt;mPlayerWrapper: &lt;a href="http://blog.tech-cats.net/examples/dotnet/mPlayerWrapper.dll"&gt;http://blog.tech-cats.net/examples/dotnet/mPlayerWrapper.dll&lt;/a&gt;&lt;br&gt;mPlayerWrapper Source: &lt;a href="http://blog.tech-cats.net/examples/dotnet/mplayerWrapper-v0.2.zip"&gt;http://blog.tech-cats.net/examples/dotnet/mplayerWrapper-v0.2.zip&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3741527017700736921?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3741527017700736921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3741527017700736921' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3741527017700736921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3741527017700736921'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/how-to-extract-video-still-frames-with.html' title='How to Extract Video Still Frames with MPlayer'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7938206452972223154</id><published>2008-03-04T09:19:00.001-05:00</published><updated>2008-03-04T09:42:41.926-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><title type='text'>Top 13 Visual Studio Keyboard Shortcuts</title><content type='html'>&lt;p&gt;My friends in college always made fun of my keyboard obsession. At the time, I knew all the Windows 98 specific shortcut keys and often had no need for the mouse. Keyboard shortcuts still rule in my book. It is amazing that you can get around without using a mouse at all. Master the following Visual Studio shortcuts and your colleagues might stare at you with amazement.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;F5: &lt;/strong&gt;Start your project in debug mode&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber1.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="146" alt="vsShortcutsNumber1" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber1_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;F7 &amp;amp; Shift-F7: &lt;/strong&gt;Show the code windows &amp;amp; Show the designer window&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="154" alt="vsShortcutsNumber2" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber2_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;Alt-Enter: &lt;/strong&gt;Show the properties panel for a selected object (this is general Windows shortcut that can be used on files and directories)&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber3.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="205" alt="vsShortcutsNumber3" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber3_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;F6 / Shift-F6 / Ctrl-Shift-B: &lt;/strong&gt;Build solution / Build project / Build solution&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber4.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="147" alt="vsShortcutsNumber4" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber4_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt; &lt;li&gt;&lt;strong&gt;Shift-Alt-C:&lt;/strong&gt; Add a new class to your project&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber12.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="vsShortcutsNumber12" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber12_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt; &lt;li&gt;&lt;strong&gt;Ctrl-K + &lt;strong&gt;Ctrl&lt;/strong&gt;-C: &lt;/strong&gt;Comment a selected block of code&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber5.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="88" alt="vsShortcutsNumber5" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber5_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-K + &lt;strong&gt;Ctrl&lt;/strong&gt;-U:&lt;/strong&gt; Un-comment a selected block of code&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber6.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="79" alt="vsShortcutsNumber6" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber6_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-M + &lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-O / &lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-M + &lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-P:&lt;/strong&gt; Collapse all code to definitions / Expand all code (stop collapsing)&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber7.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="100" alt="vsShortcutsNumber7" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber7_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-M + &lt;strong&gt;Ctrl&lt;/strong&gt;+M: &lt;/strong&gt;Expend or collapse a selected code fragment. The code collapsed depends on where the cursor is located&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber8.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="83" alt="vsShortcutsNumber8" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber8_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-B + &lt;strong&gt;Ctrl&lt;/strong&gt;-T: &lt;/strong&gt;Toggle code bookmark&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber9.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="83" alt="vsShortcutsNumber9" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber9_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-Alt-P:&lt;/strong&gt; Attach the debugger to a process. This is insanely useful for debugging ASP.NET web sites without having to start the project in debug mode&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber10.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="181" alt="vsShortcutsNumber10" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber10_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-Alt-L: &lt;/strong&gt;Show the solution explorer&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber11.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="vsShortcutsNumber11" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber11_thumb.jpg" width="161" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt; &lt;li&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;-Shift-A / Alt-Shift-A:&lt;/strong&gt; Add a new item to your project / add an existing item to your project&lt;br&gt;&lt;br&gt;&lt;a href="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber13.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="vsShortcutsNumber13" src="http://tech-cats.net/blog/images/EssentialVisualStudioShortcuts_B69E/vsShortcutsNumber13_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; &lt;br&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;The above list is my top 13. Did I miss any essential ones? What are yours?&lt;/p&gt; &lt;h3&gt;&lt;u&gt;Bonus:&lt;/u&gt;&lt;/h3&gt; &lt;p&gt;The following work in Visual Studio just like they do in most other Windows application.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-N:&lt;/strong&gt; Add a new file&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-S:&lt;/strong&gt; Save file&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-Z / &lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-Y:&lt;/strong&gt; Undo typing / Redo typing&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-F:&lt;/strong&gt; Bring up the "Find" dialog&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-H:&lt;/strong&gt; Bring up the "Replace" dialog&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-Tab: &lt;/strong&gt;Scroll forward through open windows&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;Ctrl&lt;/strong&gt;&lt;/strong&gt;-Shift-Tab:&lt;/strong&gt; Scroll backwards through open windows&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7938206452972223154?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7938206452972223154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7938206452972223154' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7938206452972223154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7938206452972223154'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/top-13-visual-studio-keyboard-shortcuts.html' title='Top 13 Visual Studio Keyboard Shortcuts'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6598560343120490244</id><published>2008-03-03T11:06:00.001-05:00</published><updated>2008-03-03T11:10:53.593-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Creating a Gmail Like Ajax Status Display</title><content type='html'>&lt;p&gt;Most of us geeks know and love Gmail. It has a very nice interface and it is an inspiration to constantly improve our own web applications. Today, I set out to create an unobtrusive Gmail like page status message, much like the one shown in the screen shot:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="105" alt="gmail_screnshot" src="http://boyan.tech-cats.com/images/blog/CreatingaGmailLikeAjaxStatus_B90D/gmail_screnshot.jpg" width="644" border="0"&gt; &lt;/p&gt; &lt;p&gt;My requirements were simple:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Should look like the one used in Gmail  &lt;li&gt;Should be able to just include the source JavaScript file without any further configuration  &lt;li&gt;Should allow the user to specify a custom status message to be displayed  &lt;li&gt;Should allow for the use of custom styles but none are required  &lt;li&gt;Integrates with Prototype.js Ajax requests&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;The only prerequisite is Prototype.js v1.6&lt;/p&gt; &lt;p&gt;Let's get started. If all you care about is the end result. Here how to include it in your page:&lt;/p&gt;&lt;pre class="js" name="code"&gt;&amp;lt;script type="text/javascript" src="prototype.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="ajaxStatusDisplay.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;That's it! Now whenever you make an Ajax request with Prototype, you will see a message popup with the text "Loading...". You can check out the end results at &lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Simple.html" target="_blank"&gt;http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Simple.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now to the advanced features.&lt;/p&gt;
&lt;p&gt;As stated #3 and #4 above, two of our requirements are to allow the user to specify a custom status message and custom CSS styles for the displayed message. Satisfying the first one of those requirements is done by having the user create an element on the page with the custom message like so:&lt;/p&gt;&lt;pre class="xml" name="code"&gt;&amp;lt;div id="ajaxStatusDisplay_userMessage"&amp;gt;
Loading...Wait a Minute!
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;This element does not have to be a div. It could be a any text container such as span or even input (text or hidden). What is important is the id of the element, it has to be set to "ajaxStatusDisplay_userMessage" for the custom message to be picked up.&lt;/p&gt;
&lt;p&gt;The next requirement works much in the same way. Custom styles can be specified by creating two CSS classes with certain names: "ajaxStatusDisplay_userStyle" and "ajaxStatusDisplay_userMessageStyle". Here an example that will produce the default look:&lt;/p&gt;&lt;pre class="css" name="code"&gt;&amp;lt;style type="text/css"&amp;gt;
.ajaxStatusDisplay_userStyle {position:absolute;left:45%;top:2px;height:10px;}
.ajaxStatusDisplay_userMessageStyle {
	background:#FFF1A8 none repeat scroll 0%;color:#000;padding: 0pt 5px;
	font-family:Arial, Helvetica, sans-serif;font-size:14px;font-weight: bold;
	text-align:center;width:100%
}
&amp;lt;/style&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And here is another example that will produce a white text on black background in the top right corner:&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre class="css" name="code"&gt;&amp;lt;style type="text/css"&amp;gt;
.ajaxStatusDisplay_userStyle {position:absolute;left:94%;top:0px;height:10px;}
.ajaxStatusDisplay_userMessageStyle {
	background-color:#000;
	color:#fff;
	font-family:Arial, Helvetica, sans-serif;
	padding:2px;
	width:100%;
}
&amp;lt;/style&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;To use the your own CSS styles,&lt;/strong&gt; you &lt;strong&gt;do not need to do anything&lt;/strong&gt; but define them as shown above (as compared to the initial version where you needed to edit the file "ajaxStatusDisplay.js" and set the "useUserCssStyles" variable to "true").&lt;/p&gt;
&lt;p&gt;A small extra feature is the ability to change the status message at runtime. This is done by using (you guessed it), the "setStatusMessage" function as follows:&lt;/p&gt;&lt;pre class="js" name="code"&gt;// Set the status message based on the value in the "userMessage" input field
ajaxStatusDisplay.setStatusMessage($F('userMessage'));
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;To see setting the status message in action along with using a custom CSS style, check out &lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Advanced.html" target="_blank"&gt;http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Advanced.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can view all the sources at:&lt;/p&gt;
&lt;p&gt;JavaScript Source: &lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay.txt" target="_blank"&gt;ajaxStatusDisplay.txt&lt;/a&gt;&lt;br&gt;Simple Example Source: &lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Simple.txt" target="_blank"&gt;ajaxStatusDisplay-Simple.txt&lt;/a&gt;&lt;br&gt;Advanced Example Source: &lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay-Advanced.txt" target="_blank"&gt;ajaxStatusDisplay-Advanced.txt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can download the JavaScript source at:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay.js" target="_blank"&gt;http://blog.tech-cats.net/examples/ajax/ajaxStatusDisplay.js&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6598560343120490244?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6598560343120490244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6598560343120490244' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6598560343120490244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6598560343120490244'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/03/creating-gmail-like-ajax-status-display.html' title='Creating a Gmail Like Ajax Status Display'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1199221244270385538</id><published>2008-02-27T13:33:00.001-05:00</published><updated>2008-02-27T13:33:03.824-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>12 Essential Free Tools for .NET Developers</title><content type='html'>&lt;p&gt;Over my course of .NET development, I have compiled a list of essential free tools for .NET applications. This is not a the alpha or the omega of tools, just a short list that I feel is essential. &lt;/p&gt;&lt;!--break--&gt; &lt;ol&gt; &lt;li&gt; &lt;h3&gt;SharpDevelop&lt;/h3&gt;&lt;a href="http://www.icsharpcode.net/OpenSource/SD/Download" target="_blank"&gt;http://www.icsharpcode.net/OpenSource/SD/Download&lt;/a&gt;&lt;br&gt;An open source IDE for .NET. Check out the full &lt;a href="http://community.sharpdevelop.net/blogs/mattward/articles/FeatureTour.aspx" target="_blank"&gt;feature tour&lt;/a&gt;.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="360" src="http://dotnet.dzone.com/sites/all/files/images/sharpDevelop.img_assist_custom.png" width="500"&gt;  &lt;li&gt; &lt;h3&gt;Visual Web Developer Express Edition&lt;/h3&gt;&lt;a id="sqs9" title="http://www.microsoft.com/express/vwd" href="http://www.microsoft.com/express/vwd" target="_blank"&gt;http://www.microsoft.com/express/vwd&lt;/a&gt;&lt;br&gt;Stripped down version of Visual Studio that allows you to write .NET web applications.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="429" src="http://dotnet.dzone.com/sites/all/files/images/visualWebDeveloper.img_assist_custom.png" width="500"&gt;  &lt;li&gt; &lt;h3&gt;TortoiseSVN&lt;/h3&gt;&lt;a id="maik" title="http://tortoisesvn.net/downloads" href="http://tortoisesvn.net/downloads" target="_blank"&gt;http://tortoisesvn.net/downloads&lt;/a&gt;&lt;br&gt;There is no better Subversion client for Windows. You need this if you are going to use VisualSVN with Visual Studio.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="377" src="http://dotnet.dzone.com/sites/all/files/images/tortoiseSVN.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;NAnt&lt;/h3&gt;&lt;a id="v7xq" title="http://nant.sourceforge.net" href="http://nant.sourceforge.net" target="_blank"&gt;http://nant.sourceforge.net&lt;/a&gt;&lt;br&gt;.NET based automation tool that has many built in tasks but could be extended with custom code written in any .NET language.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="249" src="http://dotnet.dzone.com/sites/all/files/images/nant.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;Snippet Compiler&lt;/h3&gt;&lt;a href="http://www.sliver.com/dotnet/SnippetCompiler"&gt;http://www.sliver.com/dotnet/SnippetCompiler&lt;/a&gt;&lt;br&gt;Snippet compiler is a small tool to write and execute small chunks of .NET code without creating a Visual Studio project.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="535" src="http://dotnet.dzone.com/sites/all/files/images/snippetCompiler.img_assist_custom.png" width="500"&gt;  &lt;li&gt; &lt;h3&gt;.NET Reflector&lt;/h3&gt;&lt;a id="a:c9" title="http://www.aisto.com/roeder/dotnet" href="http://www.aisto.com/roeder/dotnet" target="_blank"&gt;http://www.aisto.com/roeder/dotnet&lt;/a&gt;&lt;br&gt;Reflector is the class browser, explorer, analyzer and documentation viewer for .NET. Reflector allows to easily view, navigate, search, decompile and analyze .NET assemblies in C#, Visual Basic and IL. &lt;br&gt;&lt;img class="image image-img_assist_custom" height="377" src="http://dotnet.dzone.com/sites/all/files/images/netReflector.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;Microsoft SQL Server Management Studio Express&lt;/h3&gt;&lt;a id="wr-8" title="http://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&amp;amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&amp;amp;displaylang=en" target="_blank"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&amp;amp;displaylang=en&lt;/a&gt;&lt;br&gt;Tool for database administration and development from Microsoft&lt;br&gt;&lt;img class="image image-img_assist_custom" height="377" src="http://dotnet.dzone.com/sites/all/files/images/sqlServerManagementStudio.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;Quest Comparison Suite for SQL Server&lt;/h3&gt;&lt;a id="gm:y" title="http://www.quest.com/Comparison-Suite-for-SQL-Server" href="http://www.quest.com/Comparison-Suite-for-SQL-Server" target="_blank"&gt;http://www.quest.com/Comparison-Suite-for-SQL-Server&lt;/a&gt;&lt;br&gt;Compare and synchronize database schema and data&lt;br&gt;&lt;img class="image image-img_assist_custom" height="375" src="http://dotnet.dzone.com/sites/all/files/images/questComparisonSuiteSQLServer.img_assist_custom.png" width="500"&gt;  &lt;li&gt; &lt;h3&gt;XYPlorer&lt;/h3&gt;&lt;a id="r2ti" title="http://www.xyplorer.com" href="http://www.xyplorer.com" target="_blank"&gt;http://www.xyplorer.com&lt;/a&gt;&lt;br&gt;Awesome file manager. The older version is completely free.&lt;br&gt;&lt;img class="image image-img_assist_custom" height="377" src="http://dotnet.dzone.com/sites/all/files/images/xyplorer.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;Convert C# to VB.NET&lt;/h3&gt;&lt;a id="scga" title="http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx" href="http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx" target="_blank"&gt;http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx&lt;/a&gt;&lt;br&gt;&lt;img class="image image-img_assist_custom" height="305" src="http://dotnet.dzone.com/sites/all/files/images/convertCSharpToVB.img_assist_custom.png" width="499"&gt;  &lt;li&gt; &lt;h3&gt;NAnt Add-In&lt;/h3&gt;&lt;a id="lb3t" title="http://www.netlogics.ch/devcenter/display/NLC/NAntAddin" href="http://www.netlogics.ch/devcenter/display/NLC/NAntAddin" target="_blank"&gt;http://www.netlogics.ch/devcenter/display/NLC/NAntAddin&lt;/a&gt;&lt;br&gt;Visual Studio add-in for NAnt integration&lt;br&gt;&lt;img class="image image-_original" height="646" src="http://dotnet.dzone.com/sites/all/files/images/nantAddin.png" width="325"&gt;  &lt;li&gt; &lt;h3&gt;NUnit Add-In&lt;/h3&gt;&lt;a id="ovlg" title="http://www.netlogics.ch/devcenter/display/NLC/NUnitAddin" href="http://www.netlogics.ch/devcenter/display/NLC/NUnitAddin" target="_blank"&gt;http://www.netlogics.ch/devcenter/display/NLC/NUnitAddin&lt;/a&gt;&lt;br&gt;Visual Studio add-in for NUnit integration&lt;br&gt;&lt;img class="image image-_original" height="640" src="http://dotnet.dzone.com/sites/all/files/images/nUnitAddin.png" width="434"&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;More Visual Studio add-ins can be found at &lt;a id="bptj" title="15+ Free Visual Studio Add-Ins" href="http://www.carlj.ca/2007/09/25/15-free-visual-studio-add-ins" target="_blank"&gt;15+ Free Visual Studio Add-Ins&lt;/a&gt; and &lt;a id="ajfd" title="15+ FREE Visual Studio Add-ins - Part 2" href="http://www.carlj.ca/2007/11/28/15-free-visual-studio-add-ins-part-2" target="_blank"&gt;15+ FREE Visual Studio Add-ins - Part 2&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1199221244270385538?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1199221244270385538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1199221244270385538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1199221244270385538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1199221244270385538'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/12-essential-free-tools-for-net.html' title='12 Essential Free Tools for .NET Developers'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4350269547656322001</id><published>2008-02-21T11:23:00.002-05:00</published><updated>2008-08-06T15:34:56.802-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>Tools for Authoring NAnt Build Files</title><content type='html'>&lt;p&gt;NAnt is a great tool for automating many computer tasks. For a quick introduction, check my previous articles &lt;a title="Automating Your Computer Tasks with NAnt" href="http://dotnet.dzone.com/news/getting-started-nant-automatio"&gt;Automating Your Computer Tasks with NAnt&lt;/a&gt; and &lt;a title="Use NAnt and WinRar to Create a Self Extracting Archive" href="http://dotnet.dzone.com/news/use-nant-and-winrar-create-sel"&gt;Use NAnt and WinRar to Create a Self Extracting Archive&lt;/a&gt;. Authoring NAnt build files can be difficult without a good editor and editing XML is not my favorite thing to do anyway. Having to know all the tags and parameters for each NAnt task, makes it even less desirable. Looking at the current options, you can find several tools for authoring NAnt build files:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;NAntPad - Commercial -&amp;nbsp; &lt;a title="" href="http://nantpad.com" target="_blank"&gt;http://nantpad.com&lt;/a&gt;  &lt;li&gt;NAntBuilder - Commercial - &lt;a href="http://www.nantbuilder.com"&gt;http://www.nantbuilder.com&lt;/a&gt;  &lt;li&gt;Editor4NAnt - Free - &lt;a title="" href="http://www.download.com/Editor4NAnt/3000-2352_4-10531916.html" target="_blank"&gt;http://www.download.com/Editor4NAnt/3000-2352_4-10531916.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;While the tools above will do the job, it would be nice if you could edit your build files in Visual Studio and have at least the basic intellisense that the IDE provides. It turns out that editing NAnt build files with VS and having code insight is a pretty easy thing to setup. Here is how it is done:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Install the NAnt schema by copying the file "nant.xsd" form the NAnt distribution to "C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas". Update: for VS 2008, the directory is "C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas" &lt;li&gt;Associate NAnt build files (.build) with the Visual Studio XML editor. This can be done in one of two ways:  &lt;ul&gt; &lt;li&gt;Create a registry merge file with the following contents and merge it in your registry:&lt;br&gt;&lt;pre name="code"&gt;Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Editors\{412B8852-4F21-413B-9B47-0C9751D3EBFB}\Extensions]
"build"=dword:00000029
&lt;/pre&gt;
&lt;li&gt;Make the association through Visual Studio: 
&lt;ul&gt;
&lt;li&gt;Open any Visual Studio solution 
&lt;li&gt;Add a NAnt build file to it 
&lt;li&gt;Right click on the .build file and choose "Open With" 
&lt;li&gt;Select "XML Editor" and click on "Set as Default"&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Almost there. The last thing is to add the "xmlns" (namespace) attribute to the "project" tag of your build file. If you have copied the NAnt schema file (nant.xsd) to the right place, adding the "xmlns" attribute should list the NAnt schema as one of the available choices. The end result should look like:&lt;br&gt;&lt;pre class="xml" name="code"&gt;&amp;lt;project
 name="testProject"
 default="buildSetup"
 basedir="."
 xmlns="http://nant.sf.net/release/0.85/nant.xsd"
&amp;gt;
&lt;/pre&gt;
&lt;li&gt;And Voila! Start typing some XML and you should see a list of NAnt tasks and attributes.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4350269547656322001?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4350269547656322001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4350269547656322001' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4350269547656322001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4350269547656322001'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/tools-for-authoring-nant-build-files.html' title='Tools for Authoring NAnt Build Files'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2229551138409677202</id><published>2008-02-19T14:48:00.002-05:00</published><updated>2008-02-19T14:51:30.170-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Microsoft Giving Away Development Software to Students</title><content type='html'>&lt;p&gt;Dreamspark is the name of the Microsoft initiative to give students free developer tools so &amp;quot;you can chase your dreams and create the next big breakthrough in technology - or just get a head start on your career.&amp;quot;&lt;br /&gt;&lt;br /&gt;As of right now, this program is only avaiable to students from the US, UK, Canada, China, Germany, France, Finaldn, Spain, Sweeden, Switzerland and Belguim.&lt;br /&gt;&lt;br /&gt;So if you are a student in one of those countries, it's your lucky day.&lt;br /&gt;&lt;br /&gt;To get started, go to &lt;a href="https://downloads.channel8.msdn.com/"&gt;https://downloads.channel8.msdn.com/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2229551138409677202?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2229551138409677202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2229551138409677202' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2229551138409677202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2229551138409677202'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/microsoft-giving-away-development.html' title='Microsoft Giving Away Development Software to Students'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1194075082303519818</id><published>2008-02-19T14:14:00.005-05:00</published><updated>2008-02-19T14:36:00.385-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tracking'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Universal Package Tracking in ColdFusion</title><content type='html'>A while back, I was in need of a universal package tracking tool that is not specific to the carrier. Almost every carrier provides some kind of an API but it can be a pain to set up each one separately. Fortunately, I found a nifty tracking tool which is universal and can be leveraged through RSS. It works with UPS, FedEx, USPS, or DHL/AirBorne without having to specify which carrier you need. Instead, it determines the carrier from the tracking number.
&lt;br /&gt;&lt;br /&gt;
You can check it out at &lt;a href="http://isnoop.net/tracking/"&gt;http://isnoop.net/tracking&lt;/a&gt;
and the some details can be found at &lt;a href="http://isnoop.net/blog/?p=19"&gt;http://isnoop.net/blog/?p=19&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
While this might not be good commercial solution, it is still usable for personal or a small site. The code below shows how to leverage this with ColdFusion. The Ajax/JavaScript implementation relies on &lt;a href="http://www.prototypejs.org" target="_blank"&gt;Prototype.js&lt;/a&gt;. You can see it in action at &lt;a href="http://blog.tech-cats.net/examples/universalPackageTracking.cfm" target="_blank"&gt;http://blog.tech-cats.net/examples/universalPackageTracking.cfm&lt;/a&gt; and download it from &lt;a href="http://blog.tech-cats.net/examples/universalPackageTracking.txt"&gt;http://blog.tech-cats.net/examples/universalPackageTracking.txt&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
The code is well documented and should be easy to read/understand:
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;pre name="code" class="cf"&gt;
&amp;lt;cfsetting enablecfoutputonly="yes"&amp;gt;
&amp;lt;!--- Setup default parameters and constants ---&amp;gt;

&amp;lt;!--- Is this call to the page from javascript (Ajax) ---&amp;gt;
&amp;lt;cfparam name="url.isAjaxCall" default="false" /&amp;gt;

&amp;lt;!--- The message to display while loading ---&amp;gt;
&amp;lt;cfset loadingMessage = "Loading..." /&amp;gt;

&amp;lt;!--- Default tracking number as a url variable (trackingNumber) ---&amp;gt;
&amp;lt;cfparam name="url.trackingNumber" default="" /&amp;gt;
&amp;lt;!---
 Tracking page url: very nice free tracking for all carriers that you can
 call to get an rss feed generated based on your tracking number as in
 'http://isnoop.net/tracking/index.php?t=85642012466&amp;rss=1'.

 If you call it without setting the 'rss' variable as in:
 'http://isnoop.net/tracking/index.php?t=85642012466' you can see a nice
 google map of where in route your package is.
 
 This service works for UPS, FedEx, USPS, or DHL/AirBorne without having
 to specify the carrier as it determins it from the tracking number.
 ---&amp;gt;
&amp;lt;cfparam name="trackingPageUrl" default="http://isnoop.net/tracking/index.php" /&amp;gt;

&amp;lt;!---
Function:  parseRss

Arguments:

rssData  string (The string of rss xml retrieved with cfhttp)
debugMode boolean

Return Value:
An array of structures containing the parsed rss feed. Example:
array[1]
 link - the link from the rss item
 title - the title from the rss feed
 description - the description from the rss feed

Description:
Parses the RSS feed passed in ---&amp;gt;
&amp;lt;cffunction name="parseRss" returntype="array" output="true" hint="Parses the RSS feed passed in"&amp;gt;
 &amp;lt;cfargument name="rssData" type="string" required="true"&amp;gt;
 &amp;lt;cfargument name="debugMode" type="string" required="false"&amp;gt;

 &amp;lt;!--- Set default variables ---&amp;gt;
 &amp;lt;cfset var xmlData = ""&amp;gt;
 &amp;lt;cfset var result = arrayNew(1)&amp;gt;
 &amp;lt;cfset var x = ""&amp;gt;
 &amp;lt;cfset var items = ""&amp;gt;
 &amp;lt;cfset var xPath = ""&amp;gt;
 &amp;lt;cfset var node = ""&amp;gt;

 &amp;lt;cftry&amp;gt;
  &amp;lt;!--- Parse the data as xml ---&amp;gt;
  &amp;lt;cfset xmlData = xmlParse(arguments.rssData)&amp;gt;

  &amp;lt;!--- Create xpath search string based on the xml root name ---&amp;gt;
  &amp;lt;cfif xmlData.xmlRoot.xmlName is "rss"&amp;gt;
   &amp;lt;cfset xPath = "//item"&amp;gt;
  &amp;lt;cfelse&amp;gt;
   &amp;lt;cfset xPath = "//:item"&amp;gt;
  &amp;lt;/cfif&amp;gt;

  &amp;lt;!--- Get all the xml nodes matching the xpath search string ---&amp;gt;
  &amp;lt;cfset items = xmlSearch(xmlData, xPath)&amp;gt;

  &amp;lt;!--- Loop through the found xml nodes and build an array of structures ---&amp;gt;
  &amp;lt;cfloop index="i" from="1" to="#arrayLen(items)#"&amp;gt;
   &amp;lt;cfset node = structNew()&amp;gt;
   &amp;lt;cfset node.link = items[i].link.xmlText&amp;gt;
   &amp;lt;cfset node.title = items[i].title.xmlText&amp;gt;
   &amp;lt;cfset node.description = items[i].description.xmlText&amp;gt;

   &amp;lt;cfset result[arrayLen(result) + 1] = duplicate(node)&amp;gt;
  &amp;lt;/cfloop&amp;gt;
  &amp;lt;cfcatch&amp;gt;
  &amp;lt;/cfcatch&amp;gt;
 &amp;lt;/cftry&amp;gt;

 &amp;lt;cfreturn result&amp;gt;
&amp;lt;/cffunction&amp;gt;

&amp;lt;cfoutput&amp;gt;
&amp;lt;!---
If this is an ajax call, get the tracking results trackingPageUrl specified above ---&amp;gt;
&amp;lt;cfif url.isAjaxCall and url.trackingNumber neq ''&amp;gt;
 &amp;lt;cfhttp method="get" url="#trackingPageUrl#" result="test" charset="windows-1252"&amp;gt;
  &amp;lt;!--- Set the 'rss' url variable ---&amp;gt;
  &amp;lt;cfhttpparam name="rss" type="url" value="1" /&amp;gt;
  &amp;lt;!--- Set the tracking url variable ---&amp;gt;
  &amp;lt;cfhttpparam name="t" type="url" value="#url.trackingNumber#" /&amp;gt;
 &amp;lt;/cfhttp&amp;gt;

 &amp;lt;!--- Parse the rss feed from the contents returned by cfhttp ---&amp;gt;
 &amp;lt;cfset rssFeed = parseRss(test.filecontent) /&amp;gt;

 &amp;lt;cfif arraylen(rssFeed) gt 0&amp;gt;
  &amp;lt;div id="rssItem"&amp;gt;
   &amp;lt;span id="description"&amp;gt;Tracking data for tracking number
   '&amp;lt;span id="trackingNumber"&amp;gt;#url.trackingNumber#&amp;lt;/span&amp;gt;'&amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;br /&amp;gt;
  &amp;lt;!--- Loop through the contents of the rss feed and display them ---&amp;gt;
  &amp;lt;cfloop index="i" from="1" to="#arrayLen(rssFeed)#"&amp;gt;
  &amp;lt;div id="rssItem"&amp;gt;
   &amp;lt;span id="description"&amp;gt;#rssFeed[i].description.replaceall("Package update on ", "")#&amp;lt;/span&amp;gt;
   &lt;!--- &amp;lt;span id="title"&amp;gt;&amp;lt;a href="#rssFeed[i].link#"&amp;gt;#rssFeed[i].title#&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt; ---&gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;/cfloop&amp;gt;
 &amp;lt;cfelse&amp;gt;
  &amp;lt;div id="rssItem"&amp;gt;
   &amp;lt;span id="description"&amp;gt;No tracking data found for tracking number
   '&amp;lt;span id="trackingNumber"&amp;gt;#url.trackingNumber#&amp;lt;/span&amp;gt;'&amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
 &amp;lt;/cfif&amp;gt;
&amp;lt;cfelse&amp;gt;
 &amp;lt;!--- This is not an ajax call, so display a form for the user to enter a tracking number ---&amp;gt;
 &amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
 &amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
 &amp;lt;head&amp;gt;
 &amp;lt;script type="text/javascript" src="/js/prototype.js"&amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;style type="text/css"&amp;gt;
 span##trackingNumber { font-weight: 700; }
 div##statusContainer { position:absolute;left:0px;top:0px;width:100%;height:10px; }
 div##statusMessageContainer { position:absolute;background-color:##000000;color:white;width:70px;font-family:Arial, Helvetica, sans-serif;padding:2px;left:0px; }
 &amp;lt;/style&amp;gt;
 &amp;lt;/head&amp;gt;
 &amp;lt;body&amp;gt;
 Browser Bookmarklet:
 &amp;lt;a href="javascript:(function(){var url='http://#cgi.http_host##cgi.script_name#';searchString=prompt('Enter your tracking number:','');searchString=((searchString==null)?'':searchString.replace(/^(\s+)?(.*?)(\s+)?$/gi,'$2'));var params='?isAjaxCall=true&amp;t=';if(searchString!=''){if(location.href.indexOf(url)==-1){var win=window.open(url+params+escape(searchString));}else{location.href=url+params+escape(searchString);}}})();"&amp;gt;
 Track Packages
 &amp;lt;/a&amp;gt;
 &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
 &amp;lt;form id="trackingForm" name="trackingForm" method="get" action="#cgi.script_name#" class="ajaxForm"&amp;gt;
 &amp;lt;input type="hidden" id="isAjaxCall" name="isAjaxCall" value="true" /&amp;gt;
 &amp;lt;input type="text" id="trackingNumber" name="trackingNumber" value="1Z04WF350314328154" /&amp;gt;
 &amp;lt;input type="submit" id="getTrackingResults" name="getTrackingResults" value="Track" /&amp;gt;
 &amp;lt;/form&amp;gt;
 &amp;lt;br /&amp;gt;
 &amp;lt;!-- Results container that will be updated with the results of the request ---&amp;gt;
 &amp;lt;div id="resultsContainer" class="ajaxContent"&amp;gt;&amp;lt;/div&amp;gt;
 &amp;lt;br /&amp;gt;
 &amp;lt;!-- Status container that will be display durring processing ---&amp;gt;
 &amp;lt;div id="statusContainer" style="display: none;" class="ajaxStatus"&amp;gt;
  &amp;lt;div id="statusMessageContainer"&amp;gt;Loading...&amp;lt;/div&amp;gt;
 &amp;lt;/div&amp;gt;
 &amp;lt;script language="javascript" type="text/javascript"&amp;gt;
 var trackingForm = Class.create();
 trackingForm.prototype = {
  ajaxContainerElement: 'div',
  formID: '',
  ajaxUrl: '',
  resultsContainer: '',
  /*
  Function: initialize
  Description: Performs various intiliazion tasks for the form
  */
  initialize: function() {
   var ajaxFormsList = $$('form.ajaxForm');
   var ajaxContainersList = $$(this.ajaxContainerElement + '.ajaxContent');

   if (ajaxFormsList.length &gt; 0 &amp;&amp; ajaxContainersList.length &gt; 0) {
    this.formID = ajaxFormsList[0].id;
    this.ajaxUrl = $(this.formID).action;
    this.resultsContainer = ajaxContainersList[0].id;

    // Tie the submit event to the submitForm function
    $(this.formID).observe('submit', this.submitForm.bind(this));

    // Reset the form
    $(this.formID).reset();

    // Activate the first element on the form
    $(this.formID).findFirstElement().activate();
   }
  },
  /*
  Function: submitForm
  Description: Submits the form
  */
  submitForm: function(event) {
   // Serialize the form parameters to pass them along as part of the form submission
   var params = $(this.formID).serialize(true);

   // Check if the tracking number is empty
   if (!params.trackingNumber.empty()) {
    // Disable the form
    $(this.formID).disable();

    // Make an ajax request passing it the serialized form    
    new Ajax.Updater(
     $(this.resultsContainer),
     this.ajaxUrl,
     {
     method: 'get',
     parameters: params,
     onFailure: this.reportError.bindAsEventListener(this),
     onSuccess: this.processResults.bindAsEventListener(this),
     evalScripts: true
     }
    );
   }

   // Prevent the form from being submitted
   Event.stop(event);
  },
  /*
  Function: processResults
  Description: Processes the server results
  */
  processResults: function() {
   // Enable the form
   $(this.formID).enable();
 
   // Reset the form
   $(this.formID).reset();

   // Activate the first element on the form
   $(this.formID).findFirstElement().activate();
  },
  reportError: function(request){}
 };

 Event.observe(window, 'load', function() {
  var ajaxStatusContainersList = $$('div.ajaxStatus');
  var ajaxStatusContainer = '';

  // Create an instance of the form object defined above
  trackingFormInstance = new trackingForm();

  if (ajaxStatusContainersList.length &gt; 0) {
   ajaxStatusContainer = $$('div.ajaxStatus')[0].id;

   Ajax.Responders.register({
    onCreate: function() {
     $(ajaxStatusContainer).show();
    },
    onComplete: function() {
     $(ajaxStatusContainer).hide();
    }
   });
  }
 });
 &amp;lt;/script&amp;gt;
 &amp;lt;/body&amp;gt;
 &amp;lt;/html&amp;gt;
&amp;lt;/cfif&amp;gt;
&amp;lt;/cfoutput&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1194075082303519818?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1194075082303519818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1194075082303519818' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1194075082303519818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1194075082303519818'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/universal-package-tracking-in.html' title='Universal Package Tracking in ColdFusion'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1499068550466050527</id><published>2008-02-18T12:24:00.002-05:00</published><updated>2008-02-19T09:02:10.280-05:00</updated><title type='text'>Get All Form Fields in ModelGlue the Elegant Way</title><content type='html'>If you are using the ModelGlue framework for your ColdFusion development, you know how to get variable values from the form/url scope. Assuming you are inside a controller method that takes the argument &amp;quot;event&amp;quot; of type &amp;quot;ModelGlue.Core.Event&amp;quot;, ModelGlue makes this as simple as &lt;pre name="code" class="cf"&gt;arguments.event.getValue(&amp;quot;eventVariableName&amp;quot;)
&lt;/pre&gt;
where &amp;quot;&lt;span class="cf"&gt;eventVariableName&lt;/span&gt;&amp;quot; is the name of the variable in the form/url scope. Simple enough. However, what happens if you have a form with 10 fields. You could recreate the above with 10 lines with a line for each variable in the form/url scope. Not nice and a bit of a pain. An alternative method would be to great a model cfc containing your getters/setters for each form field. Then using ModelGlue, you would call the &amp;quot;makeEventBean&amp;quot; function passing it the instance of your model and then use model.getName() to get the value of the &amp;quot;name&amp;quot; field. 
&lt;pre name="code" class="cf"&gt;&amp;lt;cfset formModelCFC = component.createObject(&amp;quot;component&amp;quot;, &amp;quot;path.to.formModelCFC&amp;quot;) /&amp;gt;
&amp;lt;cfset arguments.event.makeEventBean(formModelCFC) /&amp;gt;
&amp;lt;cfset name = formModelCFC.getName() /&amp;gt;
&lt;/pre&gt;If you are interested in traveling that route, the method is described in more detail on Dan Willson's blog under &lt;a href="http://www.nodans.com/index.cfm/2007/1/21/So-you-want-to-create-a-ModelGlueUnity-application--Part-3-#more"&gt;So you want to create a ModelGlue:Unity application? (Part 3)&lt;/a&gt; &lt;br /&gt;
This method can also be a pain since you have to update your bean every time you add a new field to the form. After a short dicussion with Ray Camden, there is a even easier way using a built in Model-Glue method (that I had initially overlooked). The code is pretty self-explanatory. 
&lt;pre name="code" class="cf"&gt;
&amp;lt;cfset var eventValues = structnew() /&amp;gt;

&amp;lt;!--- Get the form/url values ---&amp;gt;
&amp;lt;cfset eventValues = arguments.event.getAllValues() /&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1499068550466050527?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1499068550466050527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1499068550466050527' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1499068550466050527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1499068550466050527'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/get-all-form-fields-in-modelglue.html' title='Get All Form Fields in ModelGlue the Elegant Way'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2358078700567208107</id><published>2008-02-07T21:26:00.001-05:00</published><updated>2008-02-07T21:26:59.148-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Get Business Days and Working Hours in a Month with SQL Server</title><content type='html'>In business applications, there often is a need to know the number of business days and/or hours in a month/year. There is a dozen ways to do this depending on your language but here is a SQL Server implementation. The function to get the number of working hours in a month, simply uses the first function - dbo.fnGetBusinessDaysInMonth and by default multiplies the number of business days by 8 hours a day. &lt;br&gt;&lt;br&gt;To use these custom functions, you would call them as follows: &lt;pre class="sql" name="code"&gt;-- Get the number of business days in the month using the current date as a base
select dbo.fnGetBusinessDaysInMonth(getdate())
-- Outputs 21

-- Get the number of business days for January, the date can be any January date
select dbo.fnGetBusinessDaysInMonth('01/01/2008')
-- Outputs 23

-- Get the number of working hours for the current month with the default (8) number of hours per day
select dbo.fnGetWorkingHoursInMonth(getdate(), null)
-- Outputs 168

-- Get the number of working hours for the current month with 4 of hours per day
select dbo.fnGetWorkingHoursInMonth(getdate(), 4)
-- Outputs 84
&lt;/pre&gt;&lt;br&gt;And here are the function definitions: &lt;pre class="sql" name="code"&gt;/*
Type:		Function
Name:		dbo.fnGetBusinessDaysInMonth
Author:		Boyan Kostadinov
Created:	02.05.2007
Dependencies:	None
Usage:		select dbo.fnGetBusinessDaysInMonth(getdate())
		select dbo.fnGetBusinessDaysInMonth('01/01/2008')
Parameters:	@currentDate(datetime)
		- The date to use as a starting point
Description:

Gets the number of business days in a month
*/
alter function dbo.fnGetBusinessDaysInMonth(
	@currentDate datetime
)
returns int
as
begin

declare @dateRange int
declare @beginningOfMonthDate datetime, @endOfMonthDate datetime

-- Get the beginning of the month
set @beginningOfMonthDate = dateadd(month, -1, dateadd(day, -1, dateadd(month, datediff(month, 0, @currentDate) + 1, 1)))

-- Get the the beginning date of the next month
set @endOfMonthDate = dateadd(day, -1, dateadd(month, datediff(month, 0, @currentDate) + 1, 1))

-- Get the date range between the beginning and the end of the month
set @dateRange = datediff(day, @beginningOfMonthDate, @endOfMonthDate)

return
(
	-- Get the number of business days by getting the number
	-- of full weeks * 5 days a week plus the number days remaining
	-- minus any days from the remaining days that are a weekend day
	select	@dateRange / 7 * 5 + @dateRange % 7 -  
	(
	        select	count(*)
		from
	        (
	            select 1 as d
	            union
	            select 2
	            union
	            select 3
	            union
	            select 4
	            union
	            select 5
	            union
	            select 6
	            union
	            select 7
	        ) weekdays
	        where	d &amp;lt;= @dateRange % 7
		        and
			datename(weekday, dateadd(day, -1, @endOfMonthDate) - d)
		        in ('Saturday', 'Sunday')
	)
)

end
&lt;/pre&gt;To get the number of working hours in a month, we can use the dbo.fnGetWorkingHoursInMonth function defined as: &lt;pre class="sql" name="code"&gt;/*
Type:		Function
Name:		dbo.fnGetWorkingHoursInMonth
Author:		Boyan Kostadinov
Created:	02.05.2007
Dependencies:	None
Usage:		select dbo.fnGetWorkingHoursInMonth(getdate(), null)
		select dbo.fnGetWorkingHoursInMonth('01/01/2008', 4)
Parameters:	@currentDate(datetime)
		- The date to use as a starting point

		@workingHoursInADay(int) - Optional, default is 8
		- The number of working hours in a day
Description:

Gets the number of business days in a month
*/
create function dbo.fnGetWorkingHoursInMonth(
	@currentDate datetime,
	@workingHoursInADay int = null
)
returns int
as

begin

if @workingHoursInADay is null
	set @workingHoursInADay = 8

return dbo.fnGetBusinessDaysInMonth(@currentDate) * @workingHoursInADay

end
&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2358078700567208107?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2358078700567208107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2358078700567208107' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2358078700567208107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2358078700567208107'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/get-business-days-and-working-hours-in.html' title='Get Business Days and Working Hours in a Month with SQL Server'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3628968782622850059</id><published>2008-02-07T11:48:00.001-05:00</published><updated>2008-02-07T11:49:38.689-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>How to Impress with Your VB.NET Skills</title><content type='html'>&lt;p&gt;It is no secret that people who write in VB.NET are often looked down upon. Sometimes that can be without merit but sometimes there is a good reason as folks do not bother to learn and improve. That being said, here are some quick rules to impress people while still programming with VB.NET.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Know the .NET Framework&lt;br&gt;Seems like a no-brainer but it is mind boggling how many people switch from VB6 to VB.NET and never bother to learn the new functionality available in .NET. So here are some quick tips:  &lt;ol&gt; &lt;li&gt;Use System.IO.File.ReadAllText() for reading a complete text file instead of reading it line by line.  &lt;li&gt;If you need to process a file line by line, use #1 but split the text file with String.Split() with Environment.NewLine as the delimiter and then loop over the array.  &lt;li&gt;When you need to find something inside a string, indexOf() is not the only choice. Regular expressions are much better and more powerful.  &lt;li&gt;Related to #3, avoid using VB specific functions like Left(), Mid(), or Right() - use String.StartsWith(), String.EndsWith(), String.Substring() or regular expressions instead.  &lt;li&gt;Expanding on #4, avoid VB constructs left over from VB6. A prime example is using "vbCrLf" for inserting new lines instead of Environment.NewLine.&lt;/li&gt;&lt;/ol&gt; &lt;li&gt;Strive to program better&lt;br&gt;Some of the rules below apply not to just VB.NET but to programming in general. Some of course apply only to VB.NET as for example you cannot get by compiling your program in other languages unless your variables are strongly typed (strongly typed simply means that each variable used has an assigned type at compile time such as integer, float or string).  &lt;ol&gt; &lt;li&gt;Strongly type your variables. "dim myVariable" might work for you but how do I know what data type it is. "dim myVariable as String" is much more clear.  &lt;li&gt;Initialize your variables. While for string this might not be needed, for complex object (such as DataTables), it is almost a must. You should simply do&lt;br&gt;&lt;pre name="code" class="vb.net"&gt;dim myData as New DataTable&lt;/pre&gt;&lt;br&gt;or&lt;br&gt;&lt;pre name="code" class="vb.net"&gt;dim myStringData as String = String.Empty&lt;/pre&gt;
&lt;li&gt;Settle on a naming convention that works for you. I name my private member variables starting with "m_" while my public properties have the same name without the "m_". Methods and functions are named in with camel case as in "doSomething()". Whatever you decide is great as long as you are consitant and you stick to it. 
&lt;li&gt;Do not explicetly check a boolean value for "False". Instead of &lt;pre name="code" class="vb.net"&gt;If Directory.Exists(tempPath) = false Then&lt;/pre&gt; use &lt;pre name="code" class="vb.net"&gt;If Not Directory.Exists(tempPath) Then&lt;/pre&gt; 
&lt;li&gt;Use Path.Combine() to combine file system paths intead of concatinating strings with "&amp;amp;" or "+" 
&lt;li&gt;Use String.Format() when outputting strings instead of simple concatenation:&lt;br&gt;&lt;pre name="code" class="vb.net"&gt;String.Format("{0}, {1}, {2}", row.Item("videoID"), row.Item("videoTitle"), row.Item("videoDate"))&lt;/pre&gt; 
&lt;li&gt;Do not assume the data type. A data table row may contain a string value but still use Convert.ToString() to get the value as&lt;br&gt;Convert.ToString(row.Item("categoryName")) 
&lt;li&gt;Related to #3, enable "Option Explicit" and "Option Strict" in your VB.NET projects. This will catch many potential errors at compile time and not let you build your program unless you correct the issues.&lt;/li&gt;&lt;/ol&gt;
&lt;li&gt;Do not reinvent the wheel&lt;br&gt;This point goes hand in hand with knowing the .NET framework but I feel it is worth mentioning on it's own. .NET has so many methods and functions you can use to write your application. Furthermore, there are plenty of open source projects written for all kinds of things: 
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://logging.apache.org/log4net/" target="_blank"&gt;Log4Net&lt;/a&gt; for file, event, or trace logging. 
&lt;li&gt;&lt;a href="http://nant.sourceforge.net" target="_blank"&gt;NAnt&lt;/a&gt; for task automation through XML build files and inline scripting 
&lt;li&gt;&lt;a href="http://www.subsonicproject.com" target="_blank"&gt;SubSonic&lt;/a&gt;, &lt;a href="http://www.nhibernate.org/" target="_blank"&gt;NHibernate&lt;/a&gt; or dozen other projects for database access 
&lt;li&gt;Check out &lt;a href="http://dotnet.dzone.com" target="_blank"&gt;.NET Zone&lt;/a&gt;, &lt;a href="http://www.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt;, &lt;a href="http://www.codeproject.com" target="_blank"&gt;CodeProject&lt;/a&gt; or even &lt;a href="http://www.google.com" target="_blank"&gt;Google&lt;/a&gt; before writing your own implementation. If you need something that can be useful in more than one occasion, it is very likely that somebody else has already written it. You can easily convert code from C# to VB.NET with a dozen of free tools such as the one found at &lt;a href="http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx" target="_blank"&gt;http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3628968782622850059?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3628968782622850059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3628968782622850059' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3628968782622850059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3628968782622850059'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/how-to-impress-with-your-vbnet-skills.html' title='How to Impress with Your VB.NET Skills'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3491699759332751122</id><published>2008-02-06T10:46:00.001-05:00</published><updated>2008-02-06T11:57:04.395-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Quick Tip on Including JavaScript files in Your Model-Glue Views</title><content type='html'>While programming with Model-Glue, I find that I have to often include JavaScript files in each individual view. I most often do this for form validation but it could be for whatever other reason. To keep things consistent, my project layout is based on the standard Model-Glue project layout with the editions of "css", "js" and "images":  &lt;ul&gt; &lt;li&gt;trunk  &lt;ul&gt; &lt;li&gt;config  &lt;li&gt;controller  &lt;li&gt;css  &lt;li&gt;images  &lt;li&gt;js  &lt;li&gt;model  &lt;li&gt;views&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;As you might have guessed, all my JavaScript files reside under "js". So until recently, I would include a JavaScript file as follows:&lt;/p&gt;&lt;pre class="cf" name="code"&gt;&amp;lt;script language="javascript" type="text/javascript"&amp;gt;
&amp;lt;cfinclude template="../js/frmScanBadge.js" /&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;While this works, I do not like to have the hard coded path of the file. So instead, I settled on a solution that will get the name of the current view, look for a corresponding JavaScript file under the "js" directory and if finds one, it will include it:&lt;/p&gt;&lt;pre class="cf" name="code"&gt;&amp;lt;!--- If a JavaScript file exists with the name of the current template under the /js directory, include it ---&amp;gt;
&amp;lt;cfif fileExists(expandPath("js/" &amp;amp; getFileFromPath(getCurrentTemplatePath()).replaceAll(".cfm", ".js")))&amp;gt;
&amp;lt;script language="javascript" type="text/javascript"&amp;gt;
&amp;lt;cfinclude template="#'../js/' &amp;amp; getFileFromPath(getCurrentTemplatePath()).replaceAll('.cfm', '.js')#" /&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/cfif&amp;gt;
&lt;/pre&gt;This solution allows me to keep the name of the view and the corresponding JavaScript file the same. For new views, I can just drop a JavaScript file with the correct name in the "js" directory and it will be included in my view. Not insanely useful but nice non the less.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3491699759332751122?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3491699759332751122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3491699759332751122' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3491699759332751122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3491699759332751122'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/quick-tip-on-including-javascript-files.html' title='Quick Tip on Including JavaScript files in Your Model-Glue Views'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3636350396823371646</id><published>2008-02-05T13:19:00.001-05:00</published><updated>2008-02-05T13:19:02.810-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Capture Combination Keys in Your Windows Forms Application</title><content type='html'>Often while writing a Windows application, it can be helpful to capture a combination of keys such as Ctrl-F1 or Alt-F2. This can be a requirement when showing/hiding some special option that you would not want available by default. So here is how to do just that.  To accomplish this task, the "ProcessDialogKey" function needs to be overridden as follows: &lt;pre class="csharp" name="code"&gt;
protected override bool ProcessDialogKey(Keys keyData)
{
    // Declare a variable to keep track of the key modifiers (Ctrl,Alt,Shift,etc.)
    string modifiers = "";

    // Get the actual integer value of the keystroke
    int keyCode = (int)keyData;

    // Check to see if the control key is on
    if ((keyCode &amp; (int)Keys.Control) != 0)
    {
        modifiers += "&lt;CTRL&gt;";
    }

    // Check to see if the alt key is on
    if ((keyCode &amp; (int)Keys.Alt) != 0)
    {
        modifiers += "&lt;ALT&gt;";
    }

    // Check to see if the shift key is on
    if ((keyCode &amp; (int)Keys.Shift) != 0)
    {
        modifiers += "&lt;SHIFT&gt;";
    }

    // Strip off the modifier keys
    keyCode = keyCode &amp; 0xFFFF;

    // Attempt to convert the remaining bits to the enum name
    Keys key = (Keys)keyCode;

    if ((key != Keys.Menu) &amp;&amp; (key != Keys.ControlKey) &amp;&amp; (key != Keys.ShiftKey))
    {
        // If the user pressed the Ctrl-F1 combination
        if (key == Keys.F1 &amp;&amp; modifiers == "&lt;CTRL&gt;")
        {
            // Do something special
        }
    }

    // Return control to the base function
    return base.ProcessDialogKey(keyData);
}
&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3636350396823371646?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3636350396823371646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3636350396823371646' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3636350396823371646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3636350396823371646'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/capture-combination-keys-in-your.html' title='Capture Combination Keys in Your Windows Forms Application'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4555187727487421868</id><published>2008-02-01T09:24:00.001-05:00</published><updated>2008-02-01T09:42:08.559-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Create a Paragraph Preview with Prototype.js</title><content type='html'>Creating a paragraph with expandable text can be quite useful if you have a lot of text on your page but do not want all of it to show in the same time. Something to the effect of:&lt;br&gt; &lt;p&gt;This is a short preview of the paragraph (&lt;a href="##"&gt;More&lt;/a&gt;) &lt;/p&gt;&lt;br&gt;so when the user clicks on "More" the full paragraph will be displayed like so:  &lt;p&gt;This is a short preview of the paragraph and here is the more text you wanted to see.(&lt;a href="##"&gt;Less&lt;/a&gt;) &lt;/p&gt; &lt;p&gt;You can see the simple example in action at &lt;a title="http://tech-cats.net/blog/examples/createParagraphPreview.html" href="http://tech-cats.net/blog/examples/createParagraphPreview.html" target="_blank"&gt;http://tech-cats.net/blog/examples/createParagraphPreview.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here is how to create this with some simple HTML and JavaScript. The JavaScript relies on Prototype.js but it can be easily re-implemented with a different JavaScript framework. &lt;/p&gt;&lt;pre class="xml" name="code"&gt;&amp;lt;div&amp;gt;
	This is a short preview of the paragraph
	&amp;lt;div id="moreText" style="display: none"&amp;gt;
	and here is the more text you wanted to see.
	&amp;lt;/div&amp;gt;

	&amp;lt;a class="showMore" href="#" rel="moreText"&amp;gt;
		&amp;lt;span id="do_more_less"&amp;gt;More&amp;lt;/span&amp;gt;
	&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
And the JavaScript to do the magic:
&lt;br /&gt;
&lt;pre class="js" name="code"&gt;&amp;lt;script type="text/javascript"&amp;gt;
// For each link element that has the class name "showMore",
// tie the 'click' event to the 'showHide' function
Event.observe(window, 'load',
function() {
	$$('a.showMore').invoke('observe', 'click', showHide);
});

function showHide(event)
{
  // Use the event to get the id of the element that invoked the function
  var currentElement = Event.element(event);

  // Get the parent node of that element and the value of it's "rel" attribute
  var toggleContainer = $(currentElement).parentNode.getAttribute('rel');

  // Get the toggle caption based on the html of the clicked element
  var toggleCaption = ($(currentElement).innerHTML.toLowerCase() == "more") ? "Less" : "More";

  // Update the current element with the new caption value
  $(currentElement).update(toggleCaption);

  // If the container to be toggled exists, toggle it's visibility
  if ($(toggleContainer)) {
    $(toggleContainer).toggle();
  }

  // Return false so the link does not go anywhere
  return false;
}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Something to keep in mind is that you cannot simply copy the JavaScript in the head of the HTML page. That is because the line "$$('a.showMore').invoke('observe', 'click', showHide);", needs to fire after the HTML has been rendered. To resolve this, we can one of two things: 
&lt;ol&gt;
&lt;li&gt;Put the script in the head tag but wrap it inside a window load observer or dom:loaded event (if you are using Prototype v1.6) like so:&lt;br&gt;&lt;pre class="js" name="code"&gt;
Event.observe(window, 'load',
function() {
	$$('a.showMore').invoke('observe', 'click', showHide);
});
&lt;/pre&gt;
or
&lt;pre class="js" name="code"&gt;document.observe("dom:loaded",
function() {
	$$('a.showMore').invoke('observe', 'click', showHide);
});
&lt;/pre&gt;
&lt;li&gt;Put the script as the last thing on the page, after the html.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The code can also be downloaded at &lt;a href="http://tech-cats.net/blog/examples/createParagraphPreview.txt" target="_blank"&gt;http://tech-cats.net/blog/examples/createParagraphPreview.txt&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4555187727487421868?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4555187727487421868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4555187727487421868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4555187727487421868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4555187727487421868'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/create-paragraph-preview-with.html' title='Create a Paragraph Preview with Prototype.js'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8891640641126912950</id><published>2008-02-01T08:53:00.001-05:00</published><updated>2008-02-01T08:53:57.025-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Resources'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>DZone Launches DZone Communities</title><content type='html'>&lt;p&gt;Developer web site &lt;a href="http://www.dzone.com" target="_blank"&gt;DZone&lt;/a&gt; has launched several new web sites each with specific focus - &lt;a href="http://dotnet.dzone.com" target="_blank"&gt;.NET&lt;/a&gt;, &lt;a href="http://coldfusion.dzone.com" target="_blank"&gt;ColdFusion&lt;/a&gt;, &lt;a href="http://ajax.dzone.com/" target="_blank"&gt;Ajax&lt;/a&gt;, &lt;a href="http://php.dzone.com/" target="_blank"&gt;PHP&lt;/a&gt;, etc. Each web site or "zone" (as DZone folks are referencing the web sites) has zone leaders to write articles and contribute content. Their some famous names among the zone leaders such as John Resig (jQuery), Rey Bango, Brian Rinaldi and Dan Wilson.&lt;br&gt;&lt;br&gt;I volunteered to write for the &lt;a href="http://dotnet.dzone.com" target="_blank"&gt;.NET&lt;/a&gt;, &lt;a href="http://coldfusion.dzone.com" target="_blank"&gt;ColdFusion&lt;/a&gt;, &lt;a href="http://ajax.dzone.com/" target="_blank"&gt;Ajax&lt;/a&gt; and &lt;a href="http://sql.dzone.com" target="_blank"&gt;SQL&lt;/a&gt; zones. So from now on content that appears on my blog will also be posted on each appropriate zone web site.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8891640641126912950?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8891640641126912950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8891640641126912950' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8891640641126912950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8891640641126912950'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/02/dzone-launches-dzone-communities.html' title='DZone Launches DZone Communities'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8125825306721065623</id><published>2008-01-30T14:12:00.001-05:00</published><updated>2008-01-30T14:13:22.358-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Using Generic Lists and SQL Server Views in Model-Glue</title><content type='html'>&lt;p&gt;Model-Glue comes with some generic messages that you can use to manipulate data from your database. Generic messages are only available when you are using an ORM adapter with Model-Glue (such as Reactor or Transfer). In general, "messages" are how Model-Glue refers to requests to the server. As a very brief overview, messages are broadcast by the event handler and then handled by the defined Model-Glue controller. You can read more about this at &lt;a href="http://www.dougboude.com/blog/1/2007/08/The-ModelGlue-Event-Lifecycle-in-Laymans-Terms.cfm" target="_blank"&gt;The Model-Glue Event Lifecycle in Layman's Terms&lt;/a&gt; on Doug Boude's blog.&lt;br&gt;&lt;br&gt;I find that I most often use the "ModelGlue.genericList" message which will return a ColdFusion query from the table specified. To use this feature in your event-handler, you simply add something like so under the "broadcasts":&lt;/p&gt;&lt;pre class="xml" name="code"&gt;&amp;lt;message name="ModelGlue.genericList"&amp;gt;
  &amp;lt;!-- The name of your table --&amp;gt;
  &amp;lt;argument name="object" value="Users" /&amp;gt;

  &amp;lt;!-- The name of query variable where the data will be stored --&amp;gt;
  &amp;lt;argument name="queryName" value="usersList" /&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;br&gt;The "object" and "queryName" are the two required arguments you have to specify. However, you can also add an order by clause: &lt;pre class="xml" name="code"&gt;&amp;lt;message name="ModelGlue.genericList"&amp;gt;
  &amp;lt;!-- The name of your table --&amp;gt;
  &amp;lt;argument name="object" value="Users" /&amp;gt;

  &amp;lt;!-- The name of query variable where the data will be stored --&amp;gt;
  &amp;lt;argument name="queryName" value="usersList" /&amp;gt;

  &amp;lt;!-- The column by which the data will be ordered --&amp;gt;
  &amp;lt;argument name="orderBy" value="userName" /&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;br&gt;Or even a criteria to filter the data: &lt;pre class="xml" name="code"&gt;&amp;lt;message name="ModelGlue.genericList"&amp;gt;
  &amp;lt;!-- The name of your table --&amp;gt;
  &amp;lt;argument name="object" value="Users" /&amp;gt;

  &amp;lt;!-- The name of query variable where the data will be stored --&amp;gt;
  &amp;lt;argument name="queryName" value="usersList" /&amp;gt;

  &amp;lt;!-- The column by which the data will be ordered --&amp;gt;
  &amp;lt;argument name="orderBy" value="userName" /&amp;gt;

  &amp;lt;!-- The column by which the data will be filtered --&amp;gt;
  &amp;lt;argument name="criteria" value="userName" /&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;The "criteria" argument is the equivalent of using the "where" clause in your SQL query. It has to contain a name of a column already part of your table. It can also contain a hard coded value for the column value such as: &lt;pre class="xml" name="code"&gt;&amp;lt;!-- The column by which the data will be filtered --&amp;gt;
&amp;lt;argument name="criteria" value="userName=boyan" /&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;If a hard coded value is not specified for the "criteria" argument, Model-Glue looks for the data in the form or url scope. In case current example, it will look for variable with the name "userName" in the event scope and use it's value to set the value of the "criteria". &lt;br&gt;The last, somewhat advanced option in the "genericList" message is the "gatewayMethod" argument. In case your query is more complicated than a simple table lookup (such as many joins, various arguments and special processing), you can use the "gatewayMethod" argument to specify what cfc method Model-Glue should use to get the "genericList". The use this argument, the method has to reside in the model gateway created for the object specified under the "object" argument. In this example, the "gatewayMethod" has to exists in the "Users" gateway. Here is what a gateway generated by Reactor looks like:&lt;br&gt;&lt;pre class="cf" name="code"&gt;&amp;lt;cfcomponent hint="I am the mssql custom Gateway object for the jobs object.  I am generated, but not overwritten if I exist.  You are safe to edit me."
	extends="usersGateway" &amp;gt;

&amp;lt;/cfcomponent&amp;gt;
&lt;/pre&gt;&lt;br&gt;And here is a simple "gatewayMethod" to get a list of users based on a SQL Server stored procedure. The method takes a single numeric parameter called "showDeletedUsers" based on which it returns all users or only currently active users. Please note that this method is over simplified to show how the functionality works: &lt;pre class="cf" name="code"&gt;&amp;lt;cfcomponent hint="I am the mssql custom Gateway object for the jobs object.  I am generated, but not overwritten if I exist.  You are safe to edit me."
	extends="usersGateway" &amp;gt;

&amp;lt;cffunction name="getUsers" access="public" output="false" returntype="query"&amp;gt;
	&amp;lt;cfargument name="showDeletedUsers" type="numeric" required="yes" /&amp;gt;

	&amp;lt;cfset var usersQuery = queryNew("") /&amp;gt;

	&amp;lt;cfstoredproc datasource="#_getConfig().getDsn()#" procedure="dbo.spGetUsers"&amp;gt;
		&amp;lt;cfprocparam
		type="in" null="no" cfsqltype="cf_sql_int"
		dbvarname="showDeletedUsers" value="#arguments.showDeletedUsers#" /&amp;gt;

		&amp;lt;cfprocresult name="usersQuery" resultset="1"&amp;gt;
	&amp;lt;/cfstoredproc&amp;gt;

	&amp;lt;cfreturn usersQuery /&amp;gt;
&amp;lt;/cffunction&amp;gt;

&amp;lt;/cfcomponent&amp;gt;
&lt;/pre&gt;&lt;br&gt;To invoke this method through the "genericList", you simple use: &lt;pre class="xml" name="code"&gt;&amp;lt;message name="ModelGlue.genericList"&amp;gt;
  &amp;lt;!-- The name of your table --&amp;gt;
  &amp;lt;argument name="object" value="Users" /&amp;gt;

  &amp;lt;!-- The name of query variable where the data will be stored --&amp;gt;
  &amp;lt;argument name="queryName" value="usersList" /&amp;gt;

  &amp;lt;!-- The column by which the data will be ordered --&amp;gt;
  &amp;lt;argument name="orderBy" value="userName" /&amp;gt;

  &amp;lt;!-- The column by which the data will be filtered --&amp;gt;
  &amp;lt;argument name="criteria" value="showDeletedUsers=0" /&amp;gt;

  &amp;lt;!-- The custom method to use when retrieving the data --&amp;gt;
  &amp;lt;argument name="gatewayMethod" value="getUsers" /&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;
&lt;br&gt;
The last thing to remember is that you can use the "genericList" with SQL Server views and not just tables. Views are like a custom table that you have defined on the server. They can contain custom fields and data from multiple tables. So if you have a created a view called "vGetUsers" (instead of using the custom "gatewayMethod"), you can use in the "genericList" in the same manner as you would a table:
&lt;pre class="xml" name="code"&gt;&amp;lt;message name="ModelGlue.genericList"&amp;gt;
  &amp;lt;!-- The name of your view --&amp;gt;
  &amp;lt;argument name="object" value="vGetUsers" /&amp;gt;

  &amp;lt;!-- The name of query variable where the data will be stored --&amp;gt;
  &amp;lt;argument name="queryName" value="usersList" /&amp;gt;

  &amp;lt;!-- The column by which the data will be ordered --&amp;gt;
  &amp;lt;argument name="orderBy" value="userName" /&amp;gt;
&amp;lt;/message&amp;gt;&lt;/pre&gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8125825306721065623?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8125825306721065623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8125825306721065623' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8125825306721065623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8125825306721065623'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/using-generic-lists-and-sql-server.html' title='Using Generic Lists and SQL Server Views in Model-Glue'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5404296082301895993</id><published>2008-01-29T22:31:00.001-05:00</published><updated>2008-01-29T22:35:13.894-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Automation'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>Build Your SubSonic DAL with NAnt</title><content type='html'>&lt;p&gt;&lt;a href="http://www.subsonicproject.com"&gt;SubSonic&lt;/a&gt; is a .NET ORM (object relational mapping) tool with plenty of extras. In the ORM market, it can be compared to other tool such as Linq and NHibernate. I chose SubSonic over NHibernate, because of the ease of configuration or Linq, because I am still programming for .NET 2.0. That being said, there are three different ways to generate your data access layer using SubSonic:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Using the command line by calling &amp;quot;sonic.exe&amp;quot; &lt;/li&gt;    &lt;li&gt;Using the &lt;a title="SubSonic Tools for Visual Studio" href="http://www.codeplex.com/subsonictools" target="_blank"&gt;SubSonic Tools for Visual Studio&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Using a build provider. However, this method is only available to web projects. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I was using the second method by installing the tools for Visual Studio. However, that got to be a pain since every time I want to regenerate the data access layer I have to start Visual Studio, wait for it to load, invoke the SubSonic tools, wait for the generation and finally rebuild the project.&lt;/p&gt;  &lt;p&gt;So a few days ago I switched to using the first method - the command line. Once I did that, it was a matter of time before I wrote the NAnt build file to do it for me without Visual Studio - generate the data access layer and rebuild the data access layer dll. So here is the build file that can be used stand alone or even invoked through a pre-build event in Visual Studio:&lt;/p&gt;  &lt;pre class="xml" name="code"&gt;
&amp;lt;project name="Ensemble" default="build" basedir="."&amp;gt;
  &amp;lt;!-- The full path to the SubSonic directory where SubSonic.dll is found --&amp;gt;
  &amp;lt;property name="subSonicFullPath" value="c:\Program Files\SubSonic\SubSonic 2.0.3" /&amp;gt;

  &amp;lt;!-- The full path to the SubSonic commander --&amp;gt;
  &amp;lt;property name="sonicCommanderFullPath" value="C:\Program Files\SubSonic\SubSonic 2.0.3\SubCommander\sonic.exe" /&amp;gt;

  &amp;lt;!-- The command line arguments for the SubSonic commander --&amp;gt;
  &amp;lt;property name="sonicCommanderArguments" value="generate /lang vb" /&amp;gt;

  &amp;lt;!-- The root namespace for the project --&amp;gt;
  &amp;lt;property name="build.rootNamespace" value="ensembleVideo" /&amp;gt;

  &amp;lt;!-- The build type (release or debug) for the project --&amp;gt;
  &amp;lt;property name="build.config" value="release" /&amp;gt;

  &amp;lt;!-- The relative path to the project directory (from the location of the build file) --&amp;gt;
	&amp;lt;property name="targetDirectoryRelativePath" value="../dataAccessLayer" overwrite="false" /&amp;gt;

	&amp;lt;!-- The relative path to directory where SubSonic will generated the files (from the project target directory) --&amp;gt;
	&amp;lt;property name="subsonicGeneratedFilesRelativePath" value="generated" /&amp;gt;

  &amp;lt;property name="targetDirectoryFullPath" value="${path::get-full-path(targetDirectoryRelativePath)}" overwrite="false" /&amp;gt;
  &amp;lt;property name="subsonicGeneratedFilesFullPath" value="${path::combine(targetDirectoryFullPath, 'generated')}" /&amp;gt;
	&amp;lt;property name="binDirectory" value="${path::combine(targetDirectoryFullPath, 'bin')}" overwrite="false" /&amp;gt;

  &amp;lt;property name="buildDirectoryFullPath" value="${path::combine(binDirectory, build.config)}" overwrite="false" /&amp;gt;
  &amp;lt;property name="buildOutput" value="ensembleVideo.dataAccessLayer.dll" /&amp;gt;

  &amp;lt;!-- Default build target --&amp;gt;
	&amp;lt;target name="build"&amp;gt;
	  &amp;lt;!-- Execute the SubSonic commander to generated the files in the defined "sonicCommanderFullPath" directory --&amp;gt;
	  &amp;lt;exec
    	basedir="${targetDirectoryFullPath}"
    	program="${sonicCommanderFullPath}"
    	commandline="${sonicCommanderArguments} /out &amp;quot;${subsonicGeneratedFilesFullPath}&amp;quot;"
    	workingdir="${targetDirectoryFullPath}"
    	failonerror="true" /&amp;gt;

    &amp;lt;!-- Execute the vb compiler to compile the SubSonic generated files --&amp;gt;
    &amp;lt;vbc target="library" output="${path::combine(buildDirectoryFullPath, buildOutput)}" rootnamespace="${build.rootNamespace}"&amp;gt;
        &amp;lt;imports&amp;gt;
            &amp;lt;import namespace="System" /&amp;gt;
            &amp;lt;import namespace="System.Data" /&amp;gt;
        &amp;lt;/imports&amp;gt;

        &amp;lt;sources&amp;gt;
          &amp;lt;!-- Include all the SubSonic generated files --&amp;gt;
          &amp;lt;include name="${subsonicGeneratedFilesFullPath}\*.vb" /&amp;gt;
        &amp;lt;/sources&amp;gt;

        &amp;lt;!-- Include a reference to the SubSonic dll --&amp;gt;
        &amp;lt;references basedir="${subSonicFullPath}"&amp;gt;
  			  &amp;lt;include name="SubSonic.dll" /&amp;gt;
  		  &amp;lt;/references&amp;gt;
     &amp;lt;/vbc&amp;gt;
	&amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5404296082301895993?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5404296082301895993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5404296082301895993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5404296082301895993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5404296082301895993'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/build-your-subsonic-dal-with-nant.html' title='Build Your SubSonic DAL with NAnt'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1124816911364647765</id><published>2008-01-25T17:47:00.001-05:00</published><updated>2008-02-04T09:25:58.625-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>All Your Dates are Belong to Us - Custom Date Formatting in SQL Server</title><content type='html'>Most people that use SQL Server are familiar with formatting dates inside SQL Server. The common approach is: &lt;pre name="code" class="sql"&gt;convert(varchar, getdate(), 106) -- Displays a date in the format 25 Jan 2008&lt;/pre&gt;That is all fine and good if your requirements are satisfied with the formats available inside SQL Server. &lt;!--break--&gt; SQL Server does provide a decent number of formats. Here is the list right from the SQL Server help: &lt;table frame="box" border="1" width="100%" rules="all" cellPadding="2" cols="4" style="width: 100%; height: 650px"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th class="label" width="23%" class="label"&gt;Without century (yy) &lt;/th&gt;&lt;th class="label" width="21%" class="label"&gt;With century (yyyy) &lt;/th&gt;&lt;th class="label" width="27%" class="label"&gt;Standard &lt;/th&gt;&lt;th class="label" width="29%" class="label"&gt;Input/Output** &lt;/th&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;0 or 100 (*) &lt;/td&gt;&lt;td width="27%"&gt;Default&lt;/td&gt;&lt;td width="29%"&gt;mon dd yyyy hh:miAM (or PM)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;1&lt;/td&gt;&lt;td width="21%"&gt;101&lt;/td&gt;&lt;td width="27%"&gt;USA&lt;/td&gt;&lt;td width="29%"&gt;mm/dd/yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;2&lt;/td&gt;&lt;td width="21%"&gt;102&lt;/td&gt;&lt;td width="27%"&gt;ANSI&lt;/td&gt;&lt;td width="29%"&gt;yy.mm.dd&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;3&lt;/td&gt;&lt;td width="21%"&gt;103&lt;/td&gt;&lt;td width="27%"&gt;British/French&lt;/td&gt;&lt;td width="29%"&gt;dd/mm/yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;4&lt;/td&gt;&lt;td width="21%"&gt;104&lt;/td&gt;&lt;td width="27%"&gt;German&lt;/td&gt;&lt;td width="29%"&gt;dd.mm.yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;5&lt;/td&gt;&lt;td width="21%"&gt;105&lt;/td&gt;&lt;td width="27%"&gt;Italian&lt;/td&gt;&lt;td width="29%"&gt;dd-mm-yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;6&lt;/td&gt;&lt;td width="21%"&gt;106&lt;/td&gt;&lt;td width="27%"&gt;-&lt;/td&gt;&lt;td width="29%"&gt;dd mon yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;7&lt;/td&gt;&lt;td width="21%"&gt;107&lt;/td&gt;&lt;td width="27%"&gt;-&lt;/td&gt;&lt;td width="29%"&gt;Mon dd, yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;8&lt;/td&gt;&lt;td width="21%"&gt;108&lt;/td&gt;&lt;td width="27%"&gt;-&lt;/td&gt;&lt;td width="29%"&gt;hh:mm:ss&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;9 or 109 (*) &lt;/td&gt;&lt;td width="27%"&gt;Default + milliseconds&lt;/td&gt;&lt;td width="29%"&gt;mon dd yyyy hh:mi:ss:mmmAM (or PM)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;10&lt;/td&gt;&lt;td width="21%"&gt;110&lt;/td&gt;&lt;td width="27%"&gt;USA&lt;/td&gt;&lt;td width="29%"&gt;mm-dd-yy&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;11&lt;/td&gt;&lt;td width="21%"&gt;111&lt;/td&gt;&lt;td width="27%"&gt;JAPAN&lt;/td&gt;&lt;td width="29%"&gt;yy/mm/dd&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;12&lt;/td&gt;&lt;td width="21%"&gt;112&lt;/td&gt;&lt;td width="27%"&gt;ISO&lt;/td&gt;&lt;td width="29%"&gt;yymmdd&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;13 or 113 (*) &lt;/td&gt;&lt;td width="27%"&gt;Europe default + milliseconds&lt;/td&gt;&lt;td width="29%"&gt;dd mon yyyy hh:mm:ss:mmm(24h)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;14&lt;/td&gt;&lt;td width="21%"&gt;114&lt;/td&gt;&lt;td width="27%"&gt;-&lt;/td&gt;&lt;td width="29%"&gt;hh:mi:ss:mmm(24h)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;20 or 120 (*) &lt;/td&gt;&lt;td width="27%"&gt;ODBC canonical&lt;/td&gt;&lt;td width="29%"&gt;yyyy-mm-dd hh:mi:ss(24h)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;21 or 121 (*) &lt;/td&gt;&lt;td width="27%"&gt;ODBC canonical (with milliseconds)&lt;/td&gt;&lt;td width="29%"&gt;yyyy-mm-dd hh:mi:ss.mmm(24h)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;126(***)&lt;/td&gt;&lt;td width="27%"&gt;ISO8601&lt;/td&gt;&lt;td width="29%"&gt;yyyy-mm-dd Thh:mm:ss:mmm(no spaces)&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;130*&lt;/td&gt;&lt;td width="27%"&gt;Kuwaiti&lt;/td&gt;&lt;td width="29%"&gt;dd mon yyyy hh:mi:ss:mmmAM&lt;/td&gt;&lt;/tr&gt;&lt;tr vAlign="top"&gt;&lt;td width="23%"&gt;-&lt;/td&gt;&lt;td width="21%"&gt;131*&lt;/td&gt;&lt;td width="27%"&gt;Kuwaiti&lt;/td&gt;&lt;td width="29%"&gt;dd/mm/yy hh:mi:ss:mmmAM&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Wouldn't you know it, my requirements were not :-) I tried working with the built in formats and had to roll my own after all anyway. So here is the function I came up with: &lt;b&gt;Please note: &lt;/b&gt;The function below relies on using regular expressions inside SQL Server. SQL Server does not have built in regular expression support so the function below relies on the method described in my other blog post about &lt;a target="_blank" href="http://blog.tech-cats.com/2007/09/using-regular-expression-in-sql-server.html" title="Using Regular Expression in SQL Server" id="woy3"&gt;Using Regular Expression in SQL Server&lt;/a&gt;. &lt;pre name="code" class="sql"&gt;/*
Type:		Function
Name:		dbo.fnFormatDate
Author:		Boyan Kostadinov
Created:	01.25.2008
Dependencies:	master.dbo.fn_pcre_replace
Parameters:	@inputDate(datetime)
		- The date to format

		@formatString(varchar)
		- the format string to use (Examples &amp;quot;dd mm yyyy&amp;quot;, &amp;quot;mmm.dd.yy&amp;quot;)
Description:

Formats a given date based on the format specified in @formatString
d 	- one digit day (when applicable)
dd	- two digit day
ddd	- short day name
dddd	- long day name
m	- one digit month (when applicable)
mm	- two digit month
mmm	- short month name
mmmm	- long month name
yy	- two digit year
yyyy	- four digit year
*/
create function dbo.fnFormatDate
(
	@inputDate datetime,
	@formatString varchar(25)
)
returns varchar(20) as
begin
	declare @returnValue varchar(25)

	-- Declare local vairables
	declare @formattedDate varchar(25),
		@day varchar(20), @month varchar(20), @year varchar(20),
		@dayFormat varchar(5), @monthFormat varchar(5), @yearFormat varchar(5)

	set @dayFormat = ''
	set @monthFormat = ''
	set @yearFormat = ''

	-- Convert the supplied date to day mon year (25 Jan 2008)
	set @formattedDate = convert(varchar, @inputDate, 106)

	-- If the format string contains a format for the day
	if charindex('d', @formatString) &amp;gt; 0
		-- Get the day format string
		set @dayFormat = master.dbo.fn_pcre_replace(@formatString, '.*?(d{1,4}).*', '$1')

	-- If the format string contains a format for the month
	if charindex('m', @formatString) &amp;gt; 0
		-- Get the month format string
		set @monthFormat = master.dbo.fn_pcre_replace(@formatString, '.*?(m{1,4}|M{1,4}).*', '$1')

	-- If the format string contains a format for the year
	if charindex('y', @formatString) &amp;gt; 0
		-- Get the year format string
		set @yearFormat = master.dbo.fn_pcre_replace(@formatString, '.*?(y{2,4}).*', '$1')

	-- Format the day value based on the format string for the day
	select	@day =
		case @dayFormat
		when 'dd' then master.dbo.fn_pcre_replace(@formattedDate, '^(\d+).*', '$1')
		when 'ddd' then substring(datename(dw, @formattedDate), 1, 3)
		when 'dddd' then datename(dw, @formattedDate)
		else convert(varchar, day(@formattedDate))
	end

	-- Format the month value based on the format string for the month
	select	@month =
		case @monthFormat
		when 'mm' then master.dbo.fn_pcre_replace(convert(varchar, @inputDate, 101), '^(\d+)/.*', '$1')
		when 'mmm' then master.dbo.fn_pcre_replace(@formattedDate, '\d+\s(\w+)\s\d+', '$1')
		when 'mmmm' then datename(m, @formattedDate)
		else convert(varchar, month(@formattedDate))
	end

	-- Format the year value based on the format string for the year
	select	@year =
		case @yearFormat
		when 'yy' then substring(convert(varchar, year(@formattedDate)), 3, 2)
		else convert(varchar, year(@formattedDate))
	end

	set @returnValue = @formatString

	-- If the day format was specified
	if @dayFormat &amp;lt;&amp;gt; ''
		-- Replace the day format string with the actual day value
		set @returnValue = master.dbo.fn_pcre_replace(@returnValue, @dayFormat, @day)

	-- If the month format was specified
	if @monthFormat &amp;lt;&amp;gt; ''
		-- Replace the month format string with the actual month
		set @returnValue = master.dbo.fn_pcre_replace(@returnValue, @monthFormat, @month)
	
	-- If the year format was specified
	if @yearFormat &amp;lt;&amp;gt; ''
		-- Replace the year format string with the actual year
		set @returnValue = master.dbo.fn_pcre_replace(@returnValue, @yearFormat, @year)

	-- Return the formated value
	return @returnValue
end
&lt;/pre&gt;To test this function, I created a table that hold the following date format string: &lt;pre name="code" class="sql"&gt;formatString             &lt;br /&gt;-------------------------&lt;br /&gt;dd MMM yy&lt;br /&gt;dd MMM yyyy&lt;br /&gt;dd-MM-yy&lt;br /&gt;dd-MM-yyyy&lt;br /&gt;dd.MM.yy&lt;br /&gt;dd.MM.yyyy&lt;br /&gt;dd/MM/yy&lt;br /&gt;dd/MM/yyyy&lt;br /&gt;ddMMMyy&lt;br /&gt;ddMMMyyyy&lt;br /&gt;MM-dd-yy&lt;br /&gt;MM-dd-yyyy&lt;br /&gt;MM/dd/yy&lt;br /&gt;MM/dd/yyyy&lt;br /&gt;MMM dd yyyy&lt;br /&gt;MMM dd, yy&lt;br /&gt;MMM dd, yyyy&lt;br /&gt;MMMdd,yyyy&lt;br /&gt;MMMddyyyy&lt;br /&gt;yy.MM.dd&lt;br /&gt;yy/MM/dd&lt;br /&gt;yyMMdd&lt;br /&gt;yyyy-MM-dd&lt;br /&gt;yyyy.MM.dd&lt;br /&gt;yyyy/MM/dd&lt;br /&gt;yyyyMMdd&lt;br /&gt;MMMyyyy&lt;br /&gt;
&lt;/pre&gt;I tested the function with the simple SQL query: &lt;pre name="code" class="sql"&gt;select df.formatString,&lt;br /&gt; dbo.fnFormatDate(getdate(), df.formatString)&lt;br /&gt; as formattedDate&lt;br /&gt;from dateFormats as df&lt;br /&gt;
&lt;/pre&gt;And here are the results: &lt;pre name="code" class="sql"&gt;formatString              formattedDate       &lt;br /&gt;------------------------- --------------------&lt;br /&gt;dd MMM yy                 25 Jan 08&lt;br /&gt;dd MMM yyyy               25 Jan 2008&lt;br /&gt;dd-MM-yy                  25-01-08&lt;br /&gt;dd-MM-yyyy                25-01-2008&lt;br /&gt;dd.MM.yy                  25.01.08&lt;br /&gt;dd.MM.yyyy                25.01.2008&lt;br /&gt;dd/MM/yy                  25/01/08&lt;br /&gt;dd/MM/yyyy                25/01/2008&lt;br /&gt;ddMMMyy                   25Jan08&lt;br /&gt;ddMMMyyyy                 25Jan2008&lt;br /&gt;MM-dd-yy                  01-25-08&lt;br /&gt;MM-dd-yyyy                01-25-2008&lt;br /&gt;MM/dd/yy                  01/25/08&lt;br /&gt;MM/dd/yyyy                01/25/2008&lt;br /&gt;MMM dd yyyy               Jan 25 2008&lt;br /&gt;MMM dd, yy                Jan 25, 08&lt;br /&gt;MMM dd, yyyy              Jan 25, 2008&lt;br /&gt;MMMdd,yyyy                Jan25,2008&lt;br /&gt;MMMddyyyy                 Jan252008&lt;br /&gt;yy.MM.dd                  08.01.25&lt;br /&gt;yy/MM/dd                  08/01/25&lt;br /&gt;yyMMdd                    080125&lt;br /&gt;yyyy-MM-dd                2008-01-25&lt;br /&gt;yyyy.MM.dd                2008.01.25&lt;br /&gt;yyyy/MM/dd                2008/01/25&lt;br /&gt;yyyyMMdd                  20080125&lt;br /&gt;MMMyyyy                   Jan2008&lt;br /&gt;
&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1124816911364647765?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1124816911364647765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1124816911364647765' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1124816911364647765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1124816911364647765'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/all-your-dates-are-belong-to-us-custom.html' title='All Your Dates are Belong to Us - Custom Date Formatting in SQL Server'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3763165626981735412</id><published>2008-01-19T21:47:00.001-05:00</published><updated>2008-01-29T15:57:14.591-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Tracking'/><category scheme='http://www.blogger.com/atom/ns#' term='Organization'/><title type='text'>Kick Butt Project Management with Assembla</title><content type='html'>&lt;p&gt;A few days ago I blogged about &lt;a href="http://blog.tech-cats.com/2008/01/tools-for-better-project-management-and.html" target="_blank"&gt;Tools for Better Project Management and Organization&lt;/a&gt; and this post offers an alternative application for project management. As I mentioned in my pervious post, I highly recommend &lt;a href="http://www.redmine.org" target="_blank"&gt;RedMine&lt;/a&gt; as your web based project manager. RedMine is great if you want something that you have complete control over. With complete control however, come the pain of having to install it, configure it and worry about backups. So today, as a part of a project I am involved in, I set on a quest to find something that would be as good as RedMine but without the installation and configuration involved. After evaluating a few different web based project management application (&lt;a href="http://www.unfuddle.com" target="_blank"&gt;Unfuddle&lt;/a&gt;, &lt;a href="http://www.codespaces.com/" target="_blank"&gt;CodeSpaces&lt;/a&gt;, and a few other not worth mentioning), I tried &lt;a href="http://www.assembla.com" target="_blank"&gt;Assembla&lt;/a&gt;. I had put in on my list to evaluate a while ago so it was not a new find but I am sorry I did not try it earlier. I am not going to get into much detail on the features but I have to say, the number of features is impressive. Best of all you get all this including 500mb of space for free! Here is a quick overview:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The start page:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/BoyanKostadinovstartAssembla_1200795708018.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="401" alt="Boyan Kostadinov- start -Assembla_1200795708018" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/BoyanKostadinovstartAssembla_1200795708018_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;The dashboard&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoindexAssembla_1200795731143.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="401" alt="Ensemble Video- index -Assembla_1200795731143" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoindexAssembla_1200795731143_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Time entry&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideotasksAssembla_1200795740736.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- tasks -Assembla_1200795740736" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideotasksAssembla_1200795740736_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Milestones&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoMilestonesAssembla_1200795878080.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- Milestones -Assembla_1200795878080" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoMilestonesAssembla_1200795878080_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Online chat&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideochatAssembla_1200795889986.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- chat -Assembla_1200795889986" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideochatAssembla_1200795889986_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Files repository&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideofilesAssembla_1200795897143.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- files -Assembla_1200795897143" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideofilesAssembla_1200795897143_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Wiki&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoSpaceHomeAssembla_1200795904674.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="392" alt="Ensemble Video- Space Home -Assembla_1200795904674" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoSpaceHomeAssembla_1200795904674_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Trac/SVN integration&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideotrac_toolAssembla_1200795912877.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="401" alt="Ensemble Video- trac_tool -Assembla_1200795912877" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideotrac_toolAssembla_1200795912877_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Images repository&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoImagesAssembla_1200795923080.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- Images -Assembla_1200795923080" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoImagesAssembla_1200795923080_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Blog integration with Mephisto&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideomephisto_toolAssembla_1200795932439.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="Ensemble Video- mephisto_tool -Assembla_1200795932439" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideomephisto_toolAssembla_1200795932439_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Alerts&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoalertsAssembla_1200795964174.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="401" alt="Ensemble Video- alerts -Assembla_1200795964174" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoalertsAssembla_1200795964174_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Additional add-ons&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoeditAssembla_1200795987596.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="401" alt="Ensemble Video- edit -Assembla_1200795987596" src="http://boyan.tech-cats.com/images/blog/BoyanKostadinovstartAssembla_12C72/EnsembleVideoeditAssembla_1200795987596_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3763165626981735412?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3763165626981735412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3763165626981735412' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3763165626981735412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3763165626981735412'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/kick-butt-project-management-with.html' title='Kick Butt Project Management with Assembla'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4409643869452356901</id><published>2008-01-18T22:03:00.003-05:00</published><updated>2008-06-13T17:44:25.144-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Kill All Database Connections to a SQL Server Database</title><content type='html'>Today I needed to kill the active connections to a particular database so I can delete it. Usually that can be a painful process of opening enterprise manager and killing each active process one by one. While that approach might be fine for one or two active connections, when you have over 10, it gets to be annoying. So here is a script that will get all the active connections for a given database and kill each one. This is already part of my other post titled &lt;a href="http://blog.tech-cats.com/2007/10/sql-server-script-to-restore-database.html"&gt;SQL Server Script to Restore a Database from File&lt;/a&gt;.

&lt;pre class="sql" name="code"&gt;
-- Create the sql to kill the active database connections
declare @execSql varchar(1000), @databaseName varchar(100)
-- Set the database name for which to kill the connections
set @databaseName = 'myDatabase'

set @execSql = '' 
select  @execSql = @execSql + 'kill ' + convert(char(10), spid) + ' '
from    master.dbo.sysprocesses
where   db_name(dbid) = @databaseName
     and
     DBID &amp;lt;&amp;gt; 0
     and
     spid &amp;lt;&amp;gt; @@spid
exec(@execSql)
&lt;/pre&gt;

&lt;b&gt;Update&lt;/b&gt;
&lt;br /&gt;
As Noel pointed out, it turns out there is much simpler way:
&lt;pre class="sql" name="code"&gt;
alter database dbName set single_user with rollback immediate
&lt;/pre&gt;
and to revert that
&lt;pre class="sql" name="code"&gt;
alter database dbName set multi_user with rollback immediate
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4409643869452356901?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4409643869452356901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4409643869452356901' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4409643869452356901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4409643869452356901'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/kill-all-database-connections-to-sql.html' title='Kill All Database Connections to a SQL Server Database'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1171870084671959136</id><published>2008-01-17T09:29:00.001-05:00</published><updated>2008-01-17T09:29:53.314-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Prototype.js Extensions by Nick Stakenburg</title><content type='html'>&lt;p&gt;I was working on a project today with the excellent &lt;a title="Prototip" href="http://www.nickstakenburg.com/projects/prototip/"&gt;Prototip&lt;/a&gt; extension for Prototype.js. Prototip makes it easy to add tooltips to any element. Here is what a custom styled tooltip would look like:&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/toolitpExample.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="329" alt="toolitpExample" src="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/toolitpExample_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;While browsing the &lt;a title="support forum" href="http://www.nickstakenburg.com/forum/" target="_blank"&gt;support forum&lt;/a&gt; that Nick has put together for Prototip, I realized that he has created more than one Prototype extension. First is &lt;a title="Starbox" href="http://www.nickstakenburg.com/projects/starbox/" target="_blank"&gt;Starbox&lt;/a&gt; which allows you to add a star rating system to your page:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;a href="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/StarboxRatingstarsforprototype_1200573851295.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="400" alt="Starbox - Rating stars for prototype_1200573851295" src="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/StarboxRatingstarsforprototype_1200573851295_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Next is &lt;a title="Lightview" href="http://www.nickstakenburg.com/projects/lightview/" target="_blank"&gt;Lightview&lt;/a&gt; which is very similar to &lt;a title="Lightbox" href="http://www.huddletogether.com/projects/lightbox/" target="_blank"&gt;Lightbox&lt;/a&gt; and it creates an overlay window to display your images:&lt;/p&gt; &lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/Lightview_1200574518998.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="440" alt="Lightview_1200574518998" src="http://boyan.tech-cats.com/images/blog/NicePrototype.jsBasedAdditionsbyNick_6CB0/Lightview_1200574518998_thumb.jpg" width="644" border="0"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1171870084671959136?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1171870084671959136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1171870084671959136' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1171870084671959136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1171870084671959136'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/prototypejs-extensions-by-nick.html' title='Prototype.js Extensions by Nick Stakenburg'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5757560448304545755</id><published>2008-01-14T14:53:00.000-05:00</published><updated>2008-01-14T11:10:36.520-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Tracking'/><category scheme='http://www.blogger.com/atom/ns#' term='Organization'/><title type='text'>Tools for Better Project Management and Organization</title><content type='html'>&lt;p&gt;Organization and project management have turned into very important skills even for developers. With growing demand for automation and the spread of information, companies are consistently working on new ways to organize, restructure and make data accessible.&lt;/p&gt; &lt;p&gt;If you are a developer, at some point in your career, it is very likely that you have run into trouble with a project running over the perceived time frame and/or original specifications. Everyone in the programming word has heard the horror stories of never ending features and lack of project requirements. I would not be honest if I said this has not happened to me. C'est la vie, as the French would say but I am trying to learn something from it.&lt;/p&gt; &lt;p&gt;Over the past few months, I have started to use several tools to keep track of project requirements/bugs/features, log tasks I have worked on/accomplished, and billing related data (tasks, time, invoices, etc).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Project Management&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;After evaluating about 20 open source projects (thank you SourceForge), and some commercial products, I settled on using a open source project called &lt;a href="http://www.redmine.org" target="_blank"&gt;RedMine&lt;/a&gt;. Here is the overview of RedMine's features directly from the web site:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Multiple projects support  &lt;li&gt;Flexible role based access control.  &lt;li&gt;Flexible issue tracking system  &lt;li&gt;Gantt chart and calendar  &lt;li&gt;News, documents &amp;amp; files management  &lt;li&gt;Feeds &amp;amp; email notifications.  &lt;li&gt;Per project wiki  &lt;li&gt;Per project forums  &lt;li&gt;Simple time tracking functionality  &lt;li&gt;Custom fields for issues, projects and users  &lt;li&gt;SCM integration (SVN, CVS, Mercurial, Bazaar and Darcs)  &lt;li&gt;Multiple LDAP authentication support  &lt;li&gt;User self-registration support  &lt;li&gt;Multilingual support  &lt;li&gt;Multiple databases support &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can see a full list of features plus screen shots at the &lt;a href="http://www.redmine.org/wiki/redmine/Features" target="_blank"&gt;Features&lt;/a&gt; page.&lt;br&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Task Logging&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The nice folks at &lt;a href="http://lifehacker.com" target="_blank"&gt;Lifehacker&lt;/a&gt; have put together an excellent little script for logging your daily tasks. The basics of it are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You setup the script by editing the .vbs file, create a shortcut to it and setup a shortcut key  &lt;li&gt;You press the shortcut key and an input box pops up  &lt;li&gt;You enter the task/item you want to log and the script writes it with a date plus time to your log file&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can find the full details about it and how to set it up at &lt;a title="Geek to Live: Quick-log your work day" href="http://lifehacker.com/software/capture-tools/geek-to-live--quick+log-your-work-day-189772.php" target="_blank"&gt;Geek to Live: Quick-log your work day&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;Keeping Track of Billing Data&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;There is more than one tool for the job so choices highly depend on features, preference and price. For my need, I have found that a tool will need a least a minimum set of features:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Keep track of clients and projects  &lt;li&gt;Log time and description per time spend on project  &lt;li&gt;Generate invoices for selected time frame&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Considering the above, I can recommend a small windows application called &lt;a title="" href="http://www.billingtracker.com/"&gt;Billing Tracker&lt;/a&gt;. The pro version costs $89. I am sure there are plenty of free web based applications that fall in this category too.&lt;br&gt;&lt;br&gt;&lt;strong&gt;Bonus - Keeping Track of your Daily Tasks&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Even with all the above, keeping on track with your projects and life can be hard. Not everything falls into a project and sometimes you do not want to create the smallest task as part of your project tracking. On the other hand, if you don't write it down, you will forget it, I do.&lt;/p&gt; &lt;p&gt;So here is where a To-Do list comes in. There are many, many free, web based to-do applications. I use &lt;a title="" href="https://www.rememberthemilk.com" target="_blank"&gt;Remember The Milk&lt;/a&gt;. Some nice features are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Offline access (with Google Gears)  &lt;li&gt;Task categories, lists and locations  &lt;li&gt;Reminders  &lt;li&gt;Integration with GMail (only for Firefox with an extension) and Google Calendar  &lt;li&gt;RSS of your tasks&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;br&gt;&lt;strong&gt;Conclusion&lt;br&gt;&lt;/strong&gt;&lt;br&gt;No matter how you decide to go about it, most important than everything else is your discipline to track and log your work.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5757560448304545755?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5757560448304545755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5757560448304545755' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5757560448304545755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5757560448304545755'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/tools-for-better-project-management-and.html' title='Tools for Better Project Management and Organization'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2744987990641627985</id><published>2008-01-14T10:49:00.001-05:00</published><updated>2008-01-14T11:12:03.808-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Using Optional Parameters in SQL Server Stored Procedures</title><content type='html'>&lt;p&gt;Stored procedures are a nice way to encapsulate some business logic inside your database. This post is not about learning how to write stored procedures but instead deals with the specifics of implementing optional parameters in your SQL Server stored procedures. You can learn more about stored procedures at &lt;a title="Wikipedia" href="http://en.wikipedia.org/wiki/Stored_procedure" target="_blank"&gt;Wikipedia&lt;/a&gt; or &lt;a title="Google" href="http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;hs=aZ6&amp;amp;q=stored+procedures&amp;amp;btnG=Search"&gt;Google&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The most common use of stored procedures is to return some data based on some passed in parameters. More often then not they need to take multiple parameters. A common struggle is how to pass optional parameters to a stored procedure.&lt;/p&gt; &lt;p&gt;Let's talk about a simple example. You have an employees table that has the employee id, first name and last name. The table is defined as follows:&lt;/p&gt;&lt;pre class="sql" name="code"&gt;create table [dbo].[employees] (
  [id] int identity(1, 1) not null,
  [firstName] varchar(255) null,
  [lastName] varchar(255) null,
  primary key clustered ([id])
)
on [primary]
go
&lt;/pre&gt;
&lt;p&gt;and has the been populated with the following sample data:&lt;/p&gt;&lt;pre class="sql" name="code"&gt;insert into [dbo].[employees] ([firstName], [lastName])
values (N'Boyan', N'Vassilvev')
go

insert into [dbo].[employees] ([firstName], [lastName])
values (N'Boyan', N'Kostadinov')
go

insert into [dbo].[employees] ([firstName], [lastName])
values (N'Doug', N'Boude')
go
&lt;/pre&gt;
&lt;p&gt;You would like to write a stored procedure to return this data but if you don't want to write separate procedure for each type of employee search you want to execute. Ideally, you want to write one stored procedure that will return all employees or only an employee with a certain id or an employee has a certain first name (or last name for that matter). So how is this done? Simple, you need to use optional parameters in your stored procedure. You define your procedures as follows:&lt;/p&gt;&lt;pre class="sql" name="code"&gt;create	proc	dbo.spGetEmployees
	@employeeID int = null,
	@firstName varchar(255) = null,
	@lastName varchar(255) = null
as

select	*
from	dbo.employees
where	(id = @employeeID or @employeeID is null)
	and
	(firstName = @firstName or @firstName is null)
	and
	(lastName = @lastName or @lastName is null)
&lt;/pre&gt;
&lt;p&gt;Now you can call the same stored procedure 4 different ways:&lt;/p&gt;&lt;pre class="sql" name="code"&gt;-- Without parameters to get all the employees
exec dbo.spGetEmployees
-- With id parameter to get an employee with a specific id
exec dbo.spGetEmployees 1
-- With first name parameter to get an employee with a specific first name
exec dbo.spGetEmployees null, 'boyan'
-- With last name parameter to get an employee with a specific last name
exec dbo.spGetEmployees null, null, 'kostadinov'
&lt;/pre&gt;
&lt;p&gt;And you will get results which look like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://boyan.tech-cats.com/images/blog/UsingOptionalParametersinSQLServerStored_9486/image.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="image" src="http://boyan.tech-cats.com/images/blog/UsingOptionalParametersinSQLServerStored_9486/image_thumb.png" width="186" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;Something to keep in mind is that the parameter order is important. If you are specifying only the first optional parameter, you do not need anything else. However, if you want to use any but the first parameter, you need to set any preceding parameters to "null".&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2744987990641627985?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2744987990641627985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2744987990641627985' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2744987990641627985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2744987990641627985'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/using-optional-parameters-in-sql-server.html' title='Using Optional Parameters in SQL Server Stored Procedures'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4055718625304690523</id><published>2008-01-11T14:19:00.003-05:00</published><updated>2008-11-12T16:22:24.451-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Unobtrusive JavaScript - Tie Events to Links with Prototype</title><content type='html'>Often, it is a good practice to separate your presentation layer from the the logic of your application. In web application, the presentation layer is your html pages, while the logic usually resides on the server or in JavaScript on the client (such as validation of user submitted values). Separating presentation and logic usually has to do with as little as possible logic inside your presentation layer. &lt;br&gt;With this in mind, it would be nice to have your application do something with JavaScript when you click on a link. In previous years that would be written something like this: &lt;pre class="html" name="code"&gt;&amp;lt;a href="#" onClick="alert('You Clicked on Link 1');"&amp;gt;Link 1&amp;lt;/a&amp;gt;&lt;br&gt;&amp;lt;a href="#" onClick="alert('You Clicked on Link 1');"&amp;gt;"&amp;gt;Link 1&amp;lt;/a&amp;gt;&lt;/pre&gt;While that works for this simple example, it is much nicer not to duplicate your code and not to mix your html with JavaScript. There is more than one reason the above approach is no longer the desired on, but here are few reasons: you need to write the "alert" call in each link you create, if your functionality changes, you will have to track each one of those calls and change them. The newer, desired, approach is to leave the JavaScript in a separate file and instead use the element's CSS class name to apply some logic to the element. So instead of the way above, you will simply define your links as follows:&lt;pre class="html" name="code"&gt;&amp;lt;a href="#" class="clickMe"&amp;gt;Link 1&amp;lt;/a&amp;gt;&lt;br&gt;&amp;lt;a href="#" class="clickMe"&amp;gt;Link 2&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now you just need to write the JavaScript which will look for all "a" elements with the CSS class name of "clickMe" and for each one found, it will invoke the "whatDidIClick" function.&lt;br&gt;&lt;pre class="js" name="code"&gt;&amp;lt;script type="text/javascript" language="javascript"&amp;gt;&lt;br&gt;// For each link element with CSS class name "clickMe"&lt;br&gt;$$('a.clickMe').invoke('observe', 'click', whatDidIClick);&lt;br&gt;&lt;br&gt;function whatDidIClick(event) {&lt;br&gt;// Event.element(event) returns the element that caused the click event&lt;br&gt;alert('You clicked on ' + Event.element(event).innerHTML));&lt;br&gt;}&lt;br&gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4055718625304690523?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4055718625304690523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4055718625304690523' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4055718625304690523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4055718625304690523'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/unobtrusive-javascript-tie-events-to.html' title='Unobtrusive JavaScript - Tie Events to Links with Prototype'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6606843984093981188</id><published>2008-01-09T09:26:00.001-05:00</published><updated>2008-01-09T09:26:00.705-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Speaking at CFUnited 2008 about JavaScript Frameworks</title><content type='html'>&lt;a href="http://boyan.tech-cats.com/images/blog/SpeakingatCFUnited2008_92DD/125x125_cfunited08_speaker.gif"&gt;&lt;img style="margin: 0px 10px 0px 0px" height="125" alt="125x125_cfunited08_speaker" src="http://boyan.tech-cats.com/images/blog/SpeakingatCFUnited2008_92DD/125x125_cfunited08_speaker_thumb.gif" width="125" align="left"&gt;&lt;/a&gt;Just a quick note about this year's CFUnited in Washington DC. If you don't know what CFUnited is, you can learn more at the &lt;a href="http://cfunited.com" target="_blank"&gt;CFUnited web site&lt;/a&gt;. Basically, it is one of the few major ColdFusion conferences.&lt;br&gt;&lt;br&gt;I will be speaking on the topic of "&lt;strong&gt;Using Popular JavaScript Frameworks&lt;/strong&gt;" and it will cover Prototype, jQuery, mooTools, Yahoo UI and Ext. I haven't worked out the complete table of contents but I will have one shortly.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6606843984093981188?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6606843984093981188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6606843984093981188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6606843984093981188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6606843984093981188'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/speaking-at-cfunited-2008-about.html' title='Speaking at CFUnited 2008 about JavaScript Frameworks'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3667925396599178376</id><published>2008-01-08T07:40:00.000-05:00</published><updated>2008-01-08T07:46:19.747-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Introduction to Model-Glue</title><content type='html'>&lt;p&gt;The presentation below is a short introduction to Model-Glue for the Central New York ColdFusion Users Group. &lt;/p&gt;
&lt;p&gt;
&lt;iframe src="http://docs.google.com/EmbedSlideshow?docid=dcz9szc5_10frddxzfg" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Supporting Documentation
&lt;/strong&gt;&lt;a href="http://docs.google.com/Doc?id=dcz9szc5_11gff8ddd5"&gt;http://docs.google.com/Doc?id=dcz9szc5_11gff8ddd5&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3667925396599178376?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3667925396599178376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3667925396599178376' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3667925396599178376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3667925396599178376'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/introduction-to-model-glue.html' title='Introduction to Model-Glue'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3312463512384019662</id><published>2008-01-04T10:14:00.001-05:00</published><updated>2008-01-08T07:22:38.493-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>NAnt, What Operating System is This?</title><content type='html'>I needed a quick way to tell what operating system the NAnt build file was running under. Why, one might wonder? Let's say you are installing a web application under IIS and you need the ASP.NET extension to be enabled. If you are wondering what that means, it's simple, with the introduction of IIS 6 (under Windows 2003), individual extensions (such as ASP or ASP.NET) can be enabled or disabled by the system administrator. So back to the why, you need to install a ASP.NET web application under IIS but to make things more complicated (as I often like to do), the ASP.NET extension might be disabled. So, you create a NAnt build file to do all the copy/setup steps for your web application installation (if you don't know what NAnt is, check out my other post titled &lt;a title="Getting Started with NAnt - .NET Build Tool" target="_blank" href="http://blog.tech-cats.com/2007/11/getting-started-with-nant-net-build.html" id="fo4e"&gt;Getting Started with NAnt - .NET Build Tool&lt;/a&gt;) but now you need to check if the ASP.NET extension is enabled. Before you can do that, you have to remember that only IIS 6 under Windows 2003 supports enabling/disabling extensions. If you try that under Windows XP (IIS 5) or Windows 2000 (IIS 5), your build file with barf. So to make a long story short, I need a test that will tell me if the NAnt build file is running under Windows 2003 or another operating system. So let's start with the NAnt build file that will output the current operating system:
&lt;br /&gt;
&lt;pre class="xml" name="code"&gt;
&amp;lt;project name="testOS" default="runTest"&amp;gt;
  &amp;lt;property name="operatingSystem" value="${operating-system::to-string(environment::get-operating-system())}" /&amp;gt;

  &amp;lt;target name="runTest"&amp;gt;
    &amp;lt;echo message="${operatingSystem}" /&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;br&gt;
On Windows 2000 with Service Pack 4, that will output "Microsoft Windows NT 5.0.2195 Service Pack 4"
&lt;br&gt;
On Windows XP with Service Pack 2, that will output "Microsoft Windows NT 5.1.2600 Service Pack 2"
&lt;br&gt;
On Windows 2003 with Service Pack 2, that will output "Microsoft Windows NT 5.2.3790 Service Pack 2"
&lt;br&gt;
So now, to test if the NAnt build file is running under Windows 2003, we simply use "string::contains":
&lt;pre class="xml" name="code"&gt;
&amp;lt;if test="${string::contains(operatingSystem, 'Microsoft Windows NT 5.2')}"&amp;gt;
  &amp;lt;echo message="This is Windows 2003" /&amp;gt;
&amp;lt;/if&amp;gt;
&lt;/pre&gt;
&lt;br&gt;
The complet NAnt build file to test the operating system should look like:
&lt;br&gt;
&lt;pre class="xml" name="code"&gt;
&amp;lt;project name="testOS" default="runTest" basedir="."&amp;gt;
  &amp;lt;property name="operatingSystem" value="${operating-system::to-string(environment::get-operating-system())}" /&amp;gt;

  &amp;lt;target name="runTest"&amp;gt;
    &amp;lt;if test="${string::contains(operatingSystem, 'Microsoft Windows NT 5.0')}"&amp;gt;
      &amp;lt;echo message="This is Windows 2000" /&amp;gt;
    &amp;lt;/if&amp;gt;

    &amp;lt;if test="${string::contains(operatingSystem, 'Microsoft Windows NT 5.1')}"&amp;gt;
      &amp;lt;echo message="This is Windows XP" /&amp;gt;
    &amp;lt;/if&amp;gt;

    &amp;lt;if test="${string::contains(operatingSystem, 'Microsoft Windows NT 5.2')}"&amp;gt;
      &amp;lt;echo message="This is Windows 2003" /&amp;gt;
    &amp;lt;/if&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3312463512384019662?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3312463512384019662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3312463512384019662' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3312463512384019662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3312463512384019662'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2008/01/nant-what-operating-system-is-this.html' title='NAnt, What Operating System is This?'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8151318142027376033</id><published>2007-11-27T08:52:00.001-05:00</published><updated>2008-01-30T21:00:13.484-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>NAnt Create SFX Archive Task</title><content type='html'>&lt;p&gt;I have been working on a installer for a .NET web application with a database back-end. The installer itself deserves a series of posts since it was fairly complicated to get everything to work. An integral part of the installer was using NAnt for various things. The final stage in creating the ready to deploy executable is packaging the files in a self-extracting archive that extracts and runs the setup. With the help of Winrar and NAnt, that task can be automated. Let's get started.

Requirements:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;WinRar 3.7 or higher (&lt;a href="http://www.rarsoft.com/" target="_blank"&gt;http://www.rarsoft.com&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;WinRar SFX options file (sample provided below) &lt;/li&gt;    &lt;li&gt;NAnt (&lt;a href="http://nant.sourceforge.net/" target="_blank"&gt;http://nant.sourceforge.net&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;NAnt build file (sample provided below) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;WinRar SFX options file sample:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;; The path to the setup executable
Setup=Setup.msi
; Extract the files to a temporary directory
TempMode
; Use semi-silent mode
Silent=2
; Overwrite any existing files
Overwrite=1
; The title of the SFX archive
Title=Sample Setup
; The text to show initially when the user clicks on the SFX archive (will only matter if using Silent=0)
Text
{
The installer will extract and run the setup
}&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;NAnt build file sample:&lt;/strong&gt;&lt;/p&gt;  &lt;pre class="xml" name="code"&gt;
&amp;lt;project name="SampleSFX" default="createSFX" basedir="."&amp;gt;
 &amp;lt;description&amp;gt;createSFX task for creating a sample self-extracting installer&amp;lt;/description&amp;gt;

 &amp;lt;!-- The name of the archive to be created --&amp;gt;
 &amp;lt;property name="archiveName" value="SampleSFX" overwrite="false" /&amp;gt;

 &amp;lt;!-- The target directory from where the build will be invoked --&amp;gt;
 &amp;lt;property name="targetDirectory" value="." overwrite="false" /&amp;gt;

 &amp;lt;!-- The relative path (from the targetDirectory) to directory containing the files to be archived --&amp;gt;
 &amp;lt;property name="archiveDirectory" value="&amp;lt;RelativePathToTheDirectoryToArchive&amp;gt;" overwrite="false"&amp;gt;

 &amp;lt;!-- The mask of the file extensions to be archived --&amp;gt;
 &amp;lt;property name="archiveFileMask" value="*.*" overwrite="false" /&amp;gt;

 &amp;lt;!-- The path to the winrar executable --&amp;gt;
 &amp;lt;property name="winrarPath" value="c:\program files\winrar\winrar.exe" overwrite="false" /&amp;gt;

 &amp;lt;!-- The winrar command line switches for creating the archive --&amp;gt;
 &amp;lt;property name="winrarSwitches" value="a -ep -ep1 -r -sfxdefault.sfx" overwrite="false" /&amp;gt;

 &amp;lt;!-- The name of the sfx options file to use while creating the archive --&amp;gt;
 &amp;lt;property name="sfxOptionsFile" value="sfxoptions.txt" overwrite="false" /&amp;gt;

 &amp;lt;!-- The relative path (from the targetDirectory) to icon file to be used for the created archive --&amp;gt;
 &amp;lt;property name="sfxIconFile" value="images\setupIcon.ico" overwrite="false" /&amp;gt;

 &amp;lt;property name="archiveDirectoryFullPath" value="${path::combine(path::get-full-path(targetDirectory), archiveDirectory)}" overwrite="true" /&amp;gt;
 &amp;lt;property name="sfxOptionsFileFullPath" value="${path::combine(path::get-full-path(targetDirectory), sfxOptionsFile)}" overwrite="true" /&amp;gt;
 &amp;lt;property name="sfxIconFileFullPath" value="${path::combine(path::get-full-path(targetDirectory), sfxIconFile)}" overwrite="true" /&amp;gt;

 &amp;lt;target name="createSFX" description="Creates the self-extracing installer archive"&amp;gt;
  &amp;lt;exec
  basedir="."
  program="${winrarPath}"
  commandline="${winrarSwitches} -z&amp;amp;quot;${sfxOptionsFileFullPath}&amp;amp;quot; -iicon&amp;amp;quot;${sfxIconFileFullPath}&amp;amp;quot; &amp;amp;quot;${archiveName}&amp;amp;quot; &amp;amp;quot;${archiveDirectoryFullPath}\${archiveFileMask}&amp;amp;quot;"
  workingdir="."
  failonerror="true" /&amp;gt;
 &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;To run this NAnt task:
&lt;ol&gt;&lt;li&gt;Open a command prompt in the &lt;strong&gt;targetDirectory&lt;/strong&gt; you specified in the above build file. &lt;/li&gt;&lt;li&gt;Run the build file with: nant -buildfile:&amp;lt;nameOfTheAboveBuildFile.build&amp;gt; &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This will create a single executable file. When the user runs the executable, the setup files will be extracted and the "Setup.msi" (or whatever you specified in the sfx options file) will be executed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8151318142027376033?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8151318142027376033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8151318142027376033' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8151318142027376033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8151318142027376033'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/11/nant-create-sfx-archive-task.html' title='NAnt Create SFX Archive Task'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3186922588376778628</id><published>2007-11-21T13:22:00.001-05:00</published><updated>2007-11-26T21:02:24.307-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Getting Enabled / Disabled Active Directory Accounts in ColdFusion and T-SQL</title><content type='html'>While working on recent telephone directory project based on Active Directory, it occurred to me that I am listing all users/accounts in Active Directory regardless of the fact that they might be disabled. Usually, my workplace disables a user's account once he/she is no longer working for the company. So here is how to get a list of only enabled or only disabled accounts from Active Directory. The examples cover doing this through ColdFusion's built in &amp;lt;cfldap&amp;gt; and using T-SQL syntax by leveraging Active Directory as a linked server. I have covered setting up Active Directory as a SQL Server linked server at &lt;a href="http://blog.tech-cats.com/2007/09/querying-active-directory-through-sql.html" target="_blank"&gt;Querying Active Directory Through SQL Server&lt;/a&gt;  Here is how this is done with a simple cfldap query. Before you run this code below, please replace the values in the &amp;lt;&amp;gt; This query gets the "distinguishedName", "givenName" and "sn" attributes from Active Directory. The complicated part is the filter it uses. Here is the breakdown:  &lt;ul&gt;   &lt;li&gt;(objectCategory=Person) tells cfldap to get only objects that match the category of "person" &lt;/li&gt;   &lt;li&gt;(objectClass=User) tells cfldap to get only objects that match the class of "user" &lt;/li&gt;   &lt;li&gt;(!(userAccountControl:1.2.840.113556.1.4.803:=2)) tells cfldap to get only objects for witch when a bitwise AND is applied to the "userAccountControl" attribute and the number 2, the result does not equal to 0. This is a bit complicated but what it means is that if the bitwise operations does not return 0, the account is not disabled. To specify that only &lt;strong&gt;disabled&lt;/strong&gt; accounts should be returned instead, we would use "(userAccountControl:1.2.840.113556.1.4.803:=2)" instead of "(!(userAccountControl:1.2.840.113556.1.4.803:=2))". I did not come up with this :-) &lt;a href="http://support.microsoft.com/kb/269181" target="_blank"&gt;Here&lt;/a&gt; is Microsoft's explanation on how to use bitwise filter.&lt;/li&gt;&lt;/ul&gt;
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfldap
 action="query"
 name="enabledADUsers"
 start="&amp;lt;replaceWithBaseDN&amp;gt;"
 server="&amp;lt;replaceWithActiveDirectoryServer&amp;gt;"
 username="&amp;lt;replaceWithDomainAccount&amp;gt;"
 password="&amp;lt;replaceWithDomainAccountPassword&amp;gt;"
 scope="subtree"
 filter="(&amp;amp;(objectCategory=Person)(objectClass=User)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
 attributes="distinguishedName,givenName,sn" timeout="0"&amp;gt;

&amp;lt;cfdump var="#enabledADUsers#" /&amp;gt;
&lt;/pre&gt;
Here is the same thing but done through a SQL Server linked server. The filter is the same but written with the T-SQL syntax. The differencs is in how the filter on the "userAccountControl" attribute is applied through T-SQL. In the code below, the line "userAccountControl &amp;amp; 2 = 0" is equvalent to the cfldap filter "(!(userAccountControl:1.2.840.113556.1.4.803:=2))" which specifies that only accounts that are not disabled should be returned in the query. To specify that only &lt;strong&gt;disabled&lt;/strong&gt; accounts should be returned instead, we would use "userAccountControl &amp;amp; 2 &lt;&gt; 0".
&lt;pre class="sql" name="code"&gt;
select userAccountControl,
 distinguishedName,
 givenName as firstName, sn as lastName,
from openquery(&amp;lt;replaceWithNameOfLinkedServer&amp;gt;, '
 select userAccountControl, distinguishedName, givenName, sn
 from ''LDAP://&amp;lt;replaceWithBaseDN&amp;gt;''
 where objectCategory = ''Person''
 and
 objectClass = ''user''
 order by sn
 ')
where userAccountControl &amp;amp; 2 = 0
&lt;/pre&gt;
Here are some links on the subject:
&lt;br /&gt;
&lt;a href="http://support.microsoft.com/kb/269181" target="_blank"&gt;How to query Active Directory by using a bitwise filter&lt;/a&gt;
&lt;br /&gt;
&lt;a href="http://support.microsoft.com/kb/305144" target="_blank"&gt;How to use the UserAccountControl flags to manipulate user account properties&lt;/a&gt;
&lt;br /&gt;
&lt;a href="http://www.microsoft.com/technet/scriptcenter/resources/qanda/may05/hey0512.mspx" target="_blank"&gt;How Can I Get a List of All the Disabled User Accounts in Active Directory?&lt;/a&gt;
&lt;br /&gt;
&lt;a href="http://jwcodespot.wordpress.com/2007/04/30/retrieving-basic-active-directory-account-settings" target="_blank"&gt;Retrieving Basic Active Directory Account Settings in C#&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3186922588376778628?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3186922588376778628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3186922588376778628' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3186922588376778628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3186922588376778628'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/11/getting-enabled-disabled-active.html' title='Getting Enabled / Disabled Active Directory Accounts in ColdFusion and T-SQL'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7540088201912018234</id><published>2007-11-14T06:37:00.001-05:00</published><updated>2007-11-26T20:45:24.647-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Useful Prototype.js String Functions</title><content type='html'>&lt;p&gt;Often while doing web development with JavaScript there is a need to do some kind of string manipulation. Some of the more common tasks are checking if the string is empty and replacing some parts of the string but it doesn't have to stop there. Sometimes I want to capitalize the first letter in a string or check if the string ends with a certain character. In the past I would have to write functions most often involving regular expressions to do each of those trivial tasks. Luckily, in the present my favorite JavaScript library Prototype.js already comes with the mentioned above plus a bunch more string functions. Here are some that I use often:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;empty() - checks if a string is empty
&lt;pre class="js" name="code"&gt;var myEmptyString = "";
if (myEmptyString.empty()) alert ('myEmptyString is empty');&lt;/pre&gt;&lt;/li&gt; &lt;li&gt;blank() - checks if a string is either empty or contains white space
 &lt;pre class="js" name="code"&gt;var myBlankString = " ";
if (myBlankString.blank()) alert ('myBlankString is blank');&lt;/pre&gt;&lt;/li&gt; &lt;li&gt;capitalize() - capitalizes the first letter in a string
 &lt;pre class="js" name="code"&gt;var myString = "lower_case_string";
// Will show an alert with "Lower_case_string"
alert(myString.capitalize());&lt;/pre&gt;&lt;/li&gt; &lt;li&gt;gsub(pattern, replacement) - replaces a pattern in the string with the string specified in 'replacement'
 &lt;pre class="js" name="code"&gt;var myString = "some_string";
// Will show an alert with "some string"
alert(myString.gsub('_', ' '));&lt;/pre&gt;&lt;/li&gt; &lt;li&gt;endsWith(substring) - checks if the specified string ends with the provided 'substring'
 &lt;pre class="js" name="code"&gt;var myString = "some string_";
// Will show an alert with "myString ends with _"
if (myString.endsWith('_')) alert('myString ends with _');&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;Many more can be found at the &lt;a href="http://prototypejs.org/api/string" target="_blank"&gt;Prototype API reference&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7540088201912018234?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7540088201912018234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7540088201912018234' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7540088201912018234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7540088201912018234'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/11/useful-prototypejs-string-functions.html' title='Useful Prototype.js String Functions'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3024667112875091479</id><published>2007-11-08T12:43:00.002-05:00</published><updated>2008-04-13T23:00:13.094-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Automation'/><category scheme='http://www.blogger.com/atom/ns#' term='NAnt'/><title type='text'>Getting Started with NAnt - .NET Build Tool</title><content type='html'>As part of working on a installer for .NET web application, I decided to use NAnt (stands for Not Ant) which is a .NET equivalent of the popular Java based ANT build tool. If you don't know what a build tool is, check out the &lt;a href="http://en.wikipedia.org/wiki/Build_tool" target="_blank"&gt;Build Tool article&lt;/a&gt; on Wikipedia. The beauty of NAnt is in the fact that you can automate many tasks and once you have a working build file, you do not have to worry about it again. Here is some of you can do with the help of NAnt:   &lt;ul&gt;   &lt;li&gt;Install and register ASP.NET with IIS without user intervention &lt;/li&gt;    &lt;li&gt;Start/stop/pause or install windows services &lt;/li&gt;    &lt;li&gt;Zip or unzip files &lt;/li&gt;    &lt;li&gt;Changes values inside text or xml files &lt;/li&gt;    &lt;li&gt;Create files and/or directories &lt;/li&gt;    &lt;li&gt;Copy/move files and/or directories &lt;/li&gt;    &lt;li&gt;Set directory and/or file security permissions &lt;/li&gt;    &lt;li&gt;Much more &lt;/li&gt;    &lt;li&gt;If that is not enough, you can always extend NAnt with your own custom tasks (written in VB.NET or C#) &lt;/li&gt; &lt;/ul&gt; That being said, here are the steps to get started with NAnt:   &lt;ol&gt;   &lt;li&gt;Get NAnt from &lt;a href="http://prdownloads.sourceforge.net/nant/nant-0.85-bin.zip?download"&gt;http://prdownloads.sourceforge.net/nant/nant-0.85-bin.zip?download&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Get NAntContrib from &lt;a href="http://prdownloads.sourceforge.net/nantcontrib/nantcontrib-0.85-bin.zip?download"&gt;http://prdownloads.sourceforge.net/nantcontrib/nantcontrib-0.85-bin.zip?download&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Extract NAnt in "C:\Program Files\NAnt"&lt;/li&gt;    &lt;li&gt;Extract NAntContrib\bin in "C:\Program Files\NAnt\bin" &lt;/li&gt;    &lt;li&gt;Create a NAnt.bat file in C:\Windows with the following:     &lt;br /&gt;@echo off      &lt;br /&gt;"C:\Program Files\NAnt\bin\nant.exe" %*&lt;/li&gt;    &lt;li&gt;Create and run a sample build file. Build files can perform many functions, from compiling your .NET application to downloading files from the net. For a list of Tasks, see the &lt;a href="http://nant.sourceforge.net/release/latest/help/tasks/" target="_blank"&gt;NAnt Tasks&lt;/a&gt; list and the &lt;a href="http://nantcontrib.sourceforge.net/release/latest/help/tasks/" target="_blank"&gt;NAntContrib Tasks&lt;/a&gt; list. &lt;/li&gt; &lt;/ol&gt; Below is a sample build file that takes a currently installed web application, pre-compilies it and creates a zip file of the pre-compiled application ready to be deployed:   &lt;pre class="xml" name="code"&gt;
&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;project name="Ensemble" default="deploy" basedir="." xmlns="http://nant.sf.net/schemas/nant.xsd"&amp;gt;
 &amp;lt;description&amp;gt;Precompiles and zips the Ensemble project&amp;lt;/description&amp;gt;

  &amp;lt;property name="debug" value="true" overwrite="true" /&amp;gt;

 &amp;lt;!-- The target directory where the application will be deployed and the zip file created --&amp;gt;
  &amp;lt;property name="targetDirectory" value="." overwrite="false" /&amp;gt;

 &amp;lt;!-- The temporary directory where the web application will be precompiled --&amp;gt;
  &amp;lt;property name="deployTarget" value="${path::combine(path::get-full-path(targetDirectory), 'deploy')}" overwrite="true" /&amp;gt;

  &amp;lt;!-- The virtual directory that the web application resides in --&amp;gt;
  &amp;lt;property name="virtualDirectory" value="webApplication" overwrite="true" /&amp;gt;

 &amp;lt;!-- The name of the zip file to create when zipping the deployed web application --&amp;gt;
  &amp;lt;property name="deployZipFilename" value="webApplication.zip" overwrite="true" /&amp;gt;

 &amp;lt;!-- The location where the zip file will be created --&amp;gt;
 &amp;lt;property name="deployZipFileLocation" value="${path::combine(path::get-full-path(targetDirectory), deployZipFilename)}" overwrite="true" /&amp;gt;

 &amp;lt;!-- The location of the .NET Framework directory (for version 2) --&amp;gt;
  &amp;lt;property name="dotnetLocation" value="${framework::get-framework-directory('net-2.0')}" overwrite="true" /&amp;gt;

  &amp;lt;!-- 'clean' target deletes the previously created zip file and deploy directory --&amp;gt;
  &amp;lt;target name="clean" description="Remove all generated files"&amp;gt;
  &amp;lt;!-- Delete the existing zip file --&amp;gt;
    &amp;lt;delete file="${deployZipFileLocation}" if="${file::exists(deployZipFileLocation)}" /&amp;gt;
  &amp;lt;!-- Delete the existing deploy directory --&amp;gt;
    &amp;lt;delete dir="${deployTarget}" if="${directory::exists(deployTarget)}" /&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!-- 'build' target precompiles this ASP.Net application into the deployTarget directory --&amp;gt;
  &amp;lt;target name="deploy" description="Precompiles the web application and creates a zip file for it" depends="clean"&amp;gt;
    &amp;lt;!-- Precompile the web application with the built-in .NET utility --&amp;gt;
    &amp;lt;exec
     basedir="."
     program="${dotnetLocation}\aspnet_compiler.exe"
     commandline="-nologo -fixednames -v ${virtualDirectory} &amp;quot;${deployTarget}&amp;quot;"
     workingdir="."
     failonerror="true" /&amp;gt;

    &amp;lt;!-- Clean up the "deployTarget" directory --&amp;gt;
  &amp;lt;delete&amp;gt;
   &amp;lt;fileset&amp;gt;
    &amp;lt;!-- Delete any visual studio related files --&amp;gt;
    &amp;lt;include name="${deployTarget}/*.TempSolution" /&amp;gt;
    &amp;lt;include name="${deployTarget}/**/*.scc" /&amp;gt;
    &amp;lt;include name="${deployTarget}/**/*.resx" /&amp;gt;
    &amp;lt;include name="${deployTarget}/**/*.txt" /&amp;gt;
    &amp;lt;include name="${deployTarget}/**/*.db" /&amp;gt;
    &amp;lt;include name="${deployTarget}/**/*.vssscc" /&amp;gt;
    &amp;lt;!-- Delete all the files in the upload and files directory --&amp;gt;
    &amp;lt;include name="${deployTarget}/upload/**/*" /&amp;gt;
    &amp;lt;include name="${deployTarget}/files/**/*" /&amp;gt;
   &amp;lt;/fileset&amp;gt;
  &amp;lt;/delete&amp;gt;

    &amp;lt;!-- Create a zip file from precompiled web application --&amp;gt;
    &amp;lt;zip zipfile="${deployZipFileLocation}" includeemptydirs="true"&amp;gt;
      &amp;lt;fileset basedir="${deployTarget}"&amp;gt;
        &amp;lt;include name="**/*" /&amp;gt;
      &amp;lt;/fileset&amp;gt;
    &amp;lt;/zip&amp;gt;

    &amp;lt;!-- delete the deployTarget directory --&amp;gt;
    &amp;lt;delete dir="${deployTarget}" /&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3024667112875091479?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3024667112875091479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3024667112875091479' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3024667112875091479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3024667112875091479'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/11/getting-started-with-nant-net-build.html' title='Getting Started with NAnt - .NET Build Tool'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4538412063808067251</id><published>2007-10-24T16:54:00.001-04:00</published><updated>2007-10-24T16:56:45.047-04:00</updated><title type='text'>I Knew I'm not a Nerd - My NerdTests Results</title><content type='html'>Whenever people would accuse me of being a nerd I always protested. I knew there was a line between nerds and geeks and here is my test scores to prove it:
&lt;a href="http://www.nerdtests.com/nt2ref.html"&gt;&lt;img src="http://www.nerdtests.com/images/badge/nt2/7f69249d24708672.png" alt="NerdTests.com says I'm a Cool Technology Geek. What are you? Click here!"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4538412063808067251?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4538412063808067251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4538412063808067251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4538412063808067251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4538412063808067251'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/i-knew-i-not-nerd-my-nerdtest-results.html' title='I Knew I&amp;#39;m not a Nerd - My NerdTests Results'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5962463016968297390</id><published>2007-10-18T15:37:00.001-04:00</published><updated>2008-01-29T16:16:30.961-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>SQL Server Script to Restore a Database from File</title><content type='html'>I frequently have to backup a database from the production machine and restore it in my testing environment. You can do this with SQL Server Enterprise Manager (or other similar tools) but it can get to be a pain if you have to it over and over again. So here is a script to the second part - restore a database from a file to sql server. For the first part, please see my related post called &lt;a href="http://blog.tech-cats.com/2007/10/sql-server-script-to-backup-database-to.html"&gt;SQL Server Script to Backup a Database to File&lt;/a&gt;. To use this script you need to: &lt;ol&gt; &lt;li&gt;Set the database name in the @databaseName variable to your database&lt;/li&gt; &lt;li&gt;Set the @restoreDirectory variable to the absolute directory path where the database backup is found&lt;/li&gt; &lt;li&gt;Run the script (with something like Query Analyzer)&lt;/li&gt; &lt;/ol&gt; The script will restore a backup of the specified database from the restore directory specified in the @restoreDirectory variable. It will look for a backup filename that consists of the database name, today's date and the '.bak' extension (example: myDatabase-10.18.2007.bak). &lt;br /&gt;&lt;br /&gt; Download the script from &lt;a href="http://tech-cats.net/blog/downloads/sql/SQLServerRestoreDatabaseFromFile.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/SQLServerRestoreDatabaseFromFile.txt&lt;/a&gt; &lt;pre class="sql" name="code"&gt;
-----------------------------------------------------------------
-- Restore database from file
-----------------------------------------------------------------
use master
go

declare @backupFileName varchar(100), @restoreDirectory varchar(100),
 @databaseDataFilename varchar(100), @databaseLogFilename varchar(100),
 @databaseDataFile varchar(100), @databaseLogFile varchar(100),
 @databaseName varchar(100), @execSql nvarchar(1000)

-- Set the name of the database to restore
set @databaseName = 'myDatabase'
-- Set the path to the directory containing the database backup
set @restoreDirectory = 'aboslute_path_to_restore_directory' -- such as 'c:\temp\'

-- Create the backup file name based on the restore directory, the database name and today's date
set @backupFileName = @restoreDirectory + @databaseName + '-' + replace(convert(varchar, getdate(), 110), '-', '.') + '.bak'

-- Get the data file and its path
select @databaseDataFile = rtrim([Name]),
 @databaseDataFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
 inner join
 master.dbo.sysfilegroups as groups
 on
 files.groupID = groups.groupID
where DBID = (
  select dbid
  from master.dbo.sysdatabases
  where [Name] = @databaseName
 )

-- Get the log file and its path
select @databaseLogFile = rtrim([Name]),
 @databaseLogFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
where DBID = (
  select dbid
  from master.dbo.sysdatabases
  where [Name] = @databaseName
 )
 and
 groupID = 0

print 'Killing active connections to the "' + @databaseName + '" database'

-- Create the sql to kill the active database connections
set @execSql = ''
select @execSql = @execSql + 'kill ' + convert(char(10), spid) + ' '
from master.dbo.sysprocesses
where db_name(dbid) = @databaseName
 and
 DBID &lt;&gt; 0
 and
 spid &lt;&gt; @@spid
exec (@execSql)

print 'Restoring "' + @databaseName + '" database from "' + @backupFileName + '" with '
print '  data file "' + @databaseDataFile + '" located at "' + @databaseDataFilename + '"'
print '  log file "' + @databaseLogFile + '" located at "' + @databaseLogFilename + '"'

set @execSql = '
restore database [' + @databaseName + ']
from disk = ''' + @backupFileName + '''
with
  file = 1,
  move ''' + @databaseDataFile + ''' to ' + '''' + @databaseDataFilename + ''',
  move ''' + @databaseLogFile + ''' to ' + '''' + @databaseLogFilename + ''',
  norewind,
  nounload,
  replace'

exec sp_executesql @execSql

exec('use ' + @databaseName)
go

-- If needed, restore the database user associated with the database
/*
exec sp_revokedbaccess 'myDBUser'
go

exec sp_grantdbaccess 'myDBUser', 'myDBUser'
go

exec sp_addrolemember 'db_owner', 'myDBUser'
go

use master
go
*/
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5962463016968297390?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5962463016968297390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5962463016968297390' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5962463016968297390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5962463016968297390'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/sql-server-script-to-restore-database.html' title='SQL Server Script to Restore a Database from File'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3309447066090475548</id><published>2007-10-17T12:23:00.001-04:00</published><updated>2008-01-29T16:18:32.034-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>SQL Server Script to Backup a Database to File</title><content type='html'>I frequently have to backup a database from the production machine and restore it in my testing environment. You can do this with SQL Server Enterprise Manager (or other similar tools) but it can get to be a pain if you have to it over and over again. So here is a script to do the first part - backup a database from a sql server to a file. For the second part, please see my related post called &lt;a href="http://blog.tech-cats.com/2007/10/sql-server-script-to-restore-database.html"&gt;SQL Server Script to Restore a Database from File&lt;/a&gt;. To use this script you need to: &lt;ol&gt; &lt;li&gt;Set the database name in the @databaseName variable to your database&lt;/li&gt; &lt;li&gt;Set the absolute path for the backup directory in the @backupDirectory variable to the directory where the backup will be created&lt;/li&gt; &lt;li&gt;Run the script (with something like Query Analyzer)&lt;/li&gt;&lt;/ol&gt; The script will create a backup of the specified database and put in the directory specified in the @backupDirectory variable. The actual backup name will be based on the database name, today's date and the '.bak' extension (example: myDatabase-10.17.2007.bak). &lt;br /&gt;&lt;br /&gt; Download the script from &lt;a href="http://tech-cats.net/blog/downloads/sql/SQLServerBackupDatabaseToFile.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/sql/SQLServerBackupDatabaseToFile.txt&lt;/a&gt; &lt;pre class="sql" name="code"&gt;
-----------------------------------------------------------------
-- Backup database to file
-----------------------------------------------------------------
declare @backupFileName varchar(100), @backupDirectory varchar(100),
 @databaseDataFilename varchar(100), @databaseLogFilename varchar(100),
 @databaseDataFile varchar(100), @databaseLogFile varchar(100),
 @databaseName varchar(100), @execSql varchar(1000)

-- Set the name of the database to backup
set @databaseName = 'myDatabase'
-- Set the path fo the backup directory on the sql server pc
set @backupDirectory = 'aboslute_path_to_backup_directory' -- such as 'c:\temp\'

-- Create the backup file name based on the backup directory, the database name and today's date
set @backupFileName = @backupDirectory + @databaseName + '-' + replace(convert(varchar, getdate(), 110), '-', '.') + '.bak'

-- Get the data file and its path
select @databaseDataFile = rtrim([Name]),
 @databaseDataFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
 inner join
 master.dbo.sysfilegroups as groups
 on
 files.groupID = groups.groupID
where DBID = (
  select dbid
  from master.dbo.sysdatabases
  where [Name] = @databaseName
 )

-- Get the log file and its path
select @databaseLogFile = rtrim([Name]),
 @databaseLogFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
where DBID = (
  select dbid
  from master.dbo.sysdatabases
  where [Name] = @databaseName
 )
 and
 groupID = 0

print 'Backing up "' + @databaseName + '" database to "' + @backupFileName + '" with '
print '  data file "' + @databaseDataFile + '" located at "' + @databaseDataFilename + '"'
print '  log file "' + @databaseLogFile + '" located at "' + @databaseLogFilename + '"'

set @execSql = '
backup database [' + @databaseName + ']
to disk = ''' + @backupFileName + '''
with
  noformat,
  noinit,
  name = ''' + @databaseName + ' backup'',
  norewind,
  nounload,
  skip'

exec(@execSql)
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3309447066090475548?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3309447066090475548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3309447066090475548' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3309447066090475548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3309447066090475548'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/sql-server-script-to-backup-database-to.html' title='SQL Server Script to Backup a Database to File'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8471274960913251294</id><published>2007-10-16T19:33:00.001-04:00</published><updated>2008-01-29T16:13:39.215-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='Updates'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Unzip with UTF Support in ColdFusion - Function Updates for v0.2</title><content type='html'>Due to some shortcommings, here is an update of the "unzipWithUTFSupport" function. The change log is below. You can get the update version at &lt;a href="http://tech-cats.net/blog/downloads/coldFusion/unzipWithUTFSupportUDF.txt" target="_blank"&gt;http://tech-cats.net/blog/downloads/coldFusion/unzipWithUTFSupportUDF.txt&lt;/a&gt; &lt;ul&gt; &lt;li&gt; Support for absolute paths relative to the root of the web site &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: destination = "/"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; Back slashes get converted to forward slashes &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: destination = "/test\blah" = "/test/blah"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; Better support for relative paths: &lt;blockquote&gt; - relative to the "destination" if one is specified &lt;/blockquote&gt; &lt;blockquote&gt; - relative to the name of the zip archive otherwise (which is used as the extract directory name) &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; Support for parent paths (relative to the executing script) &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: destination = "../test"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; Support for absolute paths &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: destination = "d:\webroot\test"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; All possible ways to define a path also apply to the "destination" key in the locationsByFileType structure &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: locationsByFileType.jpg.destination = "images\jpg"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; No need for file type sub structure if you only care for the path where the files will be extracted &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Example: locationsByFileType.xml = "images\jpg"&lt;/font&gt; &lt;/blockquote&gt; &lt;blockquote&gt; &lt;font color="#0000A0"&gt;Instead of: locationsByFileType.jpg.destination = "images\jpg"&lt;/font&gt; &lt;/blockquote&gt; &lt;/li&gt; &lt;li&gt; Corrected an omission in the build script that prevented all files from being extracted because of lower case or upper case file extensions &lt;/li&gt; &lt;li&gt; Renamed "overwriteDestination" to "deleteDestination" and set it to "false" by default &lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8471274960913251294?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8471274960913251294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8471274960913251294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8471274960913251294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8471274960913251294'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/unzip-with-utf-support-in-coldfusion_16.html' title='Unzip with UTF Support in ColdFusion - Function Updates for v0.2'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7089808261257917229</id><published>2007-10-16T10:02:00.001-04:00</published><updated>2007-10-16T10:02:38.206-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><title type='text'>DriverMax - Reinstall your Windows Drivers within Minutes</title><content type='html'>Why didn't anybody think of this before?! Reinstalling your hardware drivers can always be a pain when reinstalling Windows. This program aims to backup your installed drivers so when you have to reinstall Windows, you can easily restore your drivers from the backup.  &lt;a href="http://www.innovative-sol.com/drivermax/index.htm"&gt;DriverMax for Windows Vista and Windows XP - easily reinstall all your Windows drivers within a few minutes&lt;/a&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7089808261257917229?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7089808261257917229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7089808261257917229' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7089808261257917229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7089808261257917229'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/drivermax-reinstall-your-windows.html' title='DriverMax - Reinstall your Windows Drivers within Minutes'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8224935762638150982</id><published>2007-10-15T19:25:00.001-04:00</published><updated>2007-10-17T12:29:30.185-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Unzip with UTF Support in ColdFusion Curtosy of Ant via cfant</title><content type='html'>&lt;strong&gt;Update:&lt;/strong&gt; Function was updated to v0.2 (see &lt;a href="http://blog.tech-cats.com/2007/10/unzip-with-utf-support-in-coldfusion_16.html" target="_blank"&gt;Unzip with UTF Support in ColdFusion - Function Updates for v0.2&lt;/a&gt;) &lt;br /&gt;&lt;br /&gt; A fellow by the name of Ricardo Parente contacted me today about unzipping a zip file that contains files with special characters (to be more technical, the file names were using UTF8 encoding). Some filenames contained accents and/or other characters that would cause issues. He was trying to extract the zip file programmatically using the zip component from Alagad but that was throwing an exception. After looking around for a bit, turns out there is allready an existing user defined function on &lt;a href="http://www.cflib.org" target="_blank"&gt;cflib&lt;/a&gt; called &lt;a href="http://www.cflib.org/udf.cfm?id=997" target="_blank"&gt;unzipFile&lt;/a&gt;. However, it seems that suffered from the same problem as the Alagad component when trying to extract files with UTF8 encoding. So after some searching, I found that the UTF encoding issue is an issue with Java and has not be fixed for 6 years!! Bah! So anyway, it turns out Ant, does support that with no problem and forutnatelly ColdFusion MX 7 comes with the undocumented function "cfant". So here is the custom function to unzip those pesky zip files contained UTF encoded file names. Createvely, I've named it "unzipWithUTFSupport". You can call it as simple as: &lt;pre class="cf" name="code"&gt;
&amp;lt;cfset unzipResults = unzipWithUTFSupport("myUTFEncodedZipFile.zip") /&amp;gt;
&lt;/pre&gt;
or like so to specify the destination directory:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfset unzipResults = unzipWithUTFSupport(
	zipFile = "myUTFEncodedZipFile.zip",
	destination = "yourRelativeDestination"
) /&amp;gt;
&lt;/pre&gt;
This will return a structure with the following keys:
&lt;ul&gt;
	&lt;li&gt;antMessage = string with the message Ant returned&lt;/li&gt;
	&lt;li&gt;argumentErrors = array of argument validation errors&lt;/li&gt;
	&lt;li&gt;fileList = query of files unzipped&lt;/li&gt;
	&lt;li&gt;success = boolean indicating the success or the failure of the unzip process&lt;/li&gt;
&lt;/ul&gt;
Now, for the more advanced functionality. You can have the function unzip the different file types to different sub directores. For example ".jpg" files can go in a "images" sub directory, while ".xml" files can go in a "configuration" sub directory. To take advantage of this, you need to pass the function a structure with the argument name "extractLocationsByFileType". That structure will define how what file extentions wil be extracted where. Here is a sample configuration that will extract only ".jpg" files to a "images" sub diretory:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfset locationsByFileType = structnew() /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg = structnew() /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg.destination = "images" /&amp;gt;
&lt;/pre&gt;
Once you configure the "locationsByFileType" structure, you just pass it to the function like so:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfset results = unzipWithUTFSupport(
	zipFile = "myUTFEncodedZipFile.zip",
	extractLocationsByFileType = locationsByFileType
) /&amp;gt;
&lt;/pre&gt;
The important think to keep in mind is that, if you use this functionality, you will have to define the configurtion for each file type. This means that if you use the configuration above, only ".jpg" files will be extracted from the zip archive.

This will return a structure with the following keys:
&lt;ul&gt;
	&lt;li&gt;antMessage = string with the message Ant returned&lt;/li&gt;
	&lt;li&gt;argumentErrors = array of argument validation errors&lt;/li&gt;
	&lt;li&gt;fileList = a structure of queries with the unzipped files under each file extension&lt;/li&gt;
	&lt;li&gt;success = boolean indicating the success or the failure of the unzip process&lt;/li&gt;
&lt;/ul&gt;
There are a couple of optional parameters you can pass to the function. If you are not using the advanced feature defined above, you can also pass two more values to the function:
&lt;ul&gt;
	&lt;li&gt;specialCharsMatchRegEx = string with the regular expression that will match the special characters in the file names (by default "[^A-Za-z0-9\._\-]")&lt;/li&gt;
	&lt;li&gt;replaceSpecialChars = boolean indicating if special characters in the file names should be replaced (by default true)&lt;/li&gt;
&lt;/ul&gt;
If you are using the structure that defines specific file types to be extracted thenn you can specify specific setting for the "replaceSpecialChars" and "specialCharsMatchRegEx" for each file type as so:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfset locationsByFileType = structnew() /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg = structnew() /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg.destination = "images" /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg.replaceSpecialChars = false /&amp;gt;
&amp;lt;cfset locationsByFileType.jpg.specialCharsMatchRegEx = "[^A-Za-z0-9\._\-]" /&amp;gt;
&lt;/pre&gt;
Finally, here is the function code
&lt;pre class="cf" name="code"&gt;
&amp;lt;!---
Function:		unzipWithUTFSupport
Created on:		10.15.2007
Author:			Boyan Kostadinov
Version:		0.1
Arguments:		zipFile (string) required
				The name of the zip file to extract

				destination (string)
				The relative destination directory to extract the zip to (by default ".")

				overwriteDestination (boolean)
				Should the destination directory to be overwritte (by default true)

				extractLocationsByFileType (struct)
				A structure containing the type of files to be extracted
				and their destinations (by default empty structure)

				Example:
				&amp;lt;cfset locationsByFileType.jpg = structnew() /&amp;gt;

				Specify the relative destination where to extract this type of files
				&amp;lt;cfset locationsByFileType.jpg.destination = "jpgFilesDir" /&amp;gt;

				Should special characters be replaced for this type of files
				&amp;lt;cfset locationsByFileType.jpg.replaceSpecialChars = true /&amp;gt;

				The regular expression to match special characters against
				&amp;lt;cfset locationsByFileType.jpg.specialCharsMatchRegEx = "[^A-Za-z0-9\._\-]" /&amp;gt;

				If "replaceSpecialChars" and "specialCharsMatchRegEx" do not exist, the default
				values in the functions are used (true and "[^A-Za-z0-9\._\-]")

				replaceSpecialChars (boolean)
				Should special characters in the file names be replaced (by default true)

				specialCharsMatchRegEx (string)
				The regular expression that will match the special characters in the file names
				that need to replaced (by default "[^A-Za-z0-9\._\-]")

Return Value:	unzipResults (struct)
				A structure containing the results of the unzip process with the keys:
				success (boolean)
					the sucess of the unzip
				antMessage (string)
					the message the unzip task returns
				fileList (struct)
					the list of files/directories unzipped
Description:	I extract a zip file no matter of encoding with the help of Ant
---&amp;gt;
&amp;lt;cffunction name="unzipWithUTFSupport" hint="I extract a zip file no matter of encoding with the help of Ant" returntype="struct"&amp;gt;
	&amp;lt;cfargument name="zipFile" type="string" required="yes" /&amp;gt;
	&amp;lt;cfargument name="destination" type="string" required="no" default="." /&amp;gt;
	&amp;lt;cfargument name="overwriteDestination" type="boolean" required="no" default="true" /&amp;gt;
	&amp;lt;cfargument name="extractLocationsByFileType" type="struct" required="no" default="#structnew()#" /&amp;gt;
	&amp;lt;cfargument name="replaceSpecialChars" type="boolean" required="no" default="true" /&amp;gt;
	&amp;lt;cfargument name="specialCharsMatchRegEx" type="string" required="no" default="[^A-Za-z0-9\._\-]" /&amp;gt;

	&amp;lt;!--- Create local variables for the zip file name and the destination directory ---&amp;gt;
	&amp;lt;cfset var zipFileName = "" /&amp;gt;
	&amp;lt;cfset var unzipDestination = "" /&amp;gt;
	&amp;lt;cfset var uniqueUnzipDestinationDirectory = "" /&amp;gt;
	&amp;lt;cfset var unzipResults = structnew() /&amp;gt;
	&amp;lt;cfset var buildMessage = "" /&amp;gt;
	&amp;lt;cfset var currentDir = "" /&amp;gt;
	&amp;lt;cfset var fileRenamed = false /&amp;gt;

	&amp;lt;!--- Set the name of the temporary ant build file ---&amp;gt;
	&amp;lt;cfset var buildFile = expandpath("unzip.xml") /&amp;gt;

	&amp;lt;cfset unzipResults.success = false /&amp;gt;
	&amp;lt;cfset unzipResults.antMessage = "" /&amp;gt;
	&amp;lt;cfset unzipResults.fileList = 0 /&amp;gt;
	&amp;lt;cfset unzipResults.argumentErrors = arraynew(1) /&amp;gt;

	&amp;lt;!--- Set the name of the zip file to extract ---&amp;gt;
	&amp;lt;cfif arguments.zipFile neq ""&amp;gt;
		&amp;lt;cfset zipFileName = expandPath(arguments.zipFile) /&amp;gt;

		&amp;lt;cfif not fileExists(zipFileName)&amp;gt;
			&amp;lt;cfset arrayappend(unzipResults.argumentErrors, "The zip file #arguments.zipFile# was not found") /&amp;gt;
		&amp;lt;/cfif&amp;gt;
	&amp;lt;cfelse&amp;gt;
		&amp;lt;cfset arrayappend(unzipResults.argumentErrors, "The zip file was not specified") /&amp;gt;
	&amp;lt;/cfif&amp;gt;

	&amp;lt;!--- Set the extract destination ---&amp;gt;
	&amp;lt;cfif arguments.destination neq ""&amp;gt;
		&amp;lt;cfset unzipDestination = expandPath(arguments.destination) /&amp;gt;
	&amp;lt;cfelse&amp;gt;
		&amp;lt;cfset arrayappend(unzipResults.argumentErrors, "Destination was empty") /&amp;gt;
	&amp;lt;/cfif&amp;gt;

	&amp;lt;!--- If there were not argument validation errors ---&amp;gt;
	&amp;lt;cfif arrayisempty(unzipResults.argumentErrors)&amp;gt;
		&amp;lt;!--- Create a directory for the zip file based on the name of the zip archive ---&amp;gt;
		&amp;lt;cfset uniqueUnzipDestinationDirectory =
			unzipDestination &amp; "\" &amp;
			rereplacenocase(arguments.zipFile, "\.zip$", "") /&amp;gt;

		&amp;lt;cfdump var="#uniqueUnzipDestinationDirectory#" /&amp;gt;
		&amp;lt;!--- Create the xml string for the ant build file ---&amp;gt;
		&amp;lt;cfoutput&amp;gt;
		&amp;lt;!--- If the "extractLocationsByFileType" structure is not empty, loop over it
		to extract the different files types to the specified sub directory ---&amp;gt;
		&amp;lt;cfsavecontent variable="unzipXml"&amp;gt;
		&amp;lt;project&amp;gt;
			&amp;lt;target name="unzip"&amp;gt;
				&amp;lt;cfif not structisempty(extractLocationsByFileType)&amp;gt;
					&amp;lt;cfloop list="#structKeyList(extractLocationsByFileType)#" index="key"&amp;gt;
						&amp;lt;cfif isstruct(extractLocationsByFileType[key])&amp;gt;
				&amp;lt;unzip src="#zipFileName#" dest="#uniqueUnzipDestinationDirectory#\#lcase(extractLocationsByFileType[key].destination)#"&amp;gt;
					&amp;lt;patternset&amp;gt;
						&amp;lt;include name="**/*.#lcase(key)#"/&amp;gt;
					&amp;lt;/patternset&amp;gt;
				&amp;lt;/unzip&amp;gt;
						&amp;lt;cfelse&amp;gt;
				&amp;lt;unzip src="#zipFileName#" dest="#uniqueUnzipDestinationDirectory#\#lcase(extractLocationsByFileType[key])#"&amp;gt;
					&amp;lt;patternset&amp;gt;
						&amp;lt;include name="**/*.#lcase(key)#"/&amp;gt;
					&amp;lt;/patternset&amp;gt;
				&amp;lt;/unzip&amp;gt;
						&amp;lt;/cfif&amp;gt;
					&amp;lt;/cfloop&amp;gt;
				&amp;lt;cfelse&amp;gt;
				&amp;lt;unzip src="#zipFileName#" dest="#uniqueUnzipDestinationDirectory#" /&amp;gt;
				&amp;lt;/cfif&amp;gt;
			&amp;lt;/target&amp;gt;
		&amp;lt;/project&amp;gt;
		&amp;lt;/cfsavecontent&amp;gt;
		&amp;lt;/cfoutput&amp;gt;

		&amp;lt;cftry&amp;gt;
			&amp;lt;!--- If the destination directory already exists, delete it ---&amp;gt;
			&amp;lt;cfif directoryExists(uniqueUnzipDestinationDirectory) and arguments.overwriteDestination&amp;gt;
				&amp;lt;cfdirectory action="delete" directory="#uniqueUnzipDestinationDirectory#" recurse="yes" /&amp;gt;
			&amp;lt;/cfif&amp;gt;

			&amp;lt;!--- Write the temporary ant build file on the file system ---&amp;gt;
			&amp;lt;cffile action="write" nameconflict="overwrite" file="#buildFile#" output="#unzipXml#" /&amp;gt;
		
			&amp;lt;!--- Execute the ant task with the created ant build file ---&amp;gt;
			&amp;lt;!--- "messages" holds the coldfusion variable to write the ant output to ---&amp;gt;
			&amp;lt;!--- "target" is the name of the "defaultTarget" (ant speak) to execute when runing the ant task ---&amp;gt;
			&amp;lt;cfant buildFile="#buildFile#"
				defaultDirectory=""
				anthome=""
				messages="buildMessage"
				target="unzip"
			/&amp;gt;

			&amp;lt;cfif refindnocase(".*unable to expand to file.*", buildMessage)&amp;gt;
				&amp;lt;cfset unzipResults.success = false /&amp;gt;
			&amp;lt;cfelseif refindnocase(".*build successful.*", buildMessage)&amp;gt;
				&amp;lt;cfset unzipResults.success = true /&amp;gt;
			&amp;lt;/cfif&amp;gt;

			&amp;lt;cfset unzipResults.antMessage = buildMessage /&amp;gt;

			&amp;lt;!--- Delete the temporary ant build file ---&amp;gt;
			&amp;lt;cffile action="delete" file="#buildFile#" /&amp;gt;

			&amp;lt;cfif unzipResults.success&amp;gt;
				&amp;lt;cfif not structisempty(extractLocationsByFileType)&amp;gt;
					&amp;lt;cfset unzipResults.fileList = structnew() /&amp;gt;
	
					&amp;lt;cfloop list="#structKeyList(extractLocationsByFileType)#" index="key"&amp;gt;
						&amp;lt;cfif isstruct(extractLocationsByFileType[key])&amp;gt;
							&amp;lt;cfset currentDir =
							uniqueUnzipDestinationDirectory &amp; "\" &amp;
							extractLocationsByFileType[key].destination /&amp;gt;
	
							&amp;lt;cfif structkeyexists(extractLocationsByFileType[key], "replaceSpecialChars")&amp;gt;
								&amp;lt;cfif isboolean(extractLocationsByFileType[key].replaceSpecialChars)&amp;gt;
									&amp;lt;cfset replaceSpecialChars = extractLocationsByFileType[key].replaceSpecialChars /&amp;gt;
								&amp;lt;/cfif&amp;gt;
							&amp;lt;/cfif&amp;gt;
	
							&amp;lt;cfif replaceSpecialChars&amp;gt;
								&amp;lt;cfif structkeyexists(extractLocationsByFileType[key], "specialCharsMatchRegEx")&amp;gt;
									&amp;lt;cfset specialCharsMatchRegEx = extractLocationsByFileType[key].specialCharsMatchRegEx /&amp;gt;
								&amp;lt;/cfif&amp;gt;
							&amp;lt;/cfif&amp;gt;
						&amp;lt;cfelse&amp;gt;
							&amp;lt;cfset currentDir = uniqueUnzipDestinationDirectory &amp; "\" &amp;
							extractLocationsByFileType[key] /&amp;gt;
						&amp;lt;/cfif&amp;gt;
	
						&amp;lt;!--- Get a list of the files in the directory ---&amp;gt;
						&amp;lt;cfdirectory
							action="list"
							directory="#currentDir#" name="currentFileList" /&amp;gt;
	
						&amp;lt;cfset fileRenamed = false /&amp;gt;
	
						&amp;lt;cfif replaceSpecialChars&amp;gt;
							&amp;lt;!--- Loop over all the files ---&amp;gt;
							&amp;lt;cfloop query="currentFileList"&amp;gt;
								&amp;lt;!--- If the filename has special characters ---&amp;gt;
								&amp;lt;cfif refind(specialCharsMatchRegEx, name)&amp;gt;
									&amp;lt;!--- Create a new name for the file by replacing all special characters with "_" ---&amp;gt;
									&amp;lt;cfset newName = rereplace(name, specialCharsMatchRegEx, "_", "all") /&amp;gt;
				
									&amp;lt;!--- Rename the file to the new name ---&amp;gt;
									&amp;lt;cffile
										action="rename"
										source="#directory#\#name#"
										destination="#directory#\#newName#" /&amp;gt;
	
									&amp;lt;cfset fileRenamed = true /&amp;gt;
								&amp;lt;/cfif&amp;gt;
							&amp;lt;/cfloop&amp;gt;
						&amp;lt;/cfif&amp;gt;
	
						&amp;lt;cfif fileRenamed&amp;gt;
							&amp;lt;!--- Get a list of the files in the directory
						(again since some files might have been renamed) ---&amp;gt;
							&amp;lt;cfdirectory
								action="list"
								directory="#currentDir#" name="currentFileList" /&amp;gt;
						&amp;lt;/cfif&amp;gt;
	
						&amp;lt;cfset unzipResults.fileList[key] = currentFileList /&amp;gt;
					&amp;lt;/cfloop&amp;gt;
				&amp;lt;cfelse&amp;gt;
					&amp;lt;!--- Get a list of the files in the directory ---&amp;gt;
					&amp;lt;cfdirectory
						action="list"
						directory="#uniqueUnzipDestinationDirectory#" name="currentFileList" /&amp;gt;
	
					&amp;lt;cfset fileRenamed = false /&amp;gt;
					&amp;lt;cfif arguments.replaceSpecialChars and specialCharsMatchRegEx neq ""&amp;gt;
						&amp;lt;!--- Loop over all the files ---&amp;gt;
						&amp;lt;cfloop query="currentFileList"&amp;gt;
							&amp;lt;!--- If the filename has special characters ---&amp;gt;
							&amp;lt;cfif refind(specialCharsMatchRegEx, name)&amp;gt;
								&amp;lt;!--- Create a new name for the file by replacing all special characters with "_" ---&amp;gt;
								&amp;lt;cfset newName = rereplace(name, specialCharsMatchRegEx, "_", "all") /&amp;gt;
			
								&amp;lt;!--- Rename the file to the new name ---&amp;gt;
								&amp;lt;cffile
									action="rename"
									source="#directory#\#name#"
									destination="#directory#\#newName#" /&amp;gt;
	
								&amp;lt;cfset fileRenamed = true /&amp;gt;
							&amp;lt;/cfif&amp;gt;
						&amp;lt;/cfloop&amp;gt;
					&amp;lt;/cfif&amp;gt;
	
					&amp;lt;cfif fileRenamed&amp;gt;
						&amp;lt;!--- Get a list of the files in the directory
						(again since some files might have been renamed) ---&amp;gt;
						&amp;lt;cfdirectory
							action="list"
							directory="#uniqueUnzipDestinationDirectory#" name="currentFileList" /&amp;gt;
					&amp;lt;/cfif&amp;gt;
	
					&amp;lt;cfset unzipResults.fileList = currentFileList /&amp;gt;
				&amp;lt;/cfif&amp;gt;
			&amp;lt;/cfif&amp;gt;
		&amp;lt;cfcatch type="any"&amp;gt;
			&amp;lt;cfdump var="#cfcatch#" /&amp;gt;
		&amp;lt;/cfcatch&amp;gt;
		&amp;lt;/cftry&amp;gt;
	&amp;lt;/cfif&amp;gt;

	&amp;lt;cfreturn unzipResults /&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;/pre&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8224935762638150982?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8224935762638150982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8224935762638150982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8224935762638150982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8224935762638150982'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/unzip-with-utf-support-in-coldfusion.html' title='Unzip with UTF Support in ColdFusion Curtosy of Ant via cfant'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7773964862628870030</id><published>2007-10-12T14:25:00.001-04:00</published><updated>2007-10-12T14:27:30.487-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Get a User's Primary Group Membership from Active Directory with ColdFusion</title><content type='html'>Recently, I've had to do much work with Active Directory/LDAP. I needed a way to grab the user's primary group so I can set some permissions in my application based on the primary group the user is a member of. This turned out to be a bit tricky since the primary group for each user is not part of the list of groups the user is a member of. Instead, the primary group token (just an ID) is stored in each user's record. Seems pretty simple now that I got it working but there was a big lack of documentation on how to do this in ColdFusion. So here is the psudo code: &lt;ol&gt; &lt;li&gt;We need to query Active Directory and get the value of the "primaryGroupID" for the selected user&lt;/li&gt; &lt;li&gt;We also need a full list of groups in Active Directory (this is acheived with using the filter "(&amp;amp;(objectcategory=group))")&lt;/li&gt; &lt;li&gt;Next, we need to get the group name from the full list of groups based on the primary group token we got from the user's record&lt;/li&gt; &lt;li&gt;Bingo!&lt;/li&gt; &lt;/ol&gt; Here is the code: &lt;pre class="cf" name="code"&gt;
&amp;lt;!--- Get the primary group id for an example user ---&amp;gt;
&amp;lt;cfldap
	action="query"
	name="userLdapQuery"
	start="dc=ica,dc=com"
	server="ldapServer"
	username="ldapUser"
	password="secretPassword"
	scope="subtree"
	filter="sAMAccountName=bkostadinov"
	attributes="primaryGroupID"
	timeout="0"
	maxrows="1" /&amp;gt;

&amp;lt;!--- Query the ldap server for the full list of groups ---&amp;gt;
&amp;lt;cfldap
	action="query"
	name="groupsQuery"
	start="dc=ica,dc=com"
	server="ldapServer"
	username="ldapUser"
	password="secretPassword"
	scope="subtree"
	filter="(&amp;(objectcategory=group))"
	attributes="primaryGroupToken,name"
	timeout="0" /&amp;gt;

&amp;lt;!--- Beacause the list of groups the user belongs to,
does not contain the user's primary group, query the
ldap groups to get only the group name for witch
the value of the primaryGroupTokenAttribute
matches the value of the primaryGroupIDAttribute ---&amp;gt;
&amp;lt;cfquery name="primaryGroupQuery" dbtype="query"&amp;gt;
select	lower(name) as name
from	groupsQuery
where	primaryGroupToken = '#userLdapQuery.primaryGroupID#'
&amp;lt;/cfquery&amp;gt;

&amp;lt;!--- Get the primary group name from the query resutls ---&amp;gt;
&amp;lt;cfset primaryGroup = primaryGroupQuery["name"][1] /&amp;gt;
&lt;/pre&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7773964862628870030?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7773964862628870030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7773964862628870030' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7773964862628870030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7773964862628870030'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/get-user-primary-group-membership-from.html' title='Get a User&amp;#39;s Primary Group Membership from Active Directory with ColdFusion'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7672940151842387527</id><published>2007-10-11T13:31:00.001-04:00</published><updated>2007-10-11T13:31:07.262-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><title type='text'>Must Have Tools for Windows Power Users</title><content type='html'>&lt;p&gt;This is a list of must have tools with inspiration from blog post at &lt;a href="http://www.nodans.com/index.cfm/2007/10/10/Dana-Kowalski-sez-Crack-Open-your-Toolbox-and-Share"&gt;http://www.nodans.com/index.cfm/2007/10/10/Dana-Kowalski-sez-Crack-Open-your-Toolbox-and-Share&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Launchy: &lt;a href="http://www.launchy.net/"&gt;http://www.launchy.net/&lt;/a&gt; - An open source keystroke launcher for Windows    &lt;br /&gt;XYPlorer: &lt;a href="http://www.xyplorer.com"&gt;http://www.xyplorer.com&lt;/a&gt; - A windows file manager and explorer replacement    &lt;br /&gt;Hamachi: &lt;a href="http://hamachi.cc/download/list.php"&gt;http://hamachi.cc/download/list.php&lt;/a&gt; - Software based VPN    &lt;br /&gt;FolderShare: &lt;a href="http://www.foldershare.com"&gt;http://www.foldershare.com&lt;/a&gt; - Sync files/directories between multiple computers    &lt;br /&gt;RoboForm: &lt;a href="http://www.roboform.com"&gt;http://www.roboform.com&lt;/a&gt; - An automated form filer and password manager    &lt;br /&gt;Altiris Software Virtualization: &lt;a href="http://www.svsdownloads.com"&gt;http://www.svsdownloads.com&lt;/a&gt; - A virtual engine for applications    &lt;br /&gt;Paint.NET: &lt;a href="http://www.svsdownloads.com"&gt;http://www.svsdownloads.com&lt;/a&gt; - Free image and photo editing software    &lt;br /&gt;Quest Comparison Suite for SQL Server: &lt;a href="http://www.quest.com/Comparison-Suite-for-SQL-Server"&gt;http://www.quest.com/Comparison-Suite-for-SQL-Server&lt;/a&gt; - Free Microsoft SQL server comparison suite&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7672940151842387527?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7672940151842387527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7672940151842387527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7672940151842387527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7672940151842387527'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/must-have-tools-for-windows-power-users.html' title='Must Have Tools for Windows Power Users'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5378382428477293491</id><published>2007-10-09T21:29:00.001-04:00</published><updated>2007-10-09T21:30:27.742-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Neat Prototype Trick - Activate First Form Element Without a Certain Class Name</title><content type='html'>Let's say you have form with a bunch of fields that you have disabled with the "read only" attribute so the user can't change the data. Also, you have applied a css class called "readOnlyInput" so you can style the input field as read only field (different color or whatever else you like). I had such form this evening but I wanted the focus to automatically go to the first non read only element when the page is loaded. Usually, you can pass focus on a form element by doing this:
&lt;pre class="js" name="code"&gt;
// 'myFormField' is the id of form field you want to focus on
$('myFormField').focus();
&lt;/pre&gt;
However, if the input field already contains data, you might want to focus the field and highlight it in the same time. In that case you will do:
&lt;pre class="js" name="code"&gt;
// 'myFormField' is the id of form field you want to focus on
$('myFormField').activate();
&lt;/pre&gt;
That is all fine and great but what when I have a bunch of input elements and some of them might be marked "read only". To make things more complicated (as I love to do), I would hate to hard code the id of the first element I want to focus/activate. So here is the solution:
&lt;pre class="js" name="code"&gt;
// For each input element on the form
$A($('myForm').getInputs()).each(function(formElement) {
 // If the form element does not have the class "readOnlyInput"
 if (!$(formElement).hasClassName('readOnlyInput')) {
  // Activate that element
  $(formElement).activate();
  // Break out of the loop (prototype specific syntax here)
  throw $break;
 }
});
&lt;/pre&gt;

Just so Doug's kids would understand this, here it is in psudo code:
&lt;ol&gt;
&lt;li&gt;Get a list of form input elements by using Prototype's built in "getInputs" function
$('myForm').getInputs()
&lt;/li&gt;
&lt;li&gt;Convert the list of form inputs to a Prototype array
$A($('myForm').getInputs())
&lt;/li&gt;
&lt;li&gt;Now for each of the elements in the array, run a function pass in the current element
$A($('myForm').getInputs()).each(function(formElement) 
&lt;/li&gt;
&lt;li&gt;If the current form element has a  css class not matching "readOnlyInput"
if (!$(formElement).hasClassName('readOnlyInput')) 
&lt;/li&gt;
&lt;li&gt;Activate that form element
$(formElement).activate();
&lt;/li&gt;
&lt;li&gt;We found the first element so break out of the loop
throw $break;
&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5378382428477293491?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5378382428477293491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5378382428477293491' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5378382428477293491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5378382428477293491'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/neat-prototype-trick-activate-first.html' title='Neat Prototype Trick - Activate First Form Element Without a Certain Class Name'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-9156948370108122610</id><published>2007-10-08T12:46:00.000-04:00</published><updated>2007-10-08T12:52:09.233-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion CFC Scope Exploration</title><content type='html'>Doug Boude's post at &lt;a href="http://www.dougboude.com/blog/1/2007/10/Appropriate-Usage-of-the-THIS-Scope.cfm" target="_blank"&gt;http://www.dougboude.com/blog/1/2007/10/Appropriate-Usage-of-the-THIS-Scope.cfm&lt;/a&gt;, prompted me to create this simple test that should show the difference between using the "this" scope, the "variables" scope and the "var" scope. Here is what  you need to get things setup.
Declare a test component as follows:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfcomponent displayname="thisScopeToUseOrNotToUse"&amp;gt;
 &amp;lt;cffunction name="testMethod"&amp;gt;
  &amp;lt;!--- Create a variable in the local scope of the function ---&amp;gt;
  &amp;lt;cfset var iAmAccessableOnlyWithinThisMethod = true /&amp;gt;

  &amp;lt;!--- Create a variable in the "this" scope ---&amp;gt;
  &amp;lt;cfset this.iAmAccessableFromOutside = true /&amp;gt;

  &amp;lt;!--- Create variable in the private component scope ---&amp;gt;
  &amp;lt;cfset variables.iAmAccessableOnlyWithinThisCFC = true /&amp;gt;
 &amp;lt;/cffunction&amp;gt;

 &amp;lt;cffunction name="getIAmAccessableOnlyWithinThisCFCButCanBeViewedFromTheOutsideWithAPublicMethod"&amp;gt;
  &amp;lt;cfreturn variables.iAmAccessableOnlyWithinThisCFC /&amp;gt;
 &amp;lt;/cffunction&amp;gt;
&amp;lt;/cfcomponent&amp;gt;
&lt;/pre&gt;
Then declare a test file as follows:
&lt;pre class="cf" name="code"&gt;
&amp;lt;cfset testCFC = createObject("component", "thisScopeToUseOrNotToUse") /&amp;gt;
&amp;lt;cfset testCFC.testMethod() /&amp;gt;
=======================================
&amp;lt;p /&amp;gt;
Try to read a variable declare in the "this" scope of the component
&amp;lt;p /&amp;gt;
&amp;lt;strong&amp;gt;iAmAccessableFromOutside:&amp;lt;/strong&amp;gt;
&amp;lt;cfdump var="#testCFC.iAmAccessableFromOutside#" /&amp;gt;
&amp;lt;p /&amp;gt;
=======================================
&amp;lt;p /&amp;gt;
Try to read a variable declared in the private component scope (the &amp;quot;variables&amp;quot; scope)
&amp;lt;p /&amp;gt;
&amp;lt;strong&amp;gt;iAmAccessableOnlyWithinThisCFC:&amp;lt;/strong&amp;gt;
&amp;lt;cftry&amp;gt;
 &amp;lt;cfdump var="#testCFC.iAmAccessableOnlyWithinThisCFC#" /&amp;gt;
&amp;lt;cfcatch type="any"&amp;gt;
 &amp;lt;cfdump var="#cfcatch.message#" /&amp;gt;
&amp;lt;/cfcatch&amp;gt;
&amp;lt;/cftry&amp;gt;
&amp;lt;p /&amp;gt;
=======================================
&amp;lt;p /&amp;gt;
Using a public method to read a variable in the private component scope (the &amp;quot;variables&amp;quot; scope):
&amp;lt;p /&amp;gt;
&amp;lt;strong&amp;gt;getIAmAccessableOnlyWithinThisCFCButCanBeViewedFromTheOutsideWithAPublicMethod:&amp;lt;/strong&amp;gt;
&amp;lt;cfoutput&amp;gt;#testCFC.getIAmAccessableOnlyWithinThisCFCButCanBeViewedFromTheOutsideWithAPublicMethod()#&amp;lt;/cfoutput&amp;gt;
&amp;lt;p /&amp;gt;
=======================================
&amp;lt;p /&amp;gt;
&amp;lt;strong&amp;gt;Trying to read a variable declared only in the method scope:
&amp;lt;p /&amp;gt;
iAmAccessableOnlyWithinThisMethod:&amp;lt;/strong&amp;gt;
&amp;lt;cftry&amp;gt;
 &amp;lt;cfdump var="#testCFC.iAmAccessableOnlyWithinThisMethod#" /&amp;gt;
&amp;lt;cfcatch type="any"&amp;gt;
 &amp;lt;cfdump var="#cfcatch.message#" /&amp;gt;
&amp;lt;/cfcatch&amp;gt;
&amp;lt;/cftry&amp;gt;
&lt;/pre&gt;
Here are the results:
&lt;a href="http://www.flickr.com/photos/boyank/1516782724/" title="Photo Sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2190/1516782724_2bf436f30b_o.jpg" alt="ColdFusion &amp;quot;this&amp;quot; Scope Test" height="259" width="875" /&gt;&lt;/a&gt;
Now, for the explanation:
&lt;ol&gt;
&lt;li&gt;First we create a instance of the compontent with "createObject"&lt;/li&gt;
&lt;li&gt;Call the "testMethod" of the component so we can set the variables&lt;/li&gt;
&lt;li&gt;Then we try to access the "iAmAccessableFromOutside" variable and get "true" since that was the value set to the variable in the "testMethod" function&lt;/li&gt;
&lt;li&gt;Next, we try to read a variable declared in the private component scope "iAmAccessableOnlyWithinThisCFC". The code block is wrapped with "cfcatch" so we get a nice error message when ColdFusion cannot access the privately declare variable&lt;/li&gt;
&lt;li&gt;However, we can use the method "getIAmAccessableOnlyWithinThisCFCButCanBeViewedFromTheOutsideWithAPublicMethod" which just returns the private scope variable "iAmAccessableOnlyWithinThisCFC"&lt;/li&gt;
&lt;li&gt;Lastly, we try to access the variable "iAmAccessableOnlyWithinThisMethod" which was declared in the private "var" scope of the "testMethod" function.  The code block is wrapped with "cfcatch" so we get a nice error message when ColdFusion cannot access the privately declare variable&lt;/li&gt;
&lt;/il&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-9156948370108122610?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/9156948370108122610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=9156948370108122610' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9156948370108122610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9156948370108122610'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/coldfusion-cfc-scope-exploration.html' title='ColdFusion CFC Scope Exploration'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-9031303531507295613</id><published>2007-10-05T14:47:00.001-04:00</published><updated>2007-10-11T16:35:09.247-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Web Page Syntax Highlighting for ColdFusion - Brush for SyntaxHighlighter</title><content type='html'>I have been working on a implementing a solution to highlight ColdFusion code snippets when they are being posted on your web site/blog. Highlighting the code according to the appropriate language can make it much easier to read and comprehend (and make it pretty of course). To do this, I have created a ColdFusion syntax "brush" for the JavaScript highlighter &lt;a href="http://code.google.com/p/syntaxhighlighter/" target="_blank"&gt;SyntaxHighlighter&lt;/a&gt; (formally dp.SyntaxHighlighter). In this context, a "brush" is a set of language specific settings for highlighting/prettifying code. SyntaxHighlighter is a pretty cool piece of software and I had some fun and faced some challenges while trying to create ColdFusion specific highlighting brush. Here is a demo of the highlighter at work when given ColdFusion code snippet: &lt;pre class="cf" name="code"&gt;
&amp;lt;cfcomponent displayname="applicationController" extends="ModelGlue.unity.controller.Controller" output="false"&amp;gt;

&amp;lt;cfscript&amp;gt;
// Set component variables
variables.appConfig = 0;
variables.modelGlueConfig = 0;
variables.rolePermissions = structnew();
variables.userIDWithAdminRights = "";
&amp;lt;/cfscript&amp;gt;

&amp;lt;!---
Function: name="changeUserSiteRole"
Created on: 09.25.2007
Updated on: 09.25.2007
Author: Boyan Kostadinov
Arguments: event(ModelGlue.Core.Event)
Return Value: none
Description:
---&amp;gt;
&amp;lt;cffunction name="changeUserSiteRole" access="public" returntype="void" output="false"&amp;gt;
 &amp;lt;cfargument name="event" type="ModelGlue.Core.Event"&amp;gt;
 &amp;lt;cfset var userID = arguments.event.getValue("userID", 0) /&amp;gt;
 &amp;lt;cfset var siteID = arguments.event.getValue("siteID", 0) /&amp;gt;
 &amp;lt;cfset var roleID = arguments.event.getValue("roleID", 0) /&amp;gt;
 &amp;lt;cfset var showAllUsers = arguments.event.getValue("showAllUsers", false) /&amp;gt;
&lt;br /&gt;
 &amp;lt;cfif userID neq 0 and siteID neq 0 and roleID neq 0&amp;gt;
  &amp;lt;!--- Call the changeUserSiteRole method in the UsersGateway to change the user's
  role in the specified siteID ---&amp;gt;
  &amp;lt;cfset variables.usersGateway.changeUserSiteRole(userID, siteID, roleID) /&amp;gt;
 &amp;lt;/cfif&amp;gt;

&lt;br /&gt; &amp;lt;cfif showAllUsers&amp;gt;
  &amp;lt;cfset arguments.event.addResult("allUsers") /&amp;gt;
 &amp;lt;cfelse&amp;gt;
  &amp;lt;cfset arguments.event.addResult("singleUser") /&amp;gt;
 &amp;lt;/cfif&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;br /&gt;
&amp;lt;cffunction name="onQueueComplete" access="public" returntype="void" output="false"&amp;gt;
 &amp;lt;cfargument name="event" type="any"&amp;gt;
&lt;br /&gt; &amp;lt;cfset arguments.event.setValue("defaultEvent", getModelGlue().getBean("modelGlueConfiguration").getdefaultEvent()) /&amp;gt;
 &amp;lt;cfset arguments.event.setValue("appConfig", variables.appConfig) /&amp;gt;
 &amp;lt;cfset arguments.event.setValue("ApplicationVersion", variables.appConfig.GetConfigSetting("ApplicationVersion")) /&amp;gt;
 &amp;lt;cfset arguments.event.setValue("ApplicationLastRevisionDate", variables.appConfig.GetConfigSetting("ApplicationLastRevisionDate")) /&amp;gt;
 &amp;lt;cfset arguments.event.setValue("urlPrefix", variables.defaultTemplate &amp;amp; "?" &amp;amp; arguments.event.getValue("eventValue") &amp;amp; "=") /&amp;gt;
 &amp;lt;cfset arguments.event.setValue("CurrentPageUrl", getfilefrompath(cgi.script_name) &amp;amp; "?" &amp;amp; cgi.query_string) /&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;br /&gt;
&amp;lt;cffunction name="onRequestEnd" access="public" returntype="void" output="false"&amp;gt;
 &amp;lt;cfargument name="event" type="any"&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;br /&gt;
&amp;lt;/cfcomponent&amp;gt;
&lt;/pre&gt;
To install the SyntaxHighlighter on your page:
&lt;ol&gt;&lt;li&gt;Get it &lt;a href="http://code.google.com/p/syntaxhighlighter/" target="_blank"&gt;http://code.google.com/p/syntaxhighlighter/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract it somewhere accessable from the web&lt;/li&gt;
&lt;li&gt;Add the following code&lt;pre class="js" name="code"&gt;
&amp;lt;!-- Include the SyntaxHighlighter stylesheet --&amp;gt;
&amp;lt;style type="text/css" media="screen"&amp;gt;@import url("pathToSyntaxHighlighterStyle/syntaxHighlighter.css");&amp;lt;/style&amp;gt;
&amp;lt;!-- Include the core SyntaxHighlighter library --&amp;gt;
&amp;lt;script language="javascript" src="pathToSyntaxHighlighter/scripts/shCore.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;!-- Include the ColdFusion brush --&amp;gt;
&amp;lt;script language="javascript" src="pathToSyntaxHighlighter/scripts/shBrushColdFusion.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript"&amp;gt;
window.onload = function () {
 // Set the path to the flash component to enable 'copy to clipboard' in firefox
 dp.SyntaxHighlighter.ClipboardSwf = 'pathToSyntaxHighlighter/scripts/clipboard.swf';
 // Enable blogger mode (if using Blogger)
 dp.SyntaxHighlighter.BloggerMode();
 // Highlight page elements with the name "code"
 // For configuration options see http://code.google.com/p/syntaxhighlighter/wiki/HighlightAll
 dp.SyntaxHighlighter.HighlightAll('code', false, true, false, 1, false);
}
&amp;lt;/script&gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Modify the css for your preferences (Firebug is really handy here to figure out what classes you want to modify). Here are my changes: &lt;pre class="css" name="code"&gt;
&amp;lt;style type="text/css"&amp;gt;
.dp-highlighter ol li, .dp-highlighter .columns div { padding: 0px 3px 0px 0px  !important; font-size: 12px !important; font-family: 'Lucida Console', 'Bitstream Vera Sans Mono', 'Courier New', Monaco, Courier, monospace; }
.dp-highlighter .tools { padding-left: 0px; }
.dp-highlighter .tools a { color: #000; text-decoration: underline; }
.dp-highlighter .tools a:hover { margin-right: 10px; }
&amp;lt;/style&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Add some more brushes. For supported languages are C++, C#, CSS, Delphi, Java, JavaScript, PHP, Pythod, Ruby, SQL, VB, XML, HTML, XLST and now ColdFusion :-). More information on the languages at &lt;a href="http://code.google.com/p/syntaxhighlighter/wiki/Languages" targe="_blank"&gt;http://code.google.com/p/syntaxhighlighter/wiki/Languages&lt;/a&gt;.Here are the brushes I am using:&lt;pre class="js" name="code"&gt;
&amp;lt;script language="javascript" src="scripts/shBrushCSharp.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="scripts/shBrushCss.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="scripts/shBrushJScript.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="scripts/shBrushSql.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="scripts/shBrushVb.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="scripts/shBrushXml.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Post your code enclosed in "&amp;lt;pre&gt;" tags as follows:&lt;pre class="xml" name="code"&gt;
&amp;lt;!-- For xml/html/xslt code --&amp;gt;
&amp;lt;pre class="xml" name="code"&amp;gt;
&amp;lt;!-- For css code --&amp;gt;
&amp;lt;pre class="css" name="code"&amp;gt;
&amp;lt;!-- For coldfusion code --&amp;gt;
&amp;lt;pre class="cf" name="code"&amp;gt;
&amp;lt;!-- For sql code --&amp;gt;
&amp;lt;pre class="sql" name="code"&amp;gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;
What the ColdFusion brush does:
&lt;ol&gt;&lt;li&gt;Highlights ColdFusion functions, tags, attributes, strings, numbers, comments, cfscript comments&lt;/li&gt;
&lt;li&gt;Highlights a very limited set of Model-Glue specific keywords (I got adventures)&lt;/li&gt;
&lt;li&gt;Uses the Dreamweaver color shema to apply the syntax highlighting&lt;/li&gt;&lt;/ol&gt;
How to use it and/or modify it:
&lt;ol&gt;&lt;li&gt;To just use it (without modifications), just include the compressed version from the svn location at &lt;a href="http://opensourceprojects.googlecode.com/svn/dpSyntaxHighlighterColdFusionBrush/trunk/compressed/shBrushColdFusion.js" target="_blank"&gt;http://opensourceprojects.googlecode.com/svn/dpSyntaxHighlighterColdFusionBrush/trunk/compressed/shBrushColdFusion.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;To use it but modify the css styles, get the uncompressed version from &lt;a href="http://opensourceprojects.googlecode.com/svn/dpSyntaxHighlighterColdFusionBrush/trunk/compressed/shBrushColdFusion.js" target="_blank"&gt;http://opensourceprojects.googlecode.com/svn/dpSyntaxHighlighterColdFusionBrush/trunk/uncompressed/shBrushColdFusion.js&lt;/a&gt; and modify the css definitions in "this.Style"&lt;/li&gt;
&lt;li&gt;Include it as a brush in your page:&lt;pre class="js" name="code"&gt;
&amp;lt;script language="javascript" src="pathTo_shBrushColdFusion.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;
Here is actual brush definiton file (highlighted with the JavaScript SyntaxHighlighter brush):&lt;pre class="js" name="code"&gt;
dp.sh.Brushes.ColdFusion = function()
{
 this.CssClass = 'dp-coldfusion';
 this.Style = '.dp-coldfusion { font: 13px "Courier New", Courier, monospace; }' +
 '.dp-coldfusion .tag, .dp-coldfusion .tag-name { color: #990033; }' +
 '.dp-coldfusion .attribute { color: #990033; }' +
 '.dp-coldfusion .attribute-value { color: #0000FF; }' +
 '.dp-coldfusion .cfcomments { background-color: #FFFF99; color: #000000; }' +
 '.dp-coldfusion .cfscriptcomments { color: #999999; }' +
 '.dp-coldfusion .keywords { color: #0000FF; }' +
 '.dp-coldfusion .mgkeywords { color: #CC9900; }' +
 '.dp-coldfusion .numbers { color: #ff0000; }' +
 '.dp-coldfusion .strings { color: green; }';

 this.mgKeywords = 'setvalue getvalue addresult viewcollection viewstate';

 this.keywords = 'var eq neq gt gte lt lte not and or true false ' +
 'abs acos addsoaprequestheader addsoapresponseheader ' +
 'arrayappend arrayavg arrayclear arraydeleteat arrayinsertat ' +
 'arrayisempty arraylen arraymax arraymin arraynew ' +
 'arrayprepend arrayresize arrayset arraysort arraysum ' +
 'arrayswap arraytolist asc asin atn binarydecode binaryencode ' +
 'bitand bitmaskclear bitmaskread bitmaskset bitnot bitor bitshln ' +
 'bitshrn bitxor ceiling charsetdecode charsetencode chr cjustify ' +
 'compare comparenocase cos createdate createdatetime createobject ' +
 'createobject createobject createobject createobject createodbcdate ' +
 'createodbcdatetime createodbctime createtime createtimespan ' +
 'createuuid dateadd datecompare dateconvert datediff dateformat ' +
 'datepart day dayofweek dayofweekasstring dayofyear daysinmonth ' +
 'daysinyear de decimalformat decrementvalue decrypt decryptbinary ' +
 'deleteclientvariable directoryexists dollarformat duplicate encrypt ' +
 'encryptbinary evaluate exp expandpath fileexists find findnocase ' +
 'findoneof firstdayofmonth fix formatbasen generatesecretkey ' +
 'getauthuser getbasetagdata getbasetaglist getbasetemplatepath ' +
 'getclientvariableslist getcontextroot getcurrenttemplatepath ' +
 'getdirectoryfrompath getencoding getexception getfilefrompath ' +
 'getfunctionlist getgatewayhelper gethttprequestdata gethttptimestring ' +
 'getk2serverdoccount getk2serverdoccountlimit getlocale ' +
 'getlocaledisplayname getlocalhostip getmetadata getmetricdata ' +
 'getpagecontext getprofilesections getprofilestring getsoaprequest ' +
 'getsoaprequestheader getsoapresponse getsoapresponseheader ' +
 'gettempdirectory gettempfile gettemplatepath gettickcount ' +
 'gettimezoneinfo gettoken hash hour htmlcodeformat htmleditformat ' +
 'iif incrementvalue inputbasen insert int isarray isbinary isboolean ' +
 'iscustomfunction isdate isdebugmode isdefined isk2serverabroker ' +
 'isk2serverdoccountexceeded isk2serveronline isleapyear islocalhost ' +
 'isnumeric isnumericdate isobject isquery issimplevalue issoaprequest ' +
 'isstruct isuserinrole isvalid isvalid isvalid iswddx isxml ' +
 'isxmlattribute isxmldoc isxmlelem isxmlnode isxmlroot javacast ' +
 'jsstringformat lcase left len listappend listchangedelims listcontains ' +
 'listcontainsnocase listdeleteat listfind listfindnocase listfirst ' +
 'listgetat listinsertat listlast listlen listprepend listqualify ' +
 'listrest listsetat listsort listtoarray listvaluecount ' +
 'listvaluecountnocase ljustify log log10 lscurrencyformat lsdateformat ' +
 'lseurocurrencyformat lsiscurrency lsisdate lsisnumeric lsnumberformat ' +
 'lsparsecurrency lsparsedatetime lsparseeurocurrency lsparsenumber ' +
 'lstimeformat ltrim max mid min minute month monthasstring now ' +
 'numberformat paragraphformat parameterexists parsedatetime pi ' +
 'preservesinglequotes quarter queryaddcolumn queryaddrow querynew ' +
 'querysetcell quotedvaluelist rand randomize randrange refind ' +
 'refindnocase releasecomobject removechars repeatstring replace ' +
 'replacelist replacenocase rereplace rereplacenocase reverse right ' +
 'rjustify round rtrim second sendgatewaymessage setencoding ' +
 'setlocale setprofilestring setvariable sgn sin spanexcluding ' +
 'spanincluding sqr stripcr structappend structclear structcopy ' +
 'structcount structdelete structfind structfindkey structfindvalue ' +
 'structget structinsert structisempty structkeyarray structkeyexists ' +
 'structkeylist structnew structsort structupdate tan timeformat ' +
 'tobase64 tobinary toscript tostring trim ucase urldecode urlencodedformat ' +
 'urlsessionformat val valuelist week wrap writeoutput xmlchildpos ' +
 'xmlelemnew xmlformat xmlgetnodetype xmlnew xmlparse xmlsearch xmltransform ' +
 'xmlvalidate year yesnoformat';

 // Array to hold the possible string matches
 this.stringMatches = new Array();
 this.attributeMatches = new Array();
}

dp.sh.Brushes.ColdFusion.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ColdFusion.Aliases = ['coldfusion', 'cf'];

dp.sh.Brushes.ColdFusion.prototype.ProcessRegexList = function()
{
 function push(array, value)
 {
  array[array.length] = value;
 }

 function find(array, element)
 {
  for(var i = 0; i &lt; array.length; i++){
   if(array[i] == element){
    return i;
   }
  }

  return -1;
 }

 var match = null;
 var regex = null;

 // Match numbers
 // (\\d+)
 this.GetMatches(new RegExp('\\b(\\d+)', 'gm'), 'numbers');

 // Match mg keywords
 this.GetMatches(new RegExp(this.GetKeywords(this.mgKeywords), 'igm'), 'mgkeywords');

 // Match single line comments via the built in single line regex (for cfscript)
 this.GetMatches(dp.sh.RegexLib.SingleLineCComments, 'cfscriptcomments');

 // Match multi line comments via the built in multi line regex (for cfscript)
 this.GetMatches(dp.sh.RegexLib.MultiLineCComments, 'cfscriptcomments');

 // Match tag based comments (including multiline comments)
 // (\&amp;lt;|&amp;lt;)!---[\\s\\S]*?---(\&amp;gt;|&amp;gt;)
 this.GetMatches(new RegExp('(\&amp;lt;|&amp;lt;)!---[\\s\\S]*?---(\&amp;gt;|&amp;gt;)', 'gm'), 'cfcomments');

 // Match attributes and their values excluding cfset tags
 // (cfset\\s*)?([:\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\')*
 regex = new RegExp('(cfset\\s*)?([:\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\')*', 'gm');
 while((match = regex.exec(this.code)) != null)
 {
  // If there is match in element 1 (the tag is cfset), continute to the next match
  if (match[1] != undefined &amp;&amp; match[1] != '')
  {
   continue;
  }

  // Add the atribute to the matches only if it has a matching value (dbtype="query")
  // and the match is not an empty string
  if (match[3] != undefined &amp;&amp; match[3] != '' &amp;&amp; match[3] != '""' &amp;&amp; match[3] != "''")
  {
   push(this.matches, new dp.sh.Match(match[2], match.index, 'attribute'));
   push(this.matches, new dp.sh.Match(match[3], match.index + match[0].indexOf(match[3]), 'attribute-value'));
   // Add the attribute value to the array of string matches
   push(this.stringMatches, match[3]);

   // Add the attribute to the array of attribute matches
   push(this.attributeMatches, match[2]);
  }
 }

 // Match opening and closing tag brackets
 // (\&amp;lt;|&amp;lt;)/*\?*(?!\!)|/*\?*(\&amp;gt;|&amp;gt;)
 this.GetMatches(new RegExp('(\&amp;lt;|&amp;lt;)/*\\?*(?!\\!)|/*\\?*(\&amp;gt;|&amp;gt;)', 'gm'), 'tag');

 // Match tag names
 // (\&amp;lt;|&lt;)/*\?*\s*(\w+)
 regex = new RegExp('(?:\&amp;lt;|&lt;)/*\\?*\\s*([:\\w-\.]+)', 'gm');
 while((match = regex.exec(this.code)) != null)
 {
  push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'tag-name'));
 }

 // Match keywords
 regex = new RegExp(this.GetKeywords(this.keywords), 'igm');
 while((match = regex.exec(this.code)) != null)
 {
  // if a match exists (there is a value for the attribute)
  if (find(this.attributeMatches, match[0]) == -1)
  {
   push(this.matches, new dp.sh.Match(match[0], match.index, 'keywords'));
  }
 }

 // Match cfset tags and quoated attributes
 regex = new RegExp('cfset\\s*.*(".*?"|\'.*?\')', 'gm');
 while((match = regex.exec(this.code)) != null)
 {
  // if a match exists (there is a value for the attribute)
  if(match[1] != undefined &amp;&amp; match[1] != '')
  {
   push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'strings'));

   // Add the attribute to the array of string matches
   push(this.stringMatches, match[1]);
  }
 }

 // Match string enclosed in double quoats
 while((match = dp.sh.RegexLib.DoubleQuotedString.exec(this.code)) != null)
 {
  //if (this.stringMatches.indexOf(match[0]) == -1)
  if (find(this.stringMatches, match[0]) == -1)
   push(this.matches, new dp.sh.Match(match[0], match.index, 'strings'));
 }

 // Match string enclosed in single quoats
 while((match = dp.sh.RegexLib.SingleQuotedString.exec(this.code)) != null)
 {
  //if (this.stringMatches.indexOf(match[0]) == -1)
  if (find(this.stringMatches, match[0]) == -1)
   push(this.matches, new dp.sh.Match(match[0], match.index, 'strings'));
 }
}
&lt;/pre&gt;
Questions/comments? You can leave a comment here or use my &lt;a href="http://boyan.tech-cats.com/contact.php"&gt;contact form&lt;/a&gt; to send me your thoughts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-9031303531507295613?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/9031303531507295613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=9031303531507295613' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9031303531507295613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/9031303531507295613'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/syntax-highlighting-for-coldfusion.html' title='Web Page Syntax Highlighting for ColdFusion - Brush for SyntaxHighlighter'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4147961903775678570</id><published>2007-10-05T13:38:00.001-04:00</published><updated>2007-10-05T13:46:05.933-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Full List of ColdFusion Functions (according to DW)</title><content type='html'>Yesterday I needed a full list of ColdFusion functions for my syntax highlighting. What easier  way to get that list than using your IDE?! I found the functions under the dreamweaver directory, in the file "configuration\CodeHints\CodeHints.hml". After some regex matching with the following pattern:
&lt;pre class="html" name="code"&gt;&amp;lt;function name="code" html? pattern="(\w+).*&amp;gt;&lt;/pre&gt;
and replacing with the following pattern:
&lt;pre class="html" name="code"&gt;$1&lt;/pre&gt;
Here is the list of ColdFusion functions that I got:
&lt;pre class="coldfusion" name="code"&gt;
Abs ACos AddSOAPRequestHeader AddSOAPResponseHeader ArrayAppend ArrayAvg ArrayClear
ArrayDeleteAt ArrayInsertAt ArrayIsEmpty ArrayLen ArrayMax ArrayMin ArrayNew
ArrayPrepend ArrayResize ArraySet ArraySort ArraySum ArraySwap ArrayToList
Asc ASin Atn BinaryDecode BinaryEncode BitAnd BitMaskClear BitMaskRead BitMaskSet
BitNot BitOr BitSHLN BitSHRN BitXor Ceiling CharsetDecode CharsetEncode Chr
Cjustify Compare CompareNoCase Cos CreateDate CreateDateTime CreateObject
CreateObject CreateObject CreateObject CreateObject CreateODBCDate
CreateODBCDateTime CreateODBCTime CreateTime CreateTimeSpan CreateUUID
DateAdd DateCompare DateConvert DateDiff DateFormat DatePart Day DayOfWeek
DayOfWeekAsString DayOfYear DaysInMonth DaysInYear DE DecimalFormat DecrementValue
Decrypt DecryptBinary DeleteClientVariable DirectoryExists DollarFormat Duplicate
Encrypt EncryptBinary Evaluate Exp ExpandPath FileExists Find FindNoCase FindOneOf
FirstDayOfMonth Fix FormatBaseN GenerateSecretKey GetAuthUser GetBaseTagData
GetBaseTagList GetBaseTemplatePath GetClientVariablesList GetContextRoot
GetCurrentTemplatePath GetDirectoryFromPath GetEncoding GetException GetFileFromPath
GetFunctionList GetGatewayHelper GetHTTPRequestData GetHTTPTimeString
GetK2ServerDocCount GetK2ServerDocCountLimit GetLocale GetLocaleDisplayName
GetLocalHostIP GetMetaData GetMetricData GetPageContext GetProfileSections
GetProfileString GetSOAPRequest GetSOAPRequestHeader GetSOAPResponse
GetSOAPResponseHeader GetTempDirectory GetTempFile GetTemplatePath GetTickCount
GetTimeZoneInfo GetToken Hash Hour HTMLCodeFormat HTMLEditFormat IIf IncrementValue
InputBaseN Insert Int IsArray IsBinary IsBoolean IsCustomFunction IsDate IsDebugMode
IsDefined IsK2ServerABroker IsK2ServerDocCountExceeded IsK2ServerOnline IsLeapYear
IsLocalHost IsNumeric IsNumericDate IsObject IsQuery IsSimpleValue IsSOAPRequest
IsStruct IsUserInRole IsValid IsValid IsValid IsWDDX IsXML IsXMLAttribute IsXMLDoc
IsXMLElem IsXMLNode IsXMLRoot JavaCast JSStringFormat LCase Left Len ListAppend
ListChangeDelims ListContains ListContainsNoCase ListDeleteAt ListFind ListFindNoCase
ListFirst ListGetAt ListInsertAt ListLast ListLen ListPrepend ListQualify ListRest
ListSetAt ListSort ListToArray ListValueCount ListValueCountNoCase LJustify Log
Log10 LSCurrencyFormat LSDateFormat LSEuroCurrencyFormat LSIsCurrency LSIsDate
LSIsNumeric LSNumberFormat LSParseCurrency LSParseDateTime LSParseEuroCurrency
LSParseNumber LSTimeFormat LTrim Max Mid Min Minute Month MonthAsString Now
NumberFormat ParagraphFormat ParameterExists ParseDateTime Pi PreserveSingleQuotes
Quarter QueryAddColumn QueryAddRow QueryNew QuerySetCell QuotedValueList Rand
Randomize RandRange REFind REFindNoCase ReleaseCOMObject RemoveChars RepeatString
Replace ReplaceList ReplaceNoCase REReplace REReplaceNoCase Reverse Right RJustify
Round RTrim Second SendGatewayMessage SetEncoding SetLocale SetProfileString
SetVariable Sgn Sin SpanExcluding SpanIncluding Sqr StripCR StructAppend StructClear
StructCopy StructCount StructDelete StructFind StructFindKey StructFindValue StructGet
StructInsert StructIsEmpty StructKeyArray StructKeyExists StructKeyList StructNew
StructSort StructUpdate Tan TimeFormat ToBase64 ToBinary ToScript ToString Trim UCase
URLDecode URLEncodedFormat URLSessionFormat Val ValueList Week Wrap WriteOutput
XMLChildPos XMLElemNew XMLFormat XMLGetNodeType XMLNew XMLParse XMLSearch XMLTransform
XMLValidate Year YesNoFormat
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4147961903775678570?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4147961903775678570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4147961903775678570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4147961903775678570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4147961903775678570'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/full-list-of-coldfusion-functions.html' title='Full List of ColdFusion Functions (according to DW)'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6750901599264862403</id><published>2007-10-03T11:57:00.001-04:00</published><updated>2007-10-03T12:48:14.510-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='Debuggin'/><title type='text'>Readable ModelGlue Debugging Output while using CSS Layout</title><content type='html'>&lt;p&gt;If you have your application layout done with CSS, most likely ModelGlue debugging output looks something like the picture below.&lt;a title="Model-Glue Debbuging without CSS" href="http://www.flickr.com/photos/13087518@N00/1477869264/"&gt;    
&lt;/a&gt;&lt;a title="ModelGlue Debugging with CSS Layouts" href="http://www.flickr.com/photos/13087518@N00/1477830540/"&gt;&lt;img alt="ModelGlue Debugging with CSS Layouts" src="http://static.flickr.com/1035/1477830540_615ab0f725_m.jpg" border="0" /&gt;&lt;/a&gt;     
Overlaying the debug output with your application styles can make it a bit unreadable. So here is a tip. Get and install the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/60" target="_blank"&gt;Web Developer&lt;/a&gt; extension if you don't have it already. Once installed (and you restarted Firefox), go to the "CSS" menu and under "Disable Styles", click on "All Styles" (or use the shortcut key "Ctrl+Shift+S"). Here is a screen shot of doing so:   
&lt;a href="http://lh6.google.com/boyank/RwO77Huy8AI/AAAAAAAAACU/dFyPEX9a77E/disable_css%5B3%5D.png"&gt;&lt;img id="id" style="border: 0px none ;" alt="disable_css" src="http://lh6.google.com/boyank/RwO78Huy8BI/AAAAAAAAACc/RB7G0V6Z3DM/disable_css_thumb%5B1%5D.png" border="0" height="183" width="644" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you use Internet Explorer instead of Firefox, you can use the same thing with the &lt;a href="https://www.microsoft.com/downloads/details.aspx?familyid=E59C3964-672D-4511-BB3E-2D5E1DB91038&amp;amp;displaylang=en" target="_blank"&gt;Internet Explored Developer Toolbar&lt;/a&gt; by going to the "Disable" menu and click on "All CSS". Here is a screen shot of doing so:   
&lt;a href="http://lh5.google.com/boyank/RwO783uy8CI/AAAAAAAAACk/kGkBxJiopII/ie%5B3%5D.png"&gt;&lt;img id="id" style="border: 0px none ;" alt="ie" src="http://lh6.google.com/boyank/RwO79Huy8DI/AAAAAAAAACs/jhDiwgertJw/ie_thumb%5B1%5D.png" border="0" height="179" width="644" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now your ModelGlue debugging output should look much cleaner and readable:  
&lt;img alt="Model-Glue Debbuging without CSS" src="http://static.flickr.com/1359/1477869264_c85847ea40_m.jpg" border="0" /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6750901599264862403?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6750901599264862403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6750901599264862403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6750901599264862403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6750901599264862403'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/readable-modelglue-debugging-output.html' title='Readable ModelGlue Debugging Output while using CSS Layout'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2816205289066529475</id><published>2007-10-03T07:52:00.001-04:00</published><updated>2007-10-03T07:52:12.554-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Free'/><title type='text'>Free Ruby on Rails E-Book</title><content type='html'>&lt;p&gt;   &lt;br /&gt;&lt;a href="http://www.sitepoint.com" target="_blank"&gt;Sitepoint.com&lt;/a&gt; is offering a free Ruby on Rails book called &amp;quot;Build Your Own Ruby on Rails Web Applications&amp;quot; by Patrick Lenz.    &lt;br /&gt;    &lt;br /&gt;You can download the book in PDF format from the address    &lt;br /&gt;&lt;a href="http://media.sitepoint.com/books/ror.pdf" target="_blank"&gt;http://media.sitepoint.com/books/ror.pdf&lt;/a&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2816205289066529475?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2816205289066529475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2816205289066529475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2816205289066529475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2816205289066529475'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/free-ruby-on-rails-e-book.html' title='Free Ruby on Rails E-Book'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5933328332170221323</id><published>2007-10-02T19:01:00.001-04:00</published><updated>2007-10-05T11:43:50.318-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Prototype.js Object Initialization and Bind While Enumerating Arrays</title><content type='html'>&lt;p&gt;If the title sounds confusing, that is because it is. I couldn't figure out a better way to describe the issue I was running into. Let see if I can better demonstrate. I have a "initialize" function defined in my JavaScript object as such:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
initialize: function() {
// siteID contains a list of ids such as "1,2,3,4"
// Convert the id list in siteIDs to a prototype array $A(siteIDs) and
// for each element in the array, run a function passing it the single siteID
$A(siteIDs).each(function(siteID) {
// If an element exists on the page with the id of setCurrentSiteElementPrefix + current siteID
if ($(this.setCurrentSiteElementPrefix + siteID)) {
 // Add an observer to the 'click' event of that element and bind it
 // to the 'getContent' function
 $(this.setCurrentSiteElementPrefix + siteID).observe('click', this.getContent.bind(this));
}
});
}
&lt;/pre&gt; where "siteIDs" is a comma delimited list of ids ("1,2,3,4") and "setCurrentSiteElementPrefix" is a part of the name of link element with a dynamically generated id (such as setCurrentSiteElementPrefix_1, setCurrentSiteElementPrefix_2). Here is the above loop in pseudo code (just for your kids Doug):

Convert the list of siteIDs to a prototype array and for each found array element, run a function passing the individual site id. $A(siteIDs) converts the list of site ids to an array, while .each() executes the inline function for each array element.
// $A(siteIDs).each(function(siteID)

If an element exists on the page with the id starting with setCurrentSiteElementPrefix (definition not shown here) + current siteID (passed by the inline function above)
// if ($(this.setCurrentSiteElementPrefix + siteID))

Add an observer to the
"click" event of that element and bind it to the "getContent" function. The "getContent" function has to bound to the "this" scope since the "getContent" function will not otherwise know what "this" means when trying to refer to elements defined in the object.
// $(this.setCurrentSiteElementPrefix + siteID).observe('click', this.getContent.bind(this));

Never mind why I am doing this, I will follow up on that with another post. So I was trying to tie an event observer to the 'click' event of each link element by looping through the list of dynamic ids ($A(siteIDs).each(function(siteID)). However, that was giving me some issues with the message "this.getContent is not defined". Why the heck not, the code is inside the "initialize" method of my object?! It turns out while looping over an array as above the "this" scope is not preserved. So the function inside the loop has no idea what "this" means. The simple fix is to surround the function with parenthesis and append ".bind(this)":
&lt;pre name="code" class="js"&gt;
initialize: function() {
 // Note the extra parenthesis before 'function(siteID)'
 $A(siteIDs).each((function(siteID) {
  if ($(this.setCurrentSiteElementPrefix + siteID)) {
   $(this.setCurrentSiteElementPrefix + siteID).observe('click', this.getContent.bind(this));
  }
 }).bind(this));
 // Note the ').bind(this)' before the semicolon
}
&lt;/pre&gt;
If you like to learn more on bind, check out &lt;a href="http://neeraj.name/2007/08/13/understanding-bind-in-javascript"&gt;Understanding bind and bindAsEventListener in Javascript&lt;/a&gt; and &lt;a href="http://neeraj.name/2007/08/21/understanding-bind-and-bindaseventlistener-in-javascript-part-ii"&gt;Understanding bind and bindAsEventListener in Javascript - Part II&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5933328332170221323?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5933328332170221323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5933328332170221323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5933328332170221323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5933328332170221323'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/prototypejs-object-initialization-and.html' title='Prototype.js Object Initialization and Bind While Enumerating Arrays'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4589969843517196161</id><published>2007-10-02T17:53:00.001-04:00</published><updated>2007-10-02T17:53:13.576-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Wiki'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Modifying Canvas ColdFusion Wiki</title><content type='html'>&lt;p&gt;&lt;a href="http://canvas.riaforge.org/"&gt;Canvas&lt;/a&gt; is an excellent wiki written by &lt;a href="http://www.coldfusionjedi.com"&gt;Ray Camden&lt;/a&gt;. It has a vast number of features for creating/maintaining documentation of any sort. I have been playing with it for a bit but I still haven't taken advantage of all its features. However, it lacks some basic features I thought it needed. I have been working on a side project and as a side effect I have added a few essentials (in my opinion). In subsequent posts, I will attempt to explain how to modify Canvas and add the following features:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Database user authentication&lt;/li&gt;    &lt;li&gt;Persist user sessions between visits - &amp;quot;Remember Me&amp;quot; functionality&lt;/li&gt;    &lt;li&gt;LDAP user authentication&lt;/li&gt;    &lt;li&gt;Integration with &lt;a href="http://google.com/analytics"&gt;Google Analytics&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Contact form&lt;/li&gt;    &lt;li&gt;Better exception handling / notifications&lt;/li&gt; &lt;/ol&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4589969843517196161?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4589969843517196161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4589969843517196161' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4589969843517196161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4589969843517196161'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/modifying-canvas-coldfusion-wiki.html' title='Modifying Canvas ColdFusion Wiki'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6171468819107290632</id><published>2007-10-02T15:13:00.001-04:00</published><updated>2007-10-05T11:51:52.401-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Loop Over ColdFusion Structure</title><content type='html'>Just a quick reference on how to loop over a structure without knowing its keys.
&lt;pre name="code" class="cf"&gt;
&amp;lt;cfset testStruct = structnew() /&amp;gt;
&amp;lt;cfset testStruct.key1 = "test1" /&amp;gt;
&amp;lt;cfset testStruct.key2 = "test2" /&amp;gt;
&amp;lt;cfset testStruct.key3 = "test3" /&amp;gt;

&amp;lt;cfdump var="#testStruct#" /&amp;gt;

&amp;lt;cfloop list="#structKeyList(testStruct)#" index="key"&amp;gt;
&amp;lt;cfoutput&amp;gt;
Key: #key#, Value: #testStruct[key]#
&amp;lt;/cfoutput&amp;gt;
&amp;lt;/cfloop&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6171468819107290632?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6171468819107290632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6171468819107290632' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6171468819107290632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6171468819107290632'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/10/loop-over-coldfusion-structure.html' title='Loop Over ColdFusion Structure'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4865084582087475818</id><published>2007-09-26T21:50:00.001-04:00</published><updated>2008-01-29T16:05:38.193-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Dev'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><title type='text'>SVN4DW - Hard to Find SVN Extension for Dreamweaver</title><content type='html'>&lt;p&gt;   &lt;br /&gt;I've been using this extension for a while and it's pretty handy for updating/committing code from/to your SVN repository. I tried to find it on the net tonight so I can install it at home but it seems to have vanished. So I looked through my work PC and there it was. Awesome! For those folks that like to use it, I've put it up on my personal site. The link is &lt;a title="http://tech-cats.net/blog/downloads/SVN4DW.zip" href="http://tech-cats.net/blog/downloads/SVN4DW.zip"&gt;http://tech-cats.net/blog/downloads/SVN4DW.zip&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4865084582087475818?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4865084582087475818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4865084582087475818' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4865084582087475818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4865084582087475818'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/svn4dw-hard-to-find-svn-extension-for.html' title='SVN4DW - Hard to Find SVN Extension for Dreamweaver'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6116015571687878379</id><published>2007-09-26T14:24:00.001-04:00</published><updated>2008-02-11T15:05:14.423-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Querying Active Directory Through SQL Server</title><content type='html'>Integrating your application with Active Directory (or another LDAP based directory) is a common requirement in  many business applications. Almost every language has a way to query LDAP but little known is the approach of integrating SQL Server with your LDAP controller. This quick article will guide you through setting up and using LDAP queries through SQL Server 2000 with Active Directory as the LDAP controller.
&lt;!--break--&gt;
&lt;br /&gt;&lt;br /&gt;
First, you need to create a SQL Server linked server. Set it up through SQL Server Enterprise Manager:
&lt;ol&gt;
  &lt;li&gt;Open SQL Server Enterprise Manager&lt;/li&gt;
  &lt;li&gt;Go to the database server to which you will be adding the linked server&lt;/li&gt;
  &lt;li&gt;Expend &amp;quot;Security&amp;quot;&lt;/li&gt;
  &lt;li&gt;Right-click on &amp;quot;Linked Servers&amp;quot; and click on &amp;quot;New Linked Server...&amp;quot;&lt;/li&gt;
  &lt;li&gt;Fill in the following:
    &lt;ol&gt;
      &lt;li&gt;Under the General tab:
        &lt;ol&gt;
          &lt;li&gt;Linked Server: &lt;strong&gt;&lt;em&gt;adsi&lt;/em&gt;&lt;/strong&gt; (or whatever you want to call it)&lt;/li&gt;
          &lt;li&gt;Server type: select &lt;strong&gt;&lt;em&gt;Other Data Source&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;Provider name:select &lt;strong&gt;&lt;em&gt;OLE DB Provider for Microsoft Directory Services&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;Under Provider Options: check that &lt;strong&gt;&lt;em&gt;Allow InProcess&lt;/em&gt;&lt;/strong&gt; is checked&lt;/li&gt;
          &lt;li&gt;Leave the rest of the fields blank&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Under the Security tab:
        &lt;ol&gt;
          &lt;li&gt;Local Login: &lt;strong&gt;&lt;em&gt;sqlServerUser&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;Remote User: &lt;strong&gt;&lt;em&gt;&lt;a href="mailto:ntaccount@domain.com" title="Linkification: mailto:ntaccount@domain.com" class="linkification-ext"&gt;ntaccount@domain.com&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; (such as &lt;strong&gt;&lt;em&gt;&lt;a href="mailto:bkostadinov@ica.com" title="Linkification: mailto:bkostadinov@ica.com" class="linkification-ext"&gt;bkostadinov@ica.com&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;ica.com\bkostadinov&lt;/em&gt;&lt;/strong&gt;)&lt;/li&gt;
          &lt;li&gt;Remote Password: &lt;strong&gt;&lt;em&gt;userPassword&lt;/em&gt;&lt;/strong&gt; for the above domain account&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
Through Query Analyzer:
&lt;ol&gt;
  &lt;li&gt;Change the &amp;quot;AllowInProcess&amp;quot; registry key under &lt;strong&gt;&lt;em&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\ADSDSOObject&lt;/em&gt;&lt;/strong&gt; to &amp;quot;&lt;strong&gt;&lt;em&gt;dword:00000001&lt;/em&gt;&lt;/strong&gt;&amp;quot;
    &lt;ol&gt;
      &lt;li&gt;Edit the registry manually or put the following in a .reg file and execute it:
        &lt;pre&gt;
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\ADSDSOObject]

"AllowInProcess"=dword:00000001
      &lt;/pre&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Open Query Analyzer (or your choice of query tool)&lt;/li&gt;
  &lt;li&gt;Connect to the server to which you will be adding the linked server&lt;/li&gt;
  &lt;li&gt;Change the provided values and execute the following code:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre name="code" class="sql"&gt;
-- Change 'adsi' to the desired name of the linked server
exec sp_addlinkedserver
  'adsi',
  '',
  'ADSDSOObject',
  ''
go

-- Change 'adsi' to the desired name of the linked server
-- Change 'sqlUser' to the username of local sql server user
-- Change 'domainName\userName' to a domain account
-- (the format can be 'domainName\userName' or 'userName@domainName')
-- Change 'domainUserPassword' to the password of the domain account
exec sp_addlinkedsrvlogin
  'adsi',
  false,
  'sqlServerUser',
  'domainName\userName',
  'domainUserPassword'
go
&lt;/pre&gt;
&lt;br /&gt;
Or you can just fill in the values on top of the following script and run that:
&lt;br /&gt;&lt;br /&gt;
&lt;pre name="code" class="sql"&gt;
declare @linkedServerSql nvarchar(4000),
  @linkedServerName varchar(100),
  @localSqlUsername varchar(100),
  @domainUsername varchar(100),
  @domainUserPassword varchar(100)

-- Set the local sql server user
set @localSqlUsername = 'sqlUser'
-- format can be 'domainName\userName' or 'userName@domainName'
set @domainUsername = 'domainName\userName'
set @domainUserPassword = 'domainUserPassword'

set @linkedServerName = 'adsi'

set @linkedServerSql = '
  exec sp_addlinkedserver
  ''' + @linkedServerName + ''',
  '''',
  ''ADSDSOObject'',
  '''' 

exec sp_addlinkedsrvlogin
  ''' + @linkedServerName + ''',
  false,
  ''' + @localSqlUsername + ''',
  ''' + @domainUsername + ''',
  ''' + @domainUserPassword + ''''

exec sp_executesql @linkedServerSql
&lt;/pre&gt;
Run a query to verify that the linked server works. The query below will give you all the users in the &lt;strong&gt;&lt;em&gt;dc=ica,dc=com &lt;/em&gt;&lt;/strong&gt;(change that to match your own domain):
&lt;pre name="code" class="sql"&gt;
select  *
from  openquery(adsi, '
select  givenName,
    sn,
    sAMAccountName,
    displayName,
    mail,
    telephoneNumber,
    mobile,
    physicalDeliveryOfficeName,
    department,
    division
from    ''LDAP://dc=ica,dc=com''
where   objectCategory = ''Person''
        and
        objectClass = ''user''
')
&lt;/pre&gt;
Below, is an alternate syntax which you can use to apply ldap filters with almost universal syntax. The following will get all the users in LDAP but limit the result set to those users who's &amp;quot;given&amp;quot; &amp;amp; &amp;quot;sn&amp;quot; names are not empty. It will also apply a filter to the &amp;quot;division&amp;quot; attribute and exclude any records that  match &amp;quot;system&amp;quot; and &amp;quot;generic&amp;quot;.
&lt;pre name="code" class="sql"&gt;
declare @ldapFilter nvarchar(1000), @ldapSQL nvarchar(4000)

-- Set the filter to exlude objects that have a division of "System" and "Generic"
set @ldapFilter = '(!division=System*)(!division=Generic)'

-- Create an ldap query to get all users under dc=ica,dc=com
set @ldapSQL = '
select  givenName as firstName,
        sn as lastName,
        displayName,
        lower(sAMAccountName) as accountName,
        telephoneNumber as phoneNumber,
        mobile as cellPhoneNumber,
        mail as emailAddress,
        department,
        physicalDeliveryOfficeName as siteName
from    openquery(adsi, ''&amp;lt;LDAP://dc=ica,dc=com&amp;gt;
    (&amp;(objectCategory=Person)(objectClass=user)'+ @ldapFilter + ');
        givenName,
    sn,
    sAMAccountName,
    displayName,
    mail,
    telephoneNumber,
    mobile,
    physicalDeliveryOfficeName,
    department,
    division;
    subtree'')
where   givenName is not null
    and
    sn is not null'

exec sp_executesql @ldapSQL
&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;Some things to note:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;"LDAP" is case sensitive, if you try using "ldap", the query will throw an error.&lt;/p&gt;
&lt;p&gt;Querying the Active Directory server will work fine from Query Analyzer even if you do not run &lt;strong&gt;&lt;em&gt;sp_addlinkedserverlogin&lt;/em&gt;&lt;/strong&gt;. However, if you try to execute the query from the web (with something like  ColdFusion, you will get an error similar to:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;[Macromedia][SQLServer JDBC Driver][SQLServer]OLE DB provider 'ADSDSOObject' reported an error. The provider indicates that the user did not have the permission to perform the operation.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6116015571687878379?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6116015571687878379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6116015571687878379' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6116015571687878379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6116015571687878379'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/querying-active-directory-through-sql.html' title='Querying Active Directory Through SQL Server'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4960421955987662812</id><published>2007-09-25T22:47:00.001-04:00</published><updated>2007-09-25T22:47:55.777-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Dev'/><title type='text'>Web Application Deadly Sin</title><content type='html'>&lt;p&gt;I have ran across this situation more than a couple of times recently. First it was my hosting provider, than the new web application I tried today (called Fuser). When signing up, they let you pick your password and I use a totally random password each time somewhere around 16-20 characters. So it happens that the applications above, cut my password to their allowed length but do not let me know they are doing so. Nowhere does it say that the password should be 10 or 15 characters. So end up with a newly created account that I cannot log into only to find out (after I go through the &amp;quot;forgot password&amp;quot; procedure) that my password was chopped. That is annoying and enough to turn me off using the application. Common sense, where are you?&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4960421955987662812?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4960421955987662812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4960421955987662812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4960421955987662812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4960421955987662812'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/web-application-deadly-sin.html' title='Web Application Deadly Sin'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6629401993658965957</id><published>2007-09-25T15:27:00.001-04:00</published><updated>2007-09-25T15:37:29.363-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='Reactor'/><title type='text'>Reactor Oops - Case Sensitive Dictionary XML</title><content type='html'>Here is the message I got today while trying to do some work with reactor and model-glue.   &lt;p&gt;&lt;b&gt;Message&lt;/b&gt;  
An error occurred while Transforming an XML document.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Detail&lt;/b&gt;  
Empty expression!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Extended Info&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Tag Context&lt;/b&gt;  
D:\_Webroot\reactor\core\objectTranslator.cfc (149)  
D:\_Webroot\reactor\core\objectTranslator.cfc (164)  
D:\_Webroot\reactor\core\objectTranslator.cfc (164)  
D:\_Webroot\reactor\core\objectTranslator.cfc (101)  
D:\_Webroot\reactor\core\objectFactory.cfc (223)  
D:\_Webroot\reactor\reactorFactory.cfc (80)  
D:\_Webroot\reactor\base\abstractRecord.cfc (393)  
D:\_Webroot\reactor\project\myproject\Validator\usersValidator.cfc (10)&lt;/p&gt;  &lt;p&gt;It turned out that the dictionary file that reactor generated is case sensitive. I need to change "&amp;lt;Users&amp;gt;" to "&amp;lt;users&amp;gt;". The table is defined as "users" but I had to change it to "&amp;lt;Users&amp;gt;" on my home machine. It seems that reactor can't make up it's mind on how it wont's the table to be called. Why is it "Users" at home and "users" at work? I'm using Apache on Windows with the same version of MySQL and reactor on both machines.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Update: &lt;/span&gt;So I just learned that:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;cfset usersRecord = variables.reactor.createRecord("users") /&amp;gt;&lt;/pre&gt; is not the same as:&lt;pre class="code"&gt;&amp;lt;cfset usersRecord = variables.reactor.createRecord("Users") /&amp;gt;&lt;/pre&gt;The dictionary file was created with "Users" as the table name so reactor was looking for the same case. I think this is only an issue with MySQL.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6629401993658965957?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6629401993658965957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6629401993658965957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6629401993658965957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6629401993658965957'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/reactor-ops-case-sensitive-dictionary.html' title='Reactor Oops - Case Sensitive Dictionary XML'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7338487634871812130</id><published>2007-09-25T10:08:00.001-04:00</published><updated>2007-09-25T10:08:38.737-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Dev'/><title type='text'>Updating Web Applications in Production</title><content type='html'>&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This is just an idea so far, but it is worth documenting so I remember to do it. It also assumes that you are using some kind of source control system such as Subversion.&lt;/p&gt;  &lt;p&gt;Wouldn't it be cool to know when your production web application is out of date? By that I mean there is a newer version of it available in your source code repository. So instead of the usual steps:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Check-in latest changes to the application&lt;/li&gt;    &lt;li&gt;Go to the production sever and update the code from the repository&lt;/li&gt;    &lt;li&gt;Reinitialize the application (I use Model-Glue)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;You can simply:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Check-in latest changes to the application&lt;/li&gt;    &lt;li&gt;Go to the web application in production&lt;/li&gt;    &lt;li&gt;Click a button to updated to the latest revision&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Same number of steps I guess but doesn't the second solution seem so much nicer. I will have to implement this across all the web applications I maintain/develop.&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7338487634871812130?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7338487634871812130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7338487634871812130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7338487634871812130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7338487634871812130'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/updating-web-applications-in-production.html' title='Updating Web Applications in Production'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8611745495592916481</id><published>2007-09-20T13:58:00.001-04:00</published><updated>2007-09-20T14:02:22.416-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>CSSVista - Edit your CSS code live on Internet Explorer and Firefox</title><content type='html'>&lt;table border="0" cellpadding="2" cellspacing="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="300"&gt;         &lt;div class="wlWriterSmartContent" id="scid:0E22F29F-1D77-4799-8869-F298745B9709:8391699b-b1bc-479c-97bd-8267f2a3421a" style="margin: 0px; padding: 0px; display: inline; float: none; width: 333px;"&gt;&lt;img src="http://lh4.google.com/boyank/RvK0xbzc4NI/AAAAAAAAACM/EpACmcUazZQ/200709201354350495%5B2%5D.jpg" /&gt;&lt;/div&gt;       &lt;/td&gt;        &lt;td valign="top" width="300"&gt;I came across this pretty nice tool called &lt;a href="http://litmusapp.com/cssvista"&gt;CSSVista&lt;/a&gt;. It lets you edit css on the fly. Sure, the web developer toolbar and Firebug already does this for Firefox but it's still cool.&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8611745495592916481?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8611745495592916481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8611745495592916481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8611745495592916481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8611745495592916481'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/cssvista-edit-your-css-code-live-on_20.html' title='CSSVista - Edit your CSS code live on Internet Explorer and Firefox'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-414453094491548283</id><published>2007-09-20T12:12:00.001-04:00</published><updated>2008-03-31T18:08:16.348-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>JSValidation Kicks Butt - Validation Library for Prototype.js</title><content type='html'>to get it to work, simply include the library like so:
&lt;pre name="code" class="js"&gt;&amp;lt;script language="javascript" type="text/javascript" src="js/jsvalidate/jsvalidate.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
Add some css styles:&lt;pre name="code" class="css"&gt;.jsvalidation { color: #ff0000; font-size: 14px; }&lt;/pre&gt;
add "jsrequired" (for a required field) and the jsvalidate type (such as "jsvalidate_number") to the "class" attribute of your text element.
&lt;pre name="code" class="xml"&gt;&amp;lt;input type="text" name="year" id="year" size="4" class="jsrequired jsvalidate_number" /&amp;gt;&lt;/pre&gt;
and finally set the message to be displayed when the validation fails in the "alt" attribute of the element:
&lt;pre name="code" class="xml"&gt;&amp;lt;input type="text" name="year" id="year" size="4" class="jsrequired jsvalidate_number" alt="Please enter a Year" /&amp;gt;&lt;/pre&gt;
More on the jsvalidation types at the &lt;a href="http://www.jsvalidate.com/docs/"&gt;docs&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-414453094491548283?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/414453094491548283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=414453094491548283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/414453094491548283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/414453094491548283'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/jsvalidation-kicks-butt-validation_20.html' title='JSValidation Kicks Butt - Validation Library for Prototype.js'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5218532185340666909</id><published>2007-09-17T16:42:00.000-04:00</published><updated>2007-09-18T10:18:13.768-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Quake Style Command Prompt - Cool Stuff</title><content type='html'>This is based on the guide provided on &lt;a href="http://www.instructables.com/id/E3P6UG6F5Y3KZFT/?ALLSTEPS"&gt;Instructables.&lt;/a&gt; I'm posting this here because I finally got around trying this out. I have to say it's pretty nice.

The idea is simple. You press the Windows key + '~' (tilda) and get a semi-transparent console window in the top left corner of your screen. You press the same combination key again and the window disappears. Very handy for those of us that use the command prompt often.

Here is the end result. Click on the thumbnail to see a larger picture:
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_xYZyI9ujstU/Ru_dz6-IrBI/AAAAAAAAAB0/NWtJVBEipmI/s1600-h/console.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_xYZyI9ujstU/Ru_dz6-IrBI/AAAAAAAAAB0/NWtJVBEipmI/s320/console.png" alt="" id="BLOGGER_PHOTO_ID_5111547986161740818" border="0" /&gt;&lt;/a&gt;
To get started:

1. Get &lt;a href="http://www.autohotkey.com/download/"&gt;AutoHotkey&lt;/a&gt;
2. Download the last stable version of Console (as of 09.17.2007 that is 1.5 so get "&lt;a href="http://downloads.sourceforge.net/console/Console-1.5.zip?modtime=1127414836&amp;amp;big_mirror=0" onclick="window.location='/project/downloading.php?group_id=43764&amp;use_mirror=internap&amp;filename=Console-1.5.zip&amp;'+Math.floor(Math.random()*100000000); return false;"&gt;Console-1.5.zip"&lt;/a&gt;
3. Get the customized "console.xml" file from the bottom of the &lt;a href="http://www.instructables.com/id/E3P6UG6F5Y3KZFT/?ALLSTEPS"&gt;Instructable&lt;/a&gt; or from &lt;a href="http://www.instructables.com/files/orig/FRL/SWZ0/F5Y3KZGV/FRLSWZ0F5Y3KZGV.xml"&gt;here&lt;/a&gt; directly
4. Get the AutoHotkey script from the bottom of the &lt;a href="http://www.instructables.com/id/E3P6UG6F5Y3KZFT/?ALLSTEPS"&gt;Instructable&lt;/a&gt; or from here &lt;a href="http://www.instructables.com/files/orig/FTH/ZNXN/F5Y3KZGY/FTHZNXNF5Y3KZGY.tmp"&gt;directly&lt;/a&gt;
5. Install AutoHotkey
6. Extract Console-1.5.zip to "c:\program files\console" or wherever you desire

7. Create a shortcut to "console.exe" in your "c:\windows" directory
8. Copy the customized "console.xml" to "c:\program files\console" (or wherever you installed Console) and overwrite the file that's there
9. Start the AutoHotkey script you got in step 4. You can also put a shortcut to the script in the "Startup" folder on your Start Menu.&lt;a class="linkification-ext" href="http://sourceforge.net/project/showfiles.php?group_id=43764&amp;amp;package_id=36143" title="Linkification: http://sourceforge.net/project/showfiles.php?group_id=43764&amp;amp;package_id=36143"&gt;
&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5218532185340666909?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5218532185340666909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5218532185340666909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5218532185340666909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5218532185340666909'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/quake-style-command-prompt-cool-stuff.html' title='Quake Style Command Prompt - Cool Stuff'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_xYZyI9ujstU/Ru_dz6-IrBI/AAAAAAAAAB0/NWtJVBEipmI/s72-c/console.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7136280243097202905</id><published>2007-09-17T16:38:00.001-04:00</published><updated>2008-04-02T08:05:25.174-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RegEx'/><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><title type='text'>Using Regular Expression in SQL Server</title><content type='html'>Who doesn’t love regular expressions?! If you don’t know what they are, you should take some time to learn. Regular expressions or from here on RegEx are a very powerful way to search/replace string within strings. That being said, almost any language supports RegEx and for a while I’ve been using them with SQL Server thanks to &lt;a href="http://www.codeproject.com/database/xp_pcre.asp?df=100&amp;amp;forumid=16452&amp;amp;exp=0&amp;amp;select=1191266" target="_blank"&gt;xp_pcre - Regular Expressions in T-SQL&lt;/a&gt;

Here is an example use of two of the functions that come with the above extended sql server library:&lt;pre class="sql" name="code"&gt;declare @out varchar(8000)
declare @str varchar(500)

-- Create a string containing an ldap common name

set @str = lower(’LDAP://CN=APO Conference Room,OU=Locations,OU=APO,OU=Sites,DC=ica,DC=com’)

-- Strip everything from the string and replace with the ’ou’ that comes after ’ou=locations’

exec master.dbo.xp_pcre_replace @str, ’.*ou=locations,ou=(’w+).*’, ’$1’, @out out

-- Print the results
print @out

-- Create a string containing an ldap common name
set @str = lower(’LDAP://OU=SMD,OU=Sites,DC=ica,DC=com’)

-- Return 1 if there is a match of ’ou=&lt;one letters="" more="" or=""&gt;’ followed by ’ou=sites’
select master.dbo.fn_pcre_match(@str, ’^ldap://ou=’w+,ou=sites’)&lt;/one&gt;&lt;/pre&gt;More information here:
&lt;a href="http://www.codeproject.com/database/xp_pcre.asp?df=100&amp;amp;forumid=16452&amp;amp;exp=0&amp;amp;select=1191266"&gt;http://www.codeproject.com/database/xp_pcre.asp?df=100&amp;amp;forumid=16452&amp;amp;exp=0&amp;amp;select=1191266&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7136280243097202905?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7136280243097202905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7136280243097202905' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7136280243097202905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7136280243097202905'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/using-regular-expression-in-sql-server.html' title='Using Regular Expression in SQL Server'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-1118053892917660690</id><published>2007-09-13T20:30:00.001-04:00</published><updated>2007-09-13T20:31:25.511-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='charts'/><title type='text'>Draw Flow Charts Online</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Download Squad just had a post about this nifty online tool. Anybody that draws diagrams (that means you Doug), will benefit from this.

&lt;a href="http://www.drawanywhere.com/"&gt;Draw Anywhere - easy online diagramming, flow chart&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-1118053892917660690?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/1118053892917660690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=1118053892917660690' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1118053892917660690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/1118053892917660690'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/draw-charst-online.html' title='Draw Flow Charts Online'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8037969244300395984</id><published>2007-09-13T13:14:00.001-04:00</published><updated>2008-03-31T18:06:17.012-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Disabling Forms with Prototype - Gotcha</title><content type='html'>I love using Prototype for all my JavaScript needs. Ajax calls are real easy with or without parameters. To get some form parameters to pass with your request, you would simply do:&lt;pre name="code" class="js"&gt;var params = $('myForm').serialize();&lt;/pre&gt; and then you would disable the form like so:&lt;pre class="code"&gt;$('myForm').disable();&lt;/pre&gt;
However, here is a little gotcha I always seem to forget:
&lt;ul&gt;
&lt;li&gt;DO NOT disable the form before you read your form values&lt;/li&gt;
&lt;/ul&gt;
If you do, code such as:&lt;pre name="code" class="js"&gt;$F('myFormFiled');&lt;/pre&gt;or&lt;pre name="code" class="js"&gt;$('myForm').serialize();&lt;/pre&gt;will no longer work. By not working, I mean will just return empty and you will be beating your head against the desk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8037969244300395984?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8037969244300395984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8037969244300395984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8037969244300395984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8037969244300395984'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/disabling-forms-with-prototype-gotcha.html' title='Disabling Forms with Prototype - Gotcha'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5035340407613868172</id><published>2007-09-13T09:31:00.001-04:00</published><updated>2007-09-13T09:31:13.507-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jedi'/><title type='text'>Chad Vader - Funny Stuff</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Whoever hasn't seen the Chad Vader creation of Matt Sloan and Aeron Yonda should. It's pretty amusing. You can find it at&lt;br/&gt;&lt;a href='http://www.splu.net/chadvader.php'&gt;Chad Vader: Day Shift Manager - Blame Society Productions - Matt Sloan and Aaron Yonda&lt;/a&gt;. The tag line is "Life is hard for Chad Vader, the younger, less charismatic brother of Darth Vader, who is the day shift manager of a grocery store."&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5035340407613868172?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5035340407613868172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5035340407613868172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5035340407613868172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5035340407613868172'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/chad-vader-funny-stuff.html' title='Chad Vader - Funny Stuff'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2185448511879096897</id><published>2007-09-11T23:53:00.001-04:00</published><updated>2007-09-11T23:53:52.712-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cats'/><title type='text'>Cats love to sleep, eat and sneak out</title><content type='html'>&lt;p&gt;This is one passed out cat. She had to eat first however. This is the same cat that managed to get out and spend the night outdoors when we took our overnight trip to Old Forge. I am glad she is ok. To our surprise, we came home to a dead mole by the back door and it was a mystery until we found the cat outside of the house.&lt;a title="DSCF4856" href="http://www.flickr.com/photos/13087518@N00/1355460019/" target="_blank"&gt;&lt;img alt="DSCF4856" src="http://static.flickr.com/1228/1355460019_af94dd52cf.jpg" align="right" border="0" height="181" width="240" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2185448511879096897?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2185448511879096897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2185448511879096897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2185448511879096897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2185448511879096897'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/this-is-one-passed-out-cat.html' title='Cats love to sleep, eat and sneak out'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4805414585764132584</id><published>2007-09-10T12:55:00.000-04:00</published><updated>2007-09-10T12:59:43.463-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdSpring'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Common Model-Glue "Newbie" Mistake</title><content type='html'>In short: forgetting to "wire" the message broadcasted by your event to the function in your controller. I still do this on occasion which prompted me to post it.

The longer version:

You have a an event defined as follows:
&lt;pre class="code"&gt;
&amp;lt;event-handler name="GetUsersForm"&amp;gt;
 &amp;lt;broadcasts&amp;gt;
  &amp;lt;message name="getRolesList" /&amp;gt;
  &amp;lt;message name="getSytelineUsersBySiteID" /&amp;gt;
  &amp;lt;message name="getUsersBySiteID" /&amp;gt;
 &amp;lt;/broadcasts&amp;gt;

 &amp;lt;views&amp;gt;
  &amp;lt;view name="body" template="frmUsers.cfm" /&amp;gt;
 &amp;lt;/views&amp;gt;
&amp;lt;/event-handler&amp;gt;&lt;/pre&gt;
You have "getRolesList", "getSytelineUsersBySiteID" and "getUsersBySiteID"
defined in your controller. However, when you call the event, you don't get any of
the data you expect to see there. The gotcha is "wiring" the broadcasted message to
the function in the controller as follows:
&lt;pre class="code"&gt;&amp;lt;controller name="ApplicationController" type="LabelGeneration.controller.ApplicationController"&amp;gt;
 &amp;lt;message-listener message="OnRequestStart" function="OnRequestStart" /&amp;gt;
 &amp;lt;message-listener message="OnQueueComplete" function="OnQueueComplete" /&amp;gt;
 &amp;lt;message-listener message="OnRequestEnd" function="OnRequestEnd" /&amp;gt;

 &amp;lt;message-listener message="getSitesList" function="getSitesList" /&amp;gt;
 &amp;lt;message-listener message="getRolesList" function="getRolesList" /&amp;gt;

 &amp;lt;message-listener message="getSytelineUsersBySiteID" function="getSytelineUsersBySiteID" /&amp;gt;
 &amp;lt;message-listener message="getUsersBySiteID" function="getUsersBySiteID" /&amp;gt;
 &amp;lt;message-listener message="addUser" function="addUser" /&amp;gt;
 &amp;lt;message-listener message="deleteUser" function="deleteUser" /&amp;gt;
&amp;lt;/controller&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4805414585764132584?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4805414585764132584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4805414585764132584' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4805414585764132584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4805414585764132584'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/common-model-glue-newbie-mistake.html' title='Common Model-Glue &quot;Newbie&quot; Mistake'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3913058691115749484</id><published>2007-09-07T08:21:00.000-04:00</published><updated>2007-09-07T11:16:59.432-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdSpring'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Howto Reload Model-Glue Applications</title><content type='html'>There are a few different way to reload a Model-Glue application. Before you start, please Note the "reloadKey" and "reloadPassword" in your ColdSpring.xml file. If the "reload" value is set to true in your ColdSpring.xml file, you do not need to do anything as the application is reloaded every time you load/refresh the page. While this can be helpful for development, it will kill your application in production, so beware. If the "reload" value is set to false, here is how to reload your application:

If you want your application to reload on every request:

1. Edit the ColdSpring.xml file and set the "reload" value to true
2. Invoke the application by going to "http://yourhost/yourapplication/?init=true", where "init" is the value of the "reloadKey" and "true" is the value of the "reloadPassword"

If you don't want the application to reload on every request:

1. Invoke the application by going to "http://yourhost/yourapplication/?init=true", where "init" is the value of the "reloadKey" and "true" is the value of the "reloadPassword"

The alternative solution I use while always leaving the reload key to "false" is to write your own re-init method. For some reason I find that invoking the application with "http://yourhost/yourapplication/?init=true" is a pain and I'm not sure that it clears application or session scope variables. So instead, I have my own method. In your "application.cfc", create the onRequestStart function as follows. If it already exists, just add the code shown here.
&lt;pre class="code"&gt;&amp;lt;cffunction name="OnRequestStart" output="no"&amp;gt;
  &amp;lt;cfif structKeyExists(url, "init")&amp;gt;
    &amp;lt;cfset structclear(Application) /&amp;gt;
    &amp;lt;cfset structclear(Session) /&amp;gt;

    &amp;lt;cfset onApplicationStart() /&amp;gt;
  &amp;lt;/cfif&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;/pre&gt;Now, when you invoke the url "http://yourhost/yourapplication/?init", your application will re-init  by deleting the application and session scopes. The concept is based on some code I say Ray Camden use. Maybe it's reinventing the wheel and ColdSpring already does that but I'm not sure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3913058691115749484?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3913058691115749484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3913058691115749484' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3913058691115749484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3913058691115749484'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/howto-reload-model-glue-applications.html' title='Howto Reload Model-Glue Applications'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-8515183481897981164</id><published>2007-09-07T08:13:00.001-04:00</published><updated>2007-09-07T08:13:56.422-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><title type='text'>Apt-Get for Windows = Win-Get (auto download and install applications)</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;If you ever installed anything under Ubuntu or Debian Linux, you know how nice it is to just type "apt-get install apache" and the operating system will download apache and install it for you. This feature has forever been lacking in Windows based platforms. The guys at &lt;a href='http://windows-get.sourceforge.net/'&gt;Win-Get&lt;/a&gt; have decided to remedy that by implementing similar functionality for Windows. All you need to do (right from the win-get web page) is:&lt;br/&gt;&lt;br/&gt;1. Download &lt;a href='http://windows-get.sourceforge.net/wget.exe'&gt;wget.exe&lt;/a&gt;&lt;br/&gt;2. Download &lt;a href='http://windows-get.sourceforge.net/win-get.exe'&gt;win-get.exe&lt;/a&gt; (version 1.01)&lt;br/&gt;3. Put the 2 files some where on your system (I like in the c:\windows so they are system wide accessible).&lt;br/&gt;    &lt;br/&gt;Then to install an application from the &lt;a href='http://windows-get.sourceforge.net/listapps.php?PHPSESSID=71f87a25774f3c4c7abec5fb9941e823'&gt;supported application list&lt;/a&gt;, you open a command prompt and type:&lt;br/&gt;"win-get install paint.net" or "win-get sinstall paint.net" ("sinstall" is for silent install but not all applications support it).&lt;br/&gt;&lt;br/&gt;Here is a list of commands I ran for a new install:&lt;br/&gt;&lt;br/&gt;win-get sinstall paint.net&lt;br/&gt;win-get sinstall spybot&lt;br/&gt;win-get sinstall firefox&lt;br/&gt;win-get sinstall avg_antivirus&lt;br/&gt;win-get sinstall notepad++&lt;br/&gt;win-get sinstall openoffice&lt;br/&gt;win-get sinstall winrar&lt;br/&gt;&lt;br/&gt;So nice and easy! I love it.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-8515183481897981164?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/8515183481897981164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=8515183481897981164' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8515183481897981164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/8515183481897981164'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/apt-get-for-windows-win-get-auto.html' title='Apt-Get for Windows = Win-Get (auto download and install applications)'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4137922617366277842</id><published>2007-09-06T08:57:00.001-04:00</published><updated>2007-12-17T14:32:08.718-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Hardly Used SQL Server Functions</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;This is for you Ben Nadel:&lt;br/&gt;&lt;br/&gt;&lt;a href='http://dotnetsamplechapters.blogspot.com/2007/09/ten-sql-server-functions-that-you.html'&gt;Dot Net Sample Chapters And Resources: Ten SQL Server Functions That You Hardly Use But Should&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4137922617366277842?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4137922617366277842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4137922617366277842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4137922617366277842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4137922617366277842'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/09/hardly-used-sql-server-functions.html' title='Hardly Used SQL Server Functions'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-540792677304980397</id><published>2007-08-20T10:51:00.001-04:00</published><updated>2007-08-20T10:51:50.760-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>A couple of good Prototype.js articles</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Came across a couple of good articles on using Prototype.js:&lt;br/&gt;&lt;br/&gt;&lt;a href='http://thinkweb2.com/projects/prototype-checklist/'&gt;How well do you know prototype&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;a href='http://thinkweb2.com/projects/prototype/'&gt;How well do you know prototype (part II)&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-540792677304980397?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/540792677304980397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=540792677304980397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/540792677304980397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/540792677304980397'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/08/couple-of-good-prototypejs-articles.html' title='A couple of good Prototype.js articles'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-323050655863859790</id><published>2007-08-13T12:17:00.000-04:00</published><updated>2007-08-13T12:31:01.193-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Model-Glue Gotcha - Bug or Feature?</title><content type='html'>I just ran into an interesting issue while developing with Model-Glue. It took a couple of minutes to figure out so here is a quick reminder for both myself and anybody else using Model-Glue.

&lt;span style="font-weight: bold;"&gt;The scenario:&lt;/span&gt;
You are using multiple views to build your application template. This means that your template itself is composed of several views such as "reportsMenu", "applcationMenu", etc. The actual template file is defined as follows in the template event:&lt;pre class="code"&gt;&amp;lt;include name="template" template="dspApplicationTemplate.cfm" /&amp;gt;&lt;/pre&gt; To include the "applicationMenu" you do &lt;pre class="code"&gt;#viewcollection.getview("applicationMenu")#&lt;/pre&gt; somewhere in your dspApplicationTemplate.cfm

&lt;span style="font-weight: bold;"&gt;The gotcha:&lt;/span&gt;
The included view has to have &amp;lt;cfoutput&amp;gt; around the html even if there is no CF code to be ran.

The complete event definition:&lt;pre class="code"&gt;&amp;lt;event-handler name="applicationTemplate"&gt;
  &amp;lt;broadcasts&amp;gt;
   &amp;lt;message name="GetUsersWorkOrderTypes" /&amp;gt;
  &amp;lt;/broadcasts&amp;gt;

  &amp;lt;views&amp;gt;
   &amp;lt;include name="lookupWorkOrderForm" template="frmLookupWorkOrder.cfm" /&amp;gt;
   &amp;lt;include name="reportsMenu" template="dspReportsMenu.cfm" /&amp;gt;
   &amp;lt;include name="applicationMenu" template="dspApplicationMenu.cfm" /&amp;gt;
   &amp;lt;include name="template" template="dspApplicationTemplate.cfm" /&amp;gt;
  &amp;lt;/views&amp;gt;
 &amp;lt;/event-handler&amp;gt;&lt;/pre&gt;The "applicationMenu" view(dspApplicationMenu.cfm) iteself included the "lookupWorkOrderForm" and "reportsMenu". Unless I surrounded the html in the "reportsMenu" view (dspApplicationMenu.cfm) with &amp;lt;cfoutput&amp;gt;, it kept showing as an empty string.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-323050655863859790?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/323050655863859790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=323050655863859790' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/323050655863859790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/323050655863859790'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/08/model-glue-gotcha-bug-or-feature.html' title='Model-Glue Gotcha - Bug or Feature?'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6713772987311269093</id><published>2007-08-03T10:31:00.000-04:00</published><updated>2007-08-03T10:36:45.768-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Dev'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>Web Developer Toolbar - View Color Information</title><content type='html'>While trying to figure out what color the "Loading" indicator in Gmail uses, I was fooling around with the &lt;a href="http://chrispederick.com/work/web-developer/"&gt;Web Developer extension.&lt;/a&gt; So I found out that you can get all the colors used on a page by going to "Information" and click on "View Color Information". Click on it will open a new tab with all the colors used on the page you are looking at. Try it for yourself, it's pretty nice. The extension has about a million other options too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6713772987311269093?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6713772987311269093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6713772987311269093' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6713772987311269093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6713772987311269093'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/08/web-developer-toolbar-view-color.html' title='Web Developer Toolbar - View Color Information'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4894362743419249271</id><published>2007-08-03T09:05:00.000-04:00</published><updated>2007-08-03T09:11:56.078-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model-Glue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>How to Use Model-Glue Generic List</title><content type='html'>This not new information by any means. However, I always seem to forget how to do this so I have to dig through existing projects to find it. It's pretty damn useful so here it is:

&lt;pre class="code"&gt;
&amp;lt;message name="modelglue.genericlist"&amp;gt;
    &amp;lt;!-- Any criteria for filtering the returned query (such as UserName=boyan) --&amp;gt;
    &amp;lt;argument name="criteria" value="" /&amp;gt;
    &amp;lt;!-- The name of the table in the database --&amp;gt;
    &amp;lt;argument name="object" value="Users" /&amp;gt;
    &amp;lt;!-- The query name to store the results --&amp;gt;
    &amp;lt;argument name="queryName" value="usersList" /&amp;gt;
    &amp;lt;!-- Optional: use a custom query GetExistingUsersList from the UsersGatewayMSSQL gateway --&amp;gt;
    &amp;lt;argument name="gatewayMethod" value="GetExistingUsersList" /&amp;gt;
&amp;lt;/message&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4894362743419249271?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4894362743419249271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4894362743419249271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4894362743419249271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4894362743419249271'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/08/how-to-use-model-glue-generic-list.html' title='How to Use Model-Glue Generic List'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5922801799783130650</id><published>2007-07-26T10:15:00.001-04:00</published><updated>2007-07-26T10:15:10.234-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Prototype.js Add-ons</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I came across some add-ons based on Prototype. Here a small list:&lt;br/&gt;&lt;br/&gt;TableKit: &lt;a href='http://www.millstream.com.au/view/code/tablekit'&gt;http://www.millstream.com.au/view/code/tablekit&lt;/a&gt;&lt;br/&gt;Create sortable, resizable and editable tables&lt;br/&gt;&lt;br/&gt;Control Suite: &lt;a href='http://livepipe.net/projects/control_suite/'&gt;http://livepipe.net/projects/control_suite/&lt;/a&gt;&lt;br/&gt;From the website: "Collection of six high quality widgets and controls
for Web 2.0 applications built using the Prototype JavaScript framework"&lt;br/&gt;&lt;br/&gt;Tidbits: &lt;a href='http://livepipe.net/projects/prototype_tidbits/'&gt;http://livepipe.net/projects/prototype_tidbits/&lt;/a&gt;&lt;br/&gt;Odds and ends for the Prototype framework&lt;br/&gt;&lt;br/&gt;Window: &lt;a href='http://prototype-window.xilinus.com/'&gt;http://prototype-window.xilinus.com/&lt;/a&gt;&lt;br/&gt;Resizable/model/skinnable overlay window.&lt;br/&gt;&lt;br/&gt;LightWindow: &lt;a href='http://stickmanlabs.com/lightwindow/'&gt;http://stickmanlabs.com/lightwindow/&lt;/a&gt;&lt;br/&gt;Skinnable overlay window with many possibilities&lt;br/&gt;&lt;a href='http://livepipe.net/projects/control_suite/'/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5922801799783130650?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5922801799783130650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5922801799783130650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5922801799783130650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5922801799783130650'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/prototypejs-add-ons.html' title='Prototype.js Add-ons'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2493840798749453645</id><published>2007-07-24T13:57:00.000-04:00</published><updated>2007-07-24T14:08:58.913-04:00</updated><title type='text'>Execute JavaScript with cfSnippetExecutor</title><content type='html'>This might be a duh! for some but thought I'd blog about it anyway. You can execute JavaScript as well as CF with the cfSnippetExecutor. Here is an example:
&lt;pre class="code"&gt;
&amp;lt;-- Create a textarea for the results to be displayed --&amp;gt;
&amp;lt;textarea id="results" cols="80"&amp;gt;&amp;lt;/textarea&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
var htmlString = "&amp;lt;span&amp;gt;test&amp;lt;/span&amp;gt;";
// Replace the &amp;lt; and &amp;gt; with their safe counterparts
htmlString = htmlString.replace(/&amp;lt;/g, "&amp;amp;amp;lt;");
htmlString = htmlString.replace(/&amp;gt;/g, "&amp;amp;amp;gt;");

// Display the results
document.getElementById('results').innerHTML = htmlString;
&amp;lt;/script&amp;gt;
&amp;lt;--- Same code as above but in ColdFusion ---&amp;gt;
&amp;lt;cfset html = "&amp;lt;span&amp;gt;test&amp;lt;/span&amp;gt;" /&amp;gt;
&amp;lt;cfset html = html.replaceall("&amp;lt;", "&amp;amp;amp;lt;") /&amp;gt;
&amp;lt;cfset html = html.replaceall("&amp;gt;", "&amp;amp;amp;gt;") /&amp;gt;
&amp;lt;cfoutput&amp;gt;
&amp;lt;textarea cols="80"&amp;gt;#html#&amp;lt;/textarea&amp;gt;
&amp;lt;/cfoutput&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2493840798749453645?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2493840798749453645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2493840798749453645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2493840798749453645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2493840798749453645'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/execute-javascript-with.html' title='Execute JavaScript with cfSnippetExecutor'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7513852743218788263</id><published>2007-07-24T10:54:00.001-04:00</published><updated>2007-07-24T10:57:55.617-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>Gmail Type Loading Indicator Update</title><content type='html'>After Brian Love brought up different browsers in my previous post, I thought I'd see what it takes to make my example look exactly like Gmail's status in both IE and Firefox.

Here is the updated CSS. It's been tested with Firefox, IE6 and IE7 at 800x600, 1024x768 and 1280x1024. It includes a special margin definition for IE.
&lt;pre class="code"&gt;&amp;lt;style type="text/css"&amp;gt;
div#statusContainer {
 position: absolute;
 left: 0px;
 top: 0px;
 width: 100%;
 height: 10px;
}

div#statusMessageContainer {
 position: absolute;
 background-color: #cc4444;
 color: white;
 width: 60px;
 font-family: Arial, Helvetica, sans-serif;
 font-size: .8em;
 padding: 2px;
 right: 0px;
 margin-right: 15px;
}
&amp;lt;/style&amp;gt;
&amp;lt;!--[if IE]&amp;gt;
&amp;lt;style type="text/css" media="all"&amp;gt;
div#statusMessageContainer { margin-right: -20px; }
&amp;lt;/style&amp;gt;
&amp;lt;![endif]--&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7513852743218788263?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7513852743218788263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7513852743218788263' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7513852743218788263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7513852743218788263'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/gmail-type-loading-indicator-update.html' title='Gmail Type Loading Indicator Update'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-7457421286281835603</id><published>2007-07-23T15:23:00.001-04:00</published><updated>2007-07-23T15:27:14.943-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Using Query of Queries to Join Data from Different Sources</title><content type='html'>The current application I am working on has to have user security based on a employee's badge number. The badge number and the employee name are already stored in an external database (Syteline) which I can access through a SQL driver. When a new employee is added to the application, the application only needs to store the employee's badge number. Other associated data is also stored such as the role the user is in (admin, supervisor, etc.). The problem I ran into was that I needed to get all the data for each employee (badge, name and role). Query of queries to the rescue. With a little help from Ben Nadel (thank you!) here is how I joined both queries:
&lt;pre class="code"&gt;&amp;lt;!--- Get a list of existing users from the database ---&amp;gt;
&amp;lt;cfset existingUsersList = GetUsersList() /&amp;gt;

&amp;lt;!--- Get a list of users from Syteline but ignore the users
that already exist in the application ---&amp;gt;
&amp;lt;cfquery name="sytelineUsersList" datasource="ECDSiteDB"&amp;gt;
select  lcase(Fname) as FirstName,
   lcase(Lname) as LastName,
   ltrim(rtrim("Emp-Num")) as BadgeNumber
from  pub.employee
where    ltrim(rtrim("Emp-Num")) &amp;lt;&amp;gt; ''
   and
   ltrim(rtrim("Emp-Num")) in (#valuelist(existingUsersList.BadgeNumber)#)
order by LastName, FirstName
&amp;lt;/cfquery&amp;gt;

&amp;lt;!--- Join the two queries to get the user's name, badge and role name
The existingUsersList.BadgeNumber needs to be cast as a varchar since it's stored as
an interger in the application's Users table ---&amp;gt;
&amp;lt;cfquery name="usersList" dbtype="query"&amp;gt;
select  FirstName, LastName,
   sytelineUsersList.BadgeNumber,
   existingUsersList.Name as RoleName
from  sytelineUsersList, existingUsersList
where  sytelineUsersList.BadgeNumber = cast(existingUsersList.BadgeNumber as varchar)
order by LastName, FirstName
&amp;lt;/cfquery&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-7457421286281835603?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/7457421286281835603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=7457421286281835603' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7457421286281835603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/7457421286281835603'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/using-query-of-queries-to-join-data.html' title='Using Query of Queries to Join Data from Different Sources'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-6781224996010317879</id><published>2007-07-23T14:42:00.001-04:00</published><updated>2007-07-23T23:13:32.872-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reactor'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Using Reactor to Execute a Join Query</title><content type='html'>Let's say that you want to create a list of users with associated roles. You have a Users table and a Roles table defined in your database. The link between the two is the RoleID in the Users table that maps to the ID column in the Roles table.

Your reactor.xml should have the following to defined the relationship between the Users and the Roles tables:
&lt;pre class="code"&gt;&amp;lt;object name="Users"&amp;gt;
 &amp;lt;hasOne name="Roles"&amp;gt;
  &amp;lt;relate from="RoleID" to="ID" /&amp;gt;
 &amp;lt;/hasOne&amp;gt;
&amp;lt;/object&amp;gt;&lt;/pre&gt;
Inside the users gateway object (UsersGatewaymssql.cfc for the MS SQL Server version) instead of doing this:
&lt;pre class="code"&gt;&amp;lt;cffunction name="GetUsersList" access="public" output="false" returntype="query"&amp;gt;
 &amp;lt;cfset var usersList = 0 /&amp;gt;

 &amp;lt;!--- Get a list of users from the database with their associated roles ---&amp;gt;
 &amp;lt;cfquery name="usersList" datasource="#_getConfig().getDsn()#"&amp;gt;
 select  u.BadgeNumber, r.RoleID, r.Name
 from  dbo.Users as u
    inner join
    dbo.Roles as r
    on
    u.RoleID = r.ID
 &amp;lt;/cfquery&amp;gt;

 &amp;lt;cfreturn usersList /&amp;gt;
&amp;lt;/cffunction&amp;gt;&lt;/pre&gt;
You define the function as:
&lt;pre class="code"&gt;&amp;lt;cffunction name="GetUsersList" access="public" output="false" returntype="query"&amp;gt;
 &amp;lt;cfset var usersList = 0 /&amp;gt;

 &amp;lt;!--- Create a reactor query ---&amp;gt;
 &amp;lt;cfset query = this.createquery() /&amp;gt;

 &amp;lt;!--- Join the users and the roles tables ---&amp;gt;
 &amp;lt;cfset query.join('Users', 'Roles', 'Roles') /&amp;gt;

 &amp;lt;!--- Execute the query ---&amp;gt;
 &amp;lt;cfset usersList = this.getbyquery(query) /&amp;gt;

 &amp;lt;cfreturn usersList /&amp;gt;
&amp;lt;/cffunction&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-6781224996010317879?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/6781224996010317879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=6781224996010317879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6781224996010317879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/6781224996010317879'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/using-reactor-to-execute-join-query.html' title='Using Reactor to Execute a Join Query'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-3945214039960096912</id><published>2007-07-20T15:43:00.001-04:00</published><updated>2008-01-29T16:10:35.125-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>cfSnippetExecutor v0.1</title><content type='html'>How many time have you had to create ColdFusion pages in order to test some simple code. I have a dedicated virtual site to just test snippets. The directory is getting pretty full with random code files. The process so far has been:

1. Open the virtual site
2. Create an empty .cfm file
3. Write my code and save it
4. Go to the browser and run it

&lt;b&gt;Well, I'm tired of it!&lt;/b&gt;

So here is an initial draft to remedy the tedious task of testing cf code snippets. I'm calling it "cfSnippetExecutor". You can download it at &lt;a href="http://tech-cats.net/blog/downloads/coldFusion/cfSnippetExecutor.txt"&gt;http://tech-cats.net/blog/downloads/coldFusion/cfSnippetExecutor.txt&lt;/a&gt;

The idea is simple. Go to the cf page in your browser, paste in your code and hit "Run". The results of your code will be show up below. The only requirement is Prototype.js.
&lt;pre class="code"&gt;&amp;lt;cfsetting enablecfoutputonly="yes"&amp;gt;
&amp;lt;!--- Setup default parameters and constants ---&amp;gt;

&amp;lt;!--- Is this call to the page from javascript (Ajax) ---&amp;gt;
&amp;lt;cfparam name="url.isAjaxCall" default="false" /&amp;gt;
&amp;lt;cfparam name="url.testScript" default="" /&amp;gt;

&amp;lt;cfoutput&amp;gt;
&amp;lt;!---
If this is an ajax call, get the tracking results trackingPageUrl specified above ---&amp;gt;
&amp;lt;cfif url.isAjaxCall&amp;gt;
&amp;lt;cfif fileexists(expandpath('testInclude.cfm'))&amp;gt;
&amp;lt;cffile action="delete" file="#expandpath('testInclude.cfm')#" /&amp;gt;
&amp;lt;/cfif&amp;gt;

&amp;lt;cfsavecontent variable="testInclude"&amp;gt;#url.testScript#&amp;lt;/cfsavecontent&amp;gt;

&amp;lt;cfset testInclude = testInclude.replaceall("&amp;amp;lt;", "&amp;lt;") /&amp;gt;
&amp;lt;cfset testInclude = testInclude.replaceall("&amp;amp;gt;", "&amp;gt;") /&amp;gt;

&amp;lt;cffile action="write" file="#expandpath('testInclude.cfm')#" output="#testInclude#" /&amp;gt;

&amp;lt;cfinclude template="./testInclude.cfm" /&amp;gt;
&amp;lt;cfelse&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "&lt;a class="linkification-ext" href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" title="Linkification: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/a&gt;"&amp;gt;
&amp;lt;html xmlns="&lt;a class="linkification-ext" href="http://www.w3.org/1999/xhtml" title="Linkification: http://www.w3.org/1999/xhtml"&gt;http://www.w3.org/1999/xhtml&lt;/a&gt;"&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script type="text/javascript" src="prototype.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;style type="text/css"&amp;gt;
div##statusContainer { position:absolute;left:0px;top:0px;width:100%;height:10px; }
div##statusMessageContainer { position:absolute;background-color:##000000;color:white;width:80px;font-family:Arial, Helvetica, sans-serif;padding:2px;left:0px;font-weight:700; }
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;!--- This is not an ajax call, so display a form ---&amp;gt;
&amp;lt;form id="testForm" name="testForm" method="get"&amp;gt;
&amp;lt;input type="hidden" id="isAjaxCall" name="isAjaxCall" value="true" /&amp;gt;
&amp;lt;textarea name="testScript" cols="80" rows="10" id="testScript"&amp;gt;
&amp;lt;cfset testVar = "yourmom" /&amp;gt;
&amp;lt;cfdump var="#testVar#" /&amp;gt;
&amp;lt;/textarea&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;input type="submit" id="runScript" name="runScript" value="Run" /&amp;gt;
&amp;lt;!-- Status container that will be shown message durring processing ---&amp;gt;
&amp;lt;div id="statusContainer" style="display:none;"&amp;gt;
&amp;lt;div id="statusMessageContainer"&amp;gt;Loading...&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;!-- Results container that will be updated with the results of the tracking request ---&amp;gt;
&amp;lt;div id="testResults"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
Ajax.Responders.register({
onCreate: function() {
$('statusContainer').show();
},
onComplete: function() {
$('statusContainer').hide();
}
});

// Add an event observer to the form's submit
Event.observe(
'testForm',
'submit',
function(e){
GetResults('testForm', '#cgi.script_name#', 'testResults');
Event.stop(e);
}
);

/*
Function:  GetTrackingResults
Arguments:
  formID    string - the form id to be used in the request
  pageUrl    string - the page url to call for the results
  resultsContainer string - the container element to display the results in
Return Value: None
Description:
  Retrieves the contents of the results page with Ajax */
function GetResults(formID, pageUrl, resultsContainer)
{
var testScript = $('testScript').value.strip();

if (testScript != '') {
// Serialize the form parameters to pass them along as part of the form submission
var params = $(formID).serialize();

// Disable the form
$(formID).disable();

// Empty the contents of the results container
$(resultsContainer).update('');

// Make an ajax request with the 'get' method, passing it the serialized form
// and using 'ReportError' to show any errors
// and 'ProcessResults' to process the retrieved results
new Ajax.Updater(
 $(resultsContainer),
 pageUrl,
 {
 method: 'get',
 parameters: params,
 onFailure: function(request) { $(formID).enable(); },
 onSuccess: function() { $(formID).enable(); },
 evalScripts: true
 }
);
}
}

$('testScript').focus();
$('testScript').enable();
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&amp;lt;/cfif&amp;gt;
&amp;lt;/cfoutput&amp;gt;
&lt;/pre&gt;

&lt;a href="http://tech-cats.net/blog/downloads/coldFusion/cfSnippetExecutor.txt"&gt;Download cfSnippetExecutor&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-3945214039960096912?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/3945214039960096912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=3945214039960096912' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3945214039960096912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/3945214039960096912'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/cfsnippetexecutor-v01.html' title='cfSnippetExecutor v0.1'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-4685159819335030470</id><published>2007-07-20T11:30:00.001-04:00</published><updated>2007-07-20T11:32:06.950-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IIS'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Non-ColdFusion Document Security on Non-Shared Hosting</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Inspired by the blog post by Ben Nadel about  &lt;a href="http://www.bennadel.com/index.cfm?dax=blog:844.view"&gt;Simple Non-ColdFusion Document Security For Shared Hosting Environments&lt;/a&gt;, here is a simple solution for non-shared hosting (where you have control over IIS)

1. Setup a virtual directory in IIS
2. Go the the virtual directory properties and under the "main" tab click on the "Configuration" button
3. Add a application extension mapping for ".*" to be processed by the ColdFusion server: "C:\CFusionMX7\runtime\lib\wsconfig\1\jrun.dll" (or whatever your path to CF is)
4. Write some code in Application.cfc (or Application.cfm if you wish) to handle the security for each request.
&lt;p&gt;Now all requests (html, doc, etc.) should be first handed to ColdFusion.
&lt;/p&gt;&lt;p&gt;The pitfalls might be:
1. Not very scalable solution
2. Performance&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-4685159819335030470?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/4685159819335030470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=4685159819335030470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4685159819335030470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/4685159819335030470'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/non-coldfusion-document-security-on-non.html' title='Non-ColdFusion Document Security on Non-Shared Hosting'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-2667287167330133972</id><published>2007-07-20T09:05:00.001-04:00</published><updated>2007-07-20T09:05:50.449-04:00</updated><title type='text'>Mega Keyboard Shortcuts List</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Came across this list and I thought it was worth sharing:&lt;br/&gt;&lt;br/&gt;&lt;a href='http://www.smashingmagazine.com/2007/07/20/developers-alarm-200-hotkeys-to-boost-your-productivity/'&gt;Developer’s Alarm: 200+ Hotkeys To Boost Your Productivity&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Enjoy!&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-2667287167330133972?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/2667287167330133972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=2667287167330133972' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2667287167330133972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/2667287167330133972'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/mega-keyboard-shortcuts-list.html' title='Mega Keyboard Shortcuts List'/><author><name>Boyan Kostadinov</name><uri>https://profiles.google.com/106560991906301776392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-zjJy3-APe4g/AAAAAAAAAAI/AAAAAAAAAMc/e41cycHcgVQ/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7367794905551891931.post-5999826443782730215</id><published>2007-07-19T13:57:00.002-04:00</published><updated>2008-03-31T18:05:17.418-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Prototype'/><title type='text'>Prototype.js Show/Hide Element Gotcha</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;I like using Prototype.js since it's been around for a while and I already know most of it's methods. I mean to experiment with jQuery but have not gotten around it yet (a disclaimer for anybody meaning to flame me about using something else such as jQuery, mooTools or whatever else).

Anyway, a consistent gotcha for me is showing hidden elements after a certain action on the page. Lets take for example my statusContainer from the &lt;a href="http://boyank.blogspot.com/2007/07/gmail-style-ajax-status-message.html"&gt;Gmail Style Ajax Status Message&lt;/a&gt; post. I want the div to be hidden when the page loads. My two choices are:

1. Hide the div with JavaScript after the page has been loaded. With Prototype.js, I simply do:
&lt;pre name="code" class="js"&gt;$('statusContainer').hide();&lt;/pre&gt;or
2. Set the visibility style of the element to hidden:
&lt;pre name="code" class="js"&gt;&amp;lt;div style="visibility: hidden;" id="statusContainer"&amp;gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
I don't really like the first method since I shouldn't need JavaScript to have the element hidden at first. That leaves me with the second choice.

The gotcha is that when you try to use Prototype.js to show the element later with:
&lt;pre name="code" class="js"&gt;$('statusContainer').show();&lt;/pre&gt;nothing happens. Why not?

Doh! I keep forgetting that internally Prototype.js (at least v1.5.1_rc2 and v1.5.1.1) uses the display style property instead of visibility. So the above second option should say:
&lt;pre name="code" class="js"&gt;&amp;lt;div style="display: none;" id="statusContainer"&amp;gt;&amp;lt;/div&gt;&lt;/pre&gt;
With that change, using Prototype.js works fine:
&lt;pre name="code" class="js"&gt;$('statusContainer').show();&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7367794905551891931-5999826443782730215?l=blog.tech-cats.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tech-cats.com/feeds/5999826443782730215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7367794905551891931&amp;postID=5999826443782730215' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5999826443782730215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7367794905551891931/posts/default/5999826443782730215'/><link rel='alternate' type='text/html' href='http://blog.tech-cats.com/2007/07/prototypejs-showhide-element-gotcha.html' title='Prototype.js Show/Hide Element Gotcha'/><author><name>Boyan Kostadinov</name><uri>https://profile
