<?xml version="1.0" encoding="iso-8859-1"?>
<feed version="0.3"
  xmlns="http://purl.org/atom/ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xml:lang="en">
	<title>Marcus's Musings</title>
	<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/" />
	<tagline>THOUGHTS, TIPS, AND LINKS COVERING WEB DEVELOPMENT AND RELATED TOPICS</tagline>
	
	<modified>2005-06-02T14:16:35+01:00</modified>
	<copyright>Copyright 2004-2005</copyright>
	<generator url="http://www.uapplication.com/" version="Ublog Reload 1.0.5">Ublog Reload 1.0.5</generator>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Code Snippets (I)]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=68" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=68</id>
		<modified>2005-02-02T13:55:02+01:00</modified>
		<issued>2005-02-02T13:55:02+01:00</issued>
		<created>2005-02-02T13:55:02+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=68"><![CDATA[A few simple but handy snippets of code for you...<br /><br /><b>Kill</b><br />Firstly, since I use it in almost every function which uses objects, I thought I'd better repost Kill(), which tidies up objects and arrays, with special handling for ADO and Dictionary objects.<br /><br /><b>NOTE: All code posted on this blog from now on will assume that this function is part of your includes</b><br /><br /><pre>Function Kill(byref Obj)<br />	Select Case True<br />		Case IsObject(Obj)<br />			Select Case LCase(TypeName(Obj))<br />				Case "recordset", "command", "stream", "connection"<br />					'ADO objects<br />					If Obj.State <> 0 then<br />						Obj.Close<br />					End If<br />				<br />				case "dictionary"<br />					'remove all the pairs<br />					Obj.RemoveAll<br />					<br />				Case else<br />					'something else so don't<br />					'do anything special<br />					<br />			End Select<br />			<br />			Set Obj = Nothing<br />		<br />		Case IsArray(Obj)<br />			'clear the array<br />			Erase Obj<br />		<br />		Case Else<br />			'do nothing at all<br />			<br />	End Select<br />		<br />	'Now revert it to an unitialized state<br />	Obj = Empty<br />End Function</pre><br /><br /><br /><b>IsBlank</b><br />This is another of my most frequently used snippets, which acts as a catch-all checker for variables, meaning that you no longer have to worry about the variable type when you want to use a <b>If MyVar="" Then</b> statement. It will automatically test the variable using all the appropriate checks - see the code for exactly what it does and how. Simple, but remarkably handy! Give it a go next time you write a complicated script or entire app!<br /><br /><b>NOTE: All code posted on this blog from now on will assume that this function is part of your includes</b><br /><br /><pre>Function IsBlank(ByRef Var)<br />	IsBlank = False<br />	<br />	Select Case True<br />		Case IsObject(Var)<br />			If var Is Nothing Then<br />				IsBlank = True<br />			End If<br />		<br />		Case IsEmpty(Var), IsNull(Var)<br />			IsBlank = True<br />			<br />		Case IsArray(Var)<br />			If UBound(Var) = 0 Then<br />				IsBlank = True<br />			End If<br />		<br />		Case IsNumeric(Var)<br />			If (Var = 0) Then<br />				IsBlank = True<br />			End If<br />			<br />		Case Else<br />			If Trim(Var) = "" Then<br />				IsBlank = True<br />			End If<br />	End Select<br />End Function</pre><br /><br /><br /><b>ToggleVariable</b><br />Invaluable for all sorts of situations where variable needs to flip-flop between two values - one example being alternating colours for table rows.<br /><br /><pre>'Toggles a variable between two values, and will initalise<br />'the variable to the "on" state if it doesn't have either value<br />Function ToggleVariable(Byref Variable, ByVal StateOn, ByVal StateOff)<br />	If (Variable = StateOn) Then<br />		Variable = StateOff<br />	Else<br />		Variable = StateOn<br />	End If<br /><br />	ToggleVariable = Variable<br />End Function</pre>For example:<pre>For N = 1 To 10<br />	Response.Write "<" &amp; "tr bgcolor=""" &amp; ToggleVariable(C, "#ffaaaa", "#aaffaa") &amp; """>"<br />	Response.Write "<" &amp; "td>" &amp; N &amp; "<" &amp; "/td>"<br />	Response.Write "<" &amp; "/tr>"<br />Next</pre>(tags are broken up to circumvent posting problems in this blog)<br /><br />Note that although it's a function which returns the new value, it does directly modify the variable (because it's passed ByRef) and therefore can be called as a sub too:<br /><pre>For N = 1 To 10<br />	Call ToggleVariable(OddRowIndicator, True, False)<br />	If (OddRowIndicator = True) Then<br />		'do something here<br />	End If<br />Next</pre><br /><br /><br /><b>GetCurrentURL</b><br />Sometimes it's handy to know what the current URL is within your script, but strangely enough ASP doesn't expose this information directly, instead it must be assembled from various server variables. Here's a little function which does it for you:<br /><pre>Function GetCurrentURL()<br />	'Select the protocol<br />	If request.servervariables("HTTPS") = "on" Then<br />		GetCurrentURL = "https://"<br />	Else<br />		GetCurrentURL = "http://"<br />	End If<br />	<br />	GetCurrentURL = GetCurrentURL &amp; Request.ServerVariables("SERVER_NAME")<br />	<br />	If (Request.ServerVariables("SERVER_PORT") <> 80) Then<br />		GetCurrentURL = GetCurrentURL &amp; ":" &amp; Request.ServerVariables("SERVER_PORT")<br />	End If<br />	<br />	GetCurrentURL = GetCurrentURL &amp; Request.ServerVariables("URL")<br />	<br />	If (Request.QueryString <> "") Then<br />		GetCurrentURL = GetCurrentURL &amp; "?" &amp; Request.QueryString<br />	End If<br />End Function</pre><br /><br /><br /><b>IIf</b><br />And last but not least here's, a handy VBScript version of a VB statement which is also commonly used as a macro in C/C++. This snippet lets you condense a simple "If...Then...Else...End If" block into a single line.<br /><br /><pre>'Immediate If<br />Function IIf(Condition, ValueIfTrue, ValueIfFalse)<br />	If Condition Then<br />		IIf = ValueIfTrue<br />	Else<br />		IIf = ValueIfFalse<br />	End if<br />End Function</pre><br /><br />For example, you could turn this:<br /><pre>If IsNull(Price) Then<br />	Response.Write "(n/a)"<br />Else<br />	Response.Write Price<br />End If</pre><br />Into this:<br /><pre>Response.Write IIF(IsNull(Price), "(n/a)", Price)</pre>However, let me just make you aware of a slight caveat that presents itself when using this shorthand form...<br /><br />Let's say that we wanted to format the price as a number with 2 decimal places - one might naturally use <b>FormatNumber(Price, 2)</b> to do this and insert it into the code like so:<pre>Response.Write IIF(IsNull(Price), "(n/a)", FormatNumber(Price, 2))</pre>Unfortunately, this won't work. When you call a function or sub, all parameters are passed either ByRef or ByVal, but regardless it is either a variable (which may contain an object, array, or value) or a value which is passed. Therefore, all three parameters to the IIF function are evaluated before the function is called, and the resulting values are passed.<br /><br />The consequence of this is that if the variable <b>Price</b> is ever <b>Null</b>, the script will throw an error, because <b>FormatNumber()</b> chokes on <b>Nulls</b>. Therefore, be careful about how you use this and remember that is not quite a 1:1 replacement for the full statement block.<br /><br /><br />That's all for now, if you have any questions please post a comment and I'll be sure to answer it.]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[New demo of new trick of old dog]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=63" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=63</id>
		<modified>2005-01-19T13:19:03+01:00</modified>
		<issued>2005-01-19T13:19:03+01:00</issued>
		<created>2005-01-19T13:19:03+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=63"><![CDATA[A couple of posts back <a href="http://blog.marcustucker.com/blog_comment.asp?bi=60&amp;m=1&amp;y=2005" target="_blank">I shared my <b>GetFolderAsRecordset()</b> function</a>, but I forgot to post a related snippet of code - here's a function which returns the last modified date/time of the most recent file in a given folder, something which is pretty longwinded to do with the FSO, but with <b>GetFolderAsRecordset()</b> in place it only takes a couple of lines (you could compress it into 4 if you used the code inline):<br /><pre>Function GetMostRecentFileDate(FolderPath)<br />	Dim FolderRS<br />	Set FolderRS = GetFolderAsRecordset(FolderPath)<br />	If Not FolderRS.EOF Then<br />		FolderRS.Sort = "Modified DESC"<br />		GetMostRecentFileDate = FolderRS("Modified")<br />	Else<br />		GetMostRecentFileDate = Null<br />	End If<br />	Kill FolderRS<br />End Function</pre>This function comes in very handy for some data import systems that I wrote at work (each daily import file is a complete data set, not a delta, so I only need to select the most recent one to import - there may be many queued there under various circumstances). I'm sure that you can think of plenty of ways that you could use and adapt this for your own applications...]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Festive Merriment]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=61" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=61</id>
		<modified>2004-12-30T11:50:04+01:00</modified>
		<issued>2004-12-30T11:50:04+01:00</issued>
		<created>2004-12-30T11:50:04+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=61"><![CDATA[Just a quick post to wish you all a (belated) merry xmas and a happy new year! I hope you have a great time on friday night, and you'll be pleased to know that one of my new year's resolutions will be to post here more often.<br /><br />In the past calendar year the amount of hands-on coding that I've been doing has dropped dramatically (to virtually none at all), and I also left the forums at <a href="http://www.sitepoint.com/forums/" target="_blank">SitePoint.com</a> and <a href="http://www.codingforums.com/" target="_blank">Codingforums.com</a> because I felt that I'd devoted enough of my free time to helping others over the years and I thought that it was about time I spend more of my time doing other things. Well, I've certainly been busy in the evenings, and I've been having a great time, perhaps too much fun - I've been neglecting this blog and haven't done any ASP coding for myself (i.e. on my site) for a loooong time!<br /><br />However, in the coming months there's a few ASP projects that I'll be getting stuck into (both at work and at home), and so it's only natural that I'll start to post more frequently here. I'll share code where I can, and if there are any particular topics that you'd like me to cover, such as particularly complex techniques (multi-record form data processing, for example) then drop me a line and I'll see what I can do.<br /><br />See you in 2005!]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Old dog... new tricks?]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=60" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=60</id>
		<modified>2004-12-09T17:46:15+01:00</modified>
		<issued>2004-12-09T17:46:15+01:00</issued>
		<created>2004-12-09T17:46:15+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=60"><![CDATA[Most ASP developers seem to have jumped on the ASP.Net bandwagon already, but I thought I'd spread a little love among the remaining ASP classic developers by sharing some of the handy functions &amp; subs that I've developed over the years. I've been meaning to do this for a while, but I simply haven't got round to it until now... my apologies!<br /><br />I posted quite a few snippets of code on my <a href="http://marcustucker.com/blogold/" target="_blank">old blog</a>, so have a look at see if there's anything of interest to you there.<br /><br />One thing I mentioned there (and provided code for) was the concept of <a href="http://marcustucker.com/blogold/200403archive001.asp#1078918966001" target="_blank">disconnected recordsets</a>, but I didn't really go into what they can be used for, so here's one great use for them - directory listings.<br /><br />It is often desirable to manipulate a number of files (or subfolders) within a folder, but unfortunately doing so with the FSO is rather longwinded, particularly if you're only processing a subset of the files - all files in "c:\Gallery\" ending in ".jpg" which are less than 1MB in size. Wouldn't it be great if you could retrieve these as a list which could be iterated through?<br /><br />Well now you can - behold <b>GetFolderAsRecordset()</b>, a function I whipped up a while ago (and recently enhanced) which returns the contents of the specified folder as a disconnect recordset, with each file and folder represented as a record. The name, extension, size, created date, and last modified date of each item are represented as fields, there's a fields to indicate whether the item is a file or folder, and finally there's a field which indicates whether the item can be accessed (it may not if the process under which the script runs has insufficient rights to access the file/folder).<br /><br />By representing the folder in this way, a number of options are opened up. Firstly, the selection of certain files via particular criteria becomes simple, thanks to the <b>.Filter</b> property. For example, to turn the hypothetical mentioned earlier into reality, all you need to do is this:<br /><br /><pre>Set FolderContents = GetFolderAsRecordset("c:\Gallery\")<br />FolderContents.Filter = "Type='File' AND Extension='jpg' AND Size<" &amp; 1024^2<br /><br />While Not FolderContents.EOF<br />	'Do something here<br /><br />	FolderContents.MoveNext<br />Wend</pre><i>NOTE: The <b>Type='File'</b> criterion is needed because folders can have extensions too... I can't remember EVER giving a folder an extension, but it's been possible since MSDOS v1, so assume nothing!</i><br /><br />Secondly, by default the function groups the folder contents by type (folders and files) and then sorts alphabetically. However you can easily change this by setting the <b>.Sort</b> property (e.g. <b>FolderContents.Sort='Size DESC'</b>)<br /><br />Then, there's persistence and XML - by calling the recordset's native sub <b>.Save()</b> you can turn the recordset into XML, save it to disk, and then retrieve it another time. Alternatively, by specifying an ADO Stream object as the output rather than a file and then transforming the XML with some XSLT, you can generate a cleaner output (XML or otherwise) which could be used for all sorts of things (the response to software auto-update request, perhaps)<br /><br />Most people use recordsets for the retrieval and manipulation of tabular data, and this is no exception - it's childsplay to dump the recordset contents to an HTML table, and enabling sortable columns would take only a couple of lines of code! It could even form the part of one of those "file manager" web apps.. as if there aren't enough of those around already!<br /><br />I've recently used it as the core for an image batch processing script at work, and it's also very easily to modify the above snippet to generate a quick'n'dirty list of files which meet certain criteria (perhaps for pasting into an email) something which should be part of Windows Explorer, but sadly isn't (although I am aware that numerous directory listing shell extension utils have sprung up to fill this niche). Anyway, I hope you find it useful - it has certainly saved me hours of coding on numerous occasions!<br /><br />And now the moment you've all been waiting for - <a href="http://blog.marcustucker.com/public/files_upload/filemanip.txt" target="_blank">the code</a>! As well as the function discussed above, there are also a few handy wrapper functions for creating folders, moving files, copying files, deleting files, renaming files, etc. Nothing special, but it's nice to be able to call them as a one-liner!<br /><br />It would be nice to get some feedback, so if you find it useful or have problems/suggestions, please post a comment! If this goes down well I may be inclined to release more code in the near future... <img src="images/smile/smile2.gif" border="0" alt="[;)]" /><br /><br /><br /><i>NOTE: I have intentionally instantiated all objects in the code with a call to <b>CreateObject()</b> because the code is equally useful in Windows shell scripts, and by using the generic <b>CreateObject()</b> form, the code can be used for either without requiring changes. And in case you're wondering why you need to use the host-specific form at all (i.e. <b>Server.CreateObject()</b> or <b>WScript.CreateObject()</b>), you're not the only one! However, all-knowing scripting guru <a href="http://blogs.msdn.com/ericlippert/" target="_blank">Eric Lippert</a> was kind enough to provide <a href="http://blogs.msdn.com/ericlippert/archive/2004/06/01/145686.aspx" target="_blank">some answers</a> when I asked him a while ago, so read up (comments too)!</i>]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[New Article]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=51" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=51</id>
		<modified>2004-09-23T15:25:05+01:00</modified>
		<issued>2004-09-23T15:25:05+01:00</issued>
		<created>2004-09-23T15:25:05+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=51"><![CDATA[I've been away in Ibiza for a week (yes, I'll be posting photos soon) and I've just got back to find that the kind folks at <a href="http://www.asp101.com" target="_blank">ASP 101</a> have published my new article about <a href="http://www.asp101.com/articles/marcus/concatenation/default.asp" target="_blank">VBScript String Concatenation (And Why It Should Be Avoided Like The Plague)</a>.<br /><br />Let me know what you think!<br /><br /><img src="images/smile/smile1.gif" border="0" alt="[:)]" />]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Article no-no?!]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=46" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=46</id>
		<modified>2004-08-31T18:19:24+01:00</modified>
		<issued>2004-08-31T18:19:24+01:00</issued>
		<created>2004-08-31T18:19:24+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=46"><![CDATA[After waiting a month for it to be considered, <a href="http://www.sitepoint.com" target="_blank">SitePoint</a> got back to me to tell me that they aren't interested in publishing my article regarding VBScript string concatenation and scalable alternatives (a topic which is still very much ignored by ASP developers, and to their peril!) because they are "no longer actively covering ASP".<i>(or words to that effect - the quote is currently from memory, I'll post the exact quotation when I get home to Outlook)</i><br /><br />So that makes it official - as far as they are concerned, ASP is dead. Perhaps that's understandable - if not *actually* dead, it's *very nearly* dead, and taking its last steps down the path of obsolesence.<br /><br />However, that isn't stopping plenty of people from continuing to develop new applications in it - many developers haven't made the switch to .Net (myself included), so it's a real shame that they've decided that it's simply not worth catering to that particular audience at all any more. What's next? Shut down the ASP forum? I hope not.<br /><br />It's also rather disappointing on a personal level, because (for those of you who don't know) I've been the community-voted "SitePoint ASP Guru" for the past two years and <a href="http://blog.marcustucker.com/blog_comment.asp?bi=31&amp;m=8&amp;y=2004" target="_blank">recently resigned as Mentor</a>, so I wanted to have an article published there as a parting gift.<br /><br />Nevermind, I'll approach <a href="http://www.15seconds.com/" target="_blank">www.15seconds.com</a> (who published my first article "<a href="http://www.15seconds.com/issue/020919.htm" target="_blank">Do Stored Queries Increase the Speed of Access Queries?</a>") and see what they think... <img src="images/smile/smile2.gif" border="0" alt="[;)]" />]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Reading Roundup 20/08/2004]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=44" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=44</id>
		<modified>2004-08-20T17:27:57+01:00</modified>
		<issued>2004-08-20T17:27:57+01:00</issued>
		<created>2004-08-20T17:27:57+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=44"><![CDATA[<a href="http://blogs.msdn.com/ericlippert/archive/2004/08/19/217244.aspx" target="_blank">Error Handling in VBScript, Part One</a><br /><i>Eric continues to demystify the inner workings of the VBScript engine with another excellent post</i><br /><br />]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[ASP hints &amp; tips]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=35" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=35</id>
		<modified>2004-08-10T16:42:12+01:00</modified>
		<issued>2004-08-10T16:42:12+01:00</issued>
		<created>2004-08-10T16:42:12+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=35"><![CDATA[Here's an excellent site which I learned a lot from many years ago, and which I still link to in various forums posts here and there, but have never mentioned directly...<br /><br /><a href="http://www.motobit.com/" target="_blank">http://www.motobit.com/</a> (formerly www.pstruh.cz)<br /><br />Apart from having some great <a href="http://www.motobit.com/tips/listpg_0.htm" target="_blank">ASP coding tips</a>, Antonin Foller also offers one of the best script-only file upload processing scripts that I've seen (called "<a href="http://www.motobit.com/help/scptutl/upload.asp" target="_blank">Pure ASP Upload</a>"), which I drew ideas from when I wrote my own class.<br /><br />In any case, I highly recommend a browse through his site... you're sure to find something of interest!<br /><br /><img src="images/smile/smile2.gif" border="0" alt="[;)]" />]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Redundant Functions #1]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=27" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=27</id>
		<modified>2004-07-21T21:57:23+01:00</modified>
		<issued>2004-07-21T21:57:23+01:00</issued>
		<created>2004-07-21T21:57:23+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=27"><![CDATA[The <a href="http://msdn.microsoft.com/library/en-us/script56/html/vsfctRGB.asp" target="_blank">VBScript RGB() function</a>.... Ever used it? No, me neither, and I don't think that's going to change...! <img src="images/smile/smile17.gif" border="0" alt="[:p]" /><br /><br /><i>And surely the extra function in the example should be called "BGR()", not "RevRGB()"?!</i>]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Typelib recall!]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=22" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=22</id>
		<modified>2004-06-07T04:42:58+01:00</modified>
		<issued>2004-06-07T04:42:58+01:00</issued>
		<created>2004-06-07T04:42:58+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=22"><![CDATA[When giving ASP advice in the various forums that I frequent, I've always recommended that ASP'ers abandon the old-style ADOVBS.INC inclusion file for their constants, and instead turn to direct Typelib importing via a METADATA tag.<br /><br />However, it would appear from the Microsoft Scripting guru himself (that would be Eric Lippert, btw) that <a href="http://blogs.msdn.com/ericlippert/archive/2004/06/01/145686.aspx#147004" target="_blank">importing typelibs is in fact significantly slower than using constants defined in a script</a>... <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /> <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /> <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /><br /><br />I've grabbed the latest ADOVBS.INC from the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=5067faf8-0db4-429a-b502-de4329c8c850&amp;displaylang=en" target="_blank">Microsoft MDAC 2.8 SDK</a> and have made it available for download <a href="http://blog.marcustucker.com/public/files_upload/adovbs.inc" target="_blank">here</a>.<br /><br />It would appear that it was last updated in 1998 (presumably there haven't been any new constants defined since then), so you may have it already, but please check, because some sources are still offering earlier versions, such as <a href="http://www.4guysfromrolla.com/webtech/faq/Beginner/faq7.shtml" target="_blank">4GuysFromRolla</a> (which offers the 1996 version, and lacks many newer constants, such as those relating to the rather handy <b>ADO.Stream</b> object).<br /><br />I hereby formally retract all previous recommendations of using typelib importing... for ASP anyway, the performance hit isn't an issue in WSH, so you should still <a href="http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/wsh/htm/wsEleReference.asp" target="_blank">use it for that scripting environment</a>.<br /><br />I suggest that if you want to squeeze every last drop of performance out of your web app, you should go back to using ADOVBS.INC.<br /><br />However, it's not worth losing sleep over - don't forget that everything's not always all about performance... importing typelibs is a little tidier and is futureproof so long as you don't specify the version.]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[More XML DOM caching + Access stored queries]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=18" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=18</id>
		<modified>2004-05-24T07:35:06+01:00</modified>
		<issued>2004-05-24T07:35:06+01:00</issued>
		<created>2004-05-24T07:35:06+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=18"><![CDATA[I've been doing some PC housekeeping and rediscovered a couple of excellent articles that relate to storing an XML DOM in-memory (i.e. in the Session or Application collections), and I can highly recommend giving them a good read:<br /><br /><a href=&quot;http://www.15seconds.com/issue/010409.htm&quot; target=&quot;_blank&quot;>Creating an In-Memory Database Using XML and XPath -- Part 1</a><br /><a href=&quot;http://www.15seconds.com/issue/010410.htm&quot; target=&quot;_blank&quot;>Creating an In-Memory Database Using XML and XPath -- Part 2</a><br /><br />While I'm citing articles at <a href=&quot;http://www.15seconds.com&quot; target=&quot;_blank&quot;>15Seconds.com</a>, here's a good article from 15Seconds on what to take into consideration when optimizing database performance:<br /><br /><a href=&quot;http://www.15seconds.com/issue/040115.htm&quot; target=&quot;_blank&quot;>Database Performance Philosophy</a><br /><br />And finally, those of you persisting on using a JET4/Access database as a backend for your site might be interested to read the following 15 Seconds article written a while ago by yours truly, covering the significant peformance increases available from Access stored queries (as well as testing the best performing query execution syntax):<br /><br /><a href=&quot;http://www.15seconds.com/issue/020919.htm&quot; target=&quot;_blank&quot;>Do Stored Queries Increase the Speed of Access Queries?</a><br /><br /><i>Note to self: what a dumb title!</i>]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[Microsoft bad practice shocker!]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=15" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=15</id>
		<modified>2004-05-13T10:24:42+01:00</modified>
		<issued>2004-05-13T10:24:42+01:00</issued>
		<created>2004-05-13T10:24:42+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=15"><![CDATA[While researching my response to the issue raised in <a href=&quot;http://www.sitepoint.com/forums/showthread.php?t=168599&quot; target=&quot;_blank&quot;>a thread at SPF</a>, I made a startling discovery...<br /><br />Many years ago, giving ASP include files &quot;.INC&quot; extensions was considered standard practice, until the huge problem with this approach became evident - the full source code of these files (yes, the ASP source code, including all comments) could be retrieved simply by accessing the URL of the include file!! This worked because IIS was (by default) configured to serve requests for .ASP and .ASA files through the ASP engine, but .INC files were served up as plain text, thereby disclosing their contents!<br /><br />This potentially *huge* security flaw - huge because exposing business logic is bad enough, but lots of bad developers like to hardcode IPs, database names, and even usernames &amp; passwords, which if exposed to outsiders could be expoited to devastating effect - quickly became known throughout the ASP development (and of course hacking) communities via various security bulletins and articles (<a href=&quot;http://www.4guysfromrolla.com/webtech/020400-2.shtml&quot; target=&quot;_blank&quot;>this</a> being one... I don't have time to track down more right now - I should have gone to bed hours ago but keep getting sidetracked), and include files were renamed to have &quot;.ASP&quot; extensions instead.<br /><br />Another alternative fix was to simply remove world-readable permissions from the include folder of the web site. Even better was to do *both* just in case another vulnerability exposed the files' contents again, which is precisely what happened with the &quot;::$DATA&quot; flaw (or did that one come first, I don't recall)...<br /><br />Anyway, this all happened about 6 years ago (I think), but lo and behold, what do I find in the Microsoft ASP documentation, referred to every day by countless developers in their local IIS help files, the platform SDK and <a href=&quot;http://msdn.microsoft.com/library/en-us/iissdk/iis/ref_ssi_include.asp?frame=true&quot; target=&quot;_blank&quot;>online at MSDN</a>??<br /><br />I'll tell you what... this:<blockquote><b><i>Included files can have any file name extension, but a recommended practice is to give them the .inc extension.</i></b></blockquote>WHAT?!!! <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /> <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /> <img src="images/smile/smile21.gif" border="0" alt="[:eek:]" /> <br /><br />Years after this practice became virtually outlawed, Microsoft still *recommend* it?! I wonder how many developers are blindly following this and STILL giving their include scripts &quot;.INC&quot; extensions, thereby potentially exposing their source code to the world (or at least to malicious individuals)?!!<br /><br />Naturally, I've made the appropriate feedback submission to the MSDN site, but I wonder how long it will take to fix this astonishing blooper... start your watches please, gentlemen!]]></content>
	</entry>

	<entry>
	  	<author>
			<name>Marcus</name>
			<email>me@marcustucker.com</email>
		</author>
		<title><![CDATA[XML DOM caching]]></title>
		<link rel="alternate" type="text/html" href="http://blog.marcustucker.com/blog_comment.asp?bi=14" />
		<id>http://blog.marcustucker.com/blog_comment.asp?bi=14</id>
		<modified>2004-05-10T11:15:14+01:00</modified>
		<issued>2004-05-10T11:15:14+01:00</issued>
		<created>2004-05-10T11:15:14+01:00</created>
		<content type="text/html" mode="escaped" xml:base="http://blog.marcustucker.com/blog_comment.asp?bi=14"><![CDATA[Since it cropped up in <a href=&quot;http://www.sitepoint.com/forums/showthread.php?t=167720&quot; target=&quot;_blank&quot;>a recent thread</a> at <a href=&quot;http://www.sitepoint.com/forums/&quot; target=&quot;_blank&quot;>Sitepoint Forums</a>, I thought I'd quickly revisit the topic of caching XML, which <a href=&quot;http://marcustucker.com/blogold/200404archive001.asp#1082024194001&quot; target=&quot;_blank&quot;>I touched on briefly last month</a>.<br /><br />Since (in the web app I'm developing) I need to store hierarchical navigation &amp; security data which is queried and rendered on every page but which is not modified within the app itself, XML is the logical choice, and being able to cache the parsed XML and XSLT documents to minimize the marginal cost of each hit is the icing on the cake.<br /><br />I load the main document into a free-threaded XMLDOM object, and store it in an application variable. The XSLT is stored in an XSLTemplate object in a similar way. The menu is then rendered dynamically using 4 parameters, and the security is enforced by direct queries of the DOM. This allows me to include this functionality easily in pages in the site, and eliminate (at least) two database calls on every page (which would have been needed had I approached the problem with a database backend).<br /><br />However, using this approach is clearly only suitable for data which is not being changed, since the data must be modified sequentially by each page thread (rather than concurrently), because otherwise data will be lost. This is nothing new, and is precisely why the Application.Lock and Application.UnLock methods are there, but (in theory) it severely reduces the server throughput, since each page modifying the data must queue up to read it, as must each page reading it, otherwise it's possible that a read might occur in the middle of a write. Also, since the .Lock and .UnLock methods operate on the entire Application collection (not just the variable you're modifying or reading), the performance hit may be even more significant that you might expect.<br /><br />It's also worth mentioning that any data stored in the application or session collections is lost when the application is ended/restarted (both) or the session is ended/expires (only the latter), so if it's important you must save the data BEFORE these events occur to ensure that you don't lose valuable data! Again, since my data is read from files on disk, this is no problem.<br /><br />So, if you need to modify the data regularly (such as in a shopping cart application, as in the example in the thread - see earlier) you should use a data storage medium which is stateless so that you never lose data, for which a database is ideal.<br /><br />While you *could* save the XMLDOM back to disk every time you modify it, it's rather costly in terms of performance and will probably negate any gains you made by choosing a XML DOM in the first place!!]]></content>
	</entry>

</feed>