<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Robert McMurray's Blog [MSFT]</title><link>http://blogs.msdn.com/b/robert_mcmurray/</link><description>Discussing IIS, FTP, WebDAV, FPSE, WMI, ADSI, ISAPI, ASP, FastCGI, etc. ;-)</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/RobertMcMurraysMsdnBlog" /><feedburner:info uri="robertmcmurraysmsdnblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Adding Custom FTP Providers with the IIS Configuration Editor - Part 2</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/e1sLEZLyMuw/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-2.aspx</link><pubDate>Fri, 03 May 2013 01:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10415792</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/05/02/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-2.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/31/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx" target="_blank"&gt;Part 1 of this blog series&lt;/a&gt; about adding custom FTP providers with the &lt;strong style="font-weight: bold;"&gt;IIS Configuration Editor&lt;/strong&gt;, I showed you how to add a custom FTP provider with a custom setting for the provider that is stored in your IIS configuration settings. For my examples, I showed how to do this by using both the AppCmd.exe application from a command line and by using the &lt;strong style="font-weight: bold;"&gt;IIS Configuration Editor&lt;/strong&gt;. In part 2 of this blog series, I will show you how to use the IIS Configuration Editor to add custom FTP providers to your FTP sites.&lt;/p&gt;
&lt;p&gt;As a brief review from Part 1, the following XML excerpt illustrates what the provider's settings should resemble when added to your IIS settings:&lt;/p&gt;
&lt;p style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&lt;code&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerDefinitions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization"&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization, FtpXmlAuthorization, version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;activation&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerData&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization"&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="xmlFileName"&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="C:\inetpub\FtpUsers\Users.xml"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerData&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;activation&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerDefinitions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The above example shows the settings that are added globally to register an FTP provider. Note that this example only contains the settings for my custom provider; you would normally see the settings for the &lt;em style="font-style: italic;"&gt;IisManagerAuth&lt;/em&gt; and &lt;em style="font-style: italic;"&gt;AspNetAuth&lt;/em&gt; providers that ship with the FTP service in the &lt;strong style="font-weight: bold;"&gt;providerDefinitions&lt;/strong&gt; collection.&lt;/p&gt;
&lt;p&gt;To actually use a provider for an FTP site, you would need to add the provider to the settings for the FTP site in your IIS settings. So for part 2 of this blog series, we will focus on how to add a custom provider to an FTP site by using the IIS Configuration Editor.&lt;/p&gt;
&lt;p&gt;Having said all of that, the rest of this blog is broken down into the following sections:&lt;/p&gt;
&lt;ul&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#01"&gt;Step 1 - Looking at the configuration settings for custom FTP providers&lt;/a&gt;&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#02"&gt;Step 2 - Navigate to an FTP Site in the Configuration Editor&lt;/a&gt;&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#03"&gt;Step 3 - Add custom FTP providers to an FTP site&lt;/a&gt;
&lt;ul&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#03a"&gt;Add a custom FTP provider to an FTP site that is not used for authentication&lt;/a&gt;&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#03b"&gt;Add a custom FTP authentication provider to an FTP site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#04"&gt;Summary and Parting Thoughts&lt;/a&gt;
&lt;ul&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#04a"&gt;Disabling Custom User Isolation&lt;/a&gt;&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;a href="#04b"&gt;Additional Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before continuing, I should reiterate that custom FTP providers fall into two categories: providers that are used for authentication and providers that are used for everything else. This distinction is important, because the settings are stored in different sections of your IIS settings. With that in mind, let's take a look at the settings for an example FTP site.&lt;/p&gt;
&lt;h3 id="01"&gt;Step 1 - Looking at the configuration settings for custom FTP providers&lt;/h3&gt;
&lt;p&gt;The following example shows an FTP site with several custom FTP providers added:&lt;/p&gt;
&lt;p style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&lt;code&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;site&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ftp.contoso.com"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="2"&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;application&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;path&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/"&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;virtualDirectory&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;path&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/"&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;physicalPath&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="c:\inetpub\www.contoso.com\wwwroot"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;application&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;bindings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;binding&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;protocol&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ftp"&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;bindingInformation&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="*:21:ftp.contoso.com"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;bindings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;security&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ssl&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;controlChannelPolicy&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="SslAllow"&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;dataChannelPolicy&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="SslAllow"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;authentication&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customAuthentication&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="MyCustomFtpAuthenticationProvider"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customAuthentication&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;authentication&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;security&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customFeatures&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="MyCustomFtpHomeDirectoryProvider"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="MyCustomFtpLoggingProvider"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customFeatures&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;userIsolation&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;mode&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Custom"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;site&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you look at the above example, you will notice the following providers have been added:&lt;/p&gt;
&lt;ul&gt;
&lt;li style="line-height: 150%;"&gt;A custom FTP authentication provider named &lt;em style="font-style: italic;"&gt;MyCustomFtpAuthenticationProvider&lt;/em&gt; has been added to the &lt;strong style="font-weight: bold;"&gt;ftpServer/security/authentication/customAuthentication/providers&lt;/strong&gt; collection; this provider will obviously be used by the FTP service to validate usernames and passwords.&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;A custom FTP home directory provider named &lt;em style="font-style: italic;"&gt;MyCustomFtpHomeDirectoryProvider&lt;/em&gt; has been added to the &lt;strong style="font-weight: bold;"&gt;ftpServer/customFeatures/providers&lt;/strong&gt; collection; this will be used by the FTP service for custom user isolation. Note the mode for the &lt;strong style="font-weight: bold;"&gt;userIsolation&lt;/strong&gt; element is set to &lt;em style="font-style: italic;"&gt;custom&lt;/em&gt;.&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;A custom FTP logging provider named &lt;em style="font-style: italic;"&gt;MyCustomFtpLoggingProvider&lt;/em&gt; has been added to the &lt;strong style="font-weight: bold;"&gt;ftpServer/customFeatures/providers&lt;/strong&gt; collection; this will be used by the FTP service for creating custom log files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I mentioned earlier, you will notice that the settings for FTP custom providers are stored in different sections of the &lt;strong style="font-weight: bold;"&gt;ftpServer&lt;/strong&gt; collection depending on whether they are used for authentication or some other purpose.&lt;/p&gt;
&lt;h3 id="02"&gt;Step 2 - Navigate to an FTP Site in the Configuration Editor&lt;/h3&gt;
&lt;p&gt;Open the IIS Manager and click on the &lt;strong style="font-weight: bold;"&gt;Configuration Editor&lt;/strong&gt; at feature the server level:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pQvThdGUL69bzTfejtWrotYf19S9U8EY_B0pZZGyFMV5j4byqCs79COKdwI8q8H5VbZ6SC_DLwtJM1gGrw_1OoAp1LObGEK9w/AddingCustomProviders01.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pQvThdGUL69bzTfejtWrotYf19S9U8EY_B0pZZGyFMV5j4byqCs79COKdwI8q8H5VbZ6SC_DLwtJM1gGrw_1OoAp1LObGEK9w/AddingCustomProviders01.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click the &lt;strong style="font-weight: bold;"&gt;Section&lt;/strong&gt; drop-down menu, expand the the &lt;strong style="font-weight: bold;"&gt;system.applicationHost&lt;/strong&gt; collection, and then highlight the &lt;strong style="font-weight: bold;"&gt;sites&lt;/strong&gt; node:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pu5iskSfCSaGpGydHZd9zu_cecxqfAORlWQtWFWeGydI-mOUzfJBRvuQc0bGSMYF6X50FkCbFesX4_Gh152O-7Tj20Td9e_QhRm7Gbeu2mgNRPJAqLFSwE9IefMhdZwPL/AddingCustomProviders11.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pu5iskSfCSaGpGydHZd9zu_cecxqfAORlWQtWFWeGydI-mOUzfJBRvuQc0bGSMYF6X50FkCbFesX4_Gh152O-7Tj20Td9e_QhRm7Gbeu2mgNRPJAqLFSwE9IefMhdZwPL/AddingCustomProviders11.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you click on the &lt;strong style="font-weight: bold;"&gt;Collection&lt;/strong&gt; row, an ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt; will appear:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p_yuNw-NF2WsxTKZb_SWWArwgJ7nqVxsPyUoJmqknLcU0Z5LtANYIzs-bcPW9L46KqCHhVYkxScmVonQPadl8fga1IaqVwZhz7EbDl8EIKkt0ZIAxl-E2QmUMdDODj5iX/AddingCustomProviders12.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p_yuNw-NF2WsxTKZb_SWWArwgJ7nqVxsPyUoJmqknLcU0Z5LtANYIzs-bcPW9L46KqCHhVYkxScmVonQPadl8fga1IaqVwZhz7EbDl8EIKkt0ZIAxl-E2QmUMdDODj5iX/AddingCustomProviders12.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you click the ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt;, IIS will display the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your sites; both HTTP and FTP sites will be displayed:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2ppYyXeVWUDkLuLSuKpMdue6_abaDYqXUfIDs_jeKsmjhpK34PlK7GorZLg0djB7KfLb9x02nsBnLJykWA9GlAutt2yhhxdAEsiABt7BP0kLQauo9w3i7_kCnm_DXuWkZc/AddingCustomProviders13.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2ppYyXeVWUDkLuLSuKpMdue6_abaDYqXUfIDs_jeKsmjhpK34PlK7GorZLg0djB7KfLb9x02nsBnLJykWA9GlAutt2yhhxdAEsiABt7BP0kLQauo9w3i7_kCnm_DXuWkZc/AddingCustomProviders13.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Expand the &lt;strong style="font-weight: bold;"&gt;ftpServer&lt;/strong&gt; node, which is where all of the site-level settings for an FTP site are kept.&lt;/p&gt;
&lt;h3 id="03"&gt;Step 3 - Add custom FTP providers to an FTP site&lt;/h3&gt;
&lt;p&gt;As I mentioned earlier, custom FTP providers fall into two categories: providers that are used for authentication and everything else. Because of this distinction, the following steps show you how to add a provider to the correct section of your settings depending on the provider's purpose.&lt;/p&gt;
&lt;h4 id="03a"&gt;Add a custom FTP provider to an FTP site that is not used for authentication&lt;/h4&gt;
&lt;p&gt;Expand the &lt;strong style="font-weight: bold;"&gt;customFeatures&lt;/strong&gt; node, which is located under the &lt;strong style="font-weight: bold;"&gt;ftpServer&lt;/strong&gt; node for an FTP site; this collection defines the custom providers for an FTP site that are not used for authentication, for example: home directory providers, logging providers, etc. When you highlight the &lt;strong style="font-weight: bold;"&gt;providers&lt;/strong&gt; row, an ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt; will appear:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pfpeQGbV0Et6_obort5Ta6-pGMbAvWOD5nefxlXcVViSrpL--G3R1E0HL5Y7RDaEL9WjP0QagmpIcC7v41HpBNZ4uuHU5GOYhASiOCpnfYzd_JgnIXHrz6kdSLZMSTc1v/AddingCustomProviders14.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pfpeQGbV0Et6_obort5Ta6-pGMbAvWOD5nefxlXcVViSrpL--G3R1E0HL5Y7RDaEL9WjP0QagmpIcC7v41HpBNZ4uuHU5GOYhASiOCpnfYzd_JgnIXHrz6kdSLZMSTc1v/AddingCustomProviders14.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you click the ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt;, IIS will display the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your custom features (providers). When you click &lt;strong style="font-weight: bold;"&gt;Add&lt;/strong&gt; in the &lt;strong style="font-weight: bold;"&gt;Actions&lt;/strong&gt; pane, you need to enter the name of an FTP provider that you entered by following the instructions in &lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/31/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx" target="_blank"&gt;Part 1 of this blog series&lt;/a&gt;:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pJsI5DI1X53ld7QN1wDy5UnWDjkD0MQZVmvBenffUH6XQqjBtuS_GhYzP6jc6mC-RBLeorySlC8rr-KMuMlGuNEI9NzsIFz8p2jhJqJakTd0LzXBeWf0E4ZXfzKDOag1Y/AddingCustomProviders15.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pJsI5DI1X53ld7QN1wDy5UnWDjkD0MQZVmvBenffUH6XQqjBtuS_GhYzP6jc6mC-RBLeorySlC8rr-KMuMlGuNEI9NzsIFz8p2jhJqJakTd0LzXBeWf0E4ZXfzKDOag1Y/AddingCustomProviders15.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you enter the name of your FTP provider in the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your custom features, you can close that dialog box. The &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; for your sites will reflect the updated provider count for your FTP site:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pWAk5VbdUYk7N-yuWehl93bZHGRcelTodMLkgFkIF0l97ptyNgn4WAqMdoUNXf3R_weLFUI_MNYljQ6i3bFsd8Q1Eu3OAGH9-vEVG7H0V-vsJd-skPW5B6iYqoocRinZQ/AddingCustomProviders16.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pWAk5VbdUYk7N-yuWehl93bZHGRcelTodMLkgFkIF0l97ptyNgn4WAqMdoUNXf3R_weLFUI_MNYljQ6i3bFsd8Q1Eu3OAGH9-vEVG7H0V-vsJd-skPW5B6iYqoocRinZQ/AddingCustomProviders16.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong style="font-weight: bold;"&gt;Important Note&lt;/strong&gt;: If you are adding a custom FTP Home Directory Provider, you have to configure the mode for FTP's User Isolation features. To do so, you need to expand the userIsolation node, which is located under the &lt;strong style="font-weight: bold;"&gt;ftpServer&lt;/strong&gt; node for an FTP site. Once you have done so, click the &lt;strong style="font-weight: bold;"&gt;mode&lt;/strong&gt; drop-down menu and choose &lt;strong style="font-weight: bold;"&gt;Custom&lt;/strong&gt; from the list of choices:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p2OpSUOMUd1Hxz3UiGhZnjRuh2B_UI8yxVzsXdLqh4IsP9z12fR-k_towyhWaqBBTxd43NmfLkyTkiek5o6V7JdQix2LmzoyoUANeY350HUsVf0Q6lqZ3Iwgoo1szmpk2/AddingCustomProviders17.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p2OpSUOMUd1Hxz3UiGhZnjRuh2B_UI8yxVzsXdLqh4IsP9z12fR-k_towyhWaqBBTxd43NmfLkyTkiek5o6V7JdQix2LmzoyoUANeY350HUsVf0Q6lqZ3Iwgoo1szmpk2/AddingCustomProviders17.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you close the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your sites, you need to click &lt;strong style="font-weight: bold;"&gt;Apply&lt;/strong&gt; in the &lt;strong style="font-weight: bold;"&gt;Actions&lt;/strong&gt; pane to commit the changes to your IIS settings:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p5cohl6iKW0UPNV_IQTB_bDNTVQOrTOwTmbUR_X7RfZRQnQS3CCAYReMqa5YDYOrf8Zd7u59D-vl7g_dsn_JILRyiOhr4XJYC_0U4uw1WAqnos98EOsHWreEmw8TuvBGc/AddingCustomProviders18.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p5cohl6iKW0UPNV_IQTB_bDNTVQOrTOwTmbUR_X7RfZRQnQS3CCAYReMqa5YDYOrf8Zd7u59D-vl7g_dsn_JILRyiOhr4XJYC_0U4uw1WAqnos98EOsHWreEmw8TuvBGc/AddingCustomProviders18.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="03b"&gt;Add a custom FTP authentication provider to an FTP site&lt;/h4&gt;
&lt;p&gt;First and foremost - there is built-in support for adding custom authentication providers in IIS Manager; to see the steps to do so, see the &lt;em style="font-style: italic;"&gt;&lt;a href="http://www.iis.net/configreference/system.applicationhost/sites/site/ftpserver/security/authentication/customauthentication" target="_blank"&gt;FTP Custom Authentication &amp;lt;customAuthentication&amp;gt;&lt;/a&gt;&lt;/em&gt; article on the IIS.NET website. However, if you &lt;em style="font-style: italic;"&gt;want&lt;/em&gt; to add a custom FTP authentication provider to an FTP site by using the IIS Configuration Editor, you can do so by using the following steps.&lt;/p&gt;
&lt;p&gt;Expand the &lt;strong style="font-weight: bold;"&gt;security&lt;/strong&gt; node under the &lt;strong style="font-weight: bold;"&gt;ftpServer&lt;/strong&gt; node for an FTP site, then expand the &lt;strong style="font-weight: bold;"&gt;authentication&lt;/strong&gt; node, and then expand the &lt;strong style="font-weight: bold;"&gt;customAuthentication&lt;/strong&gt; node; this collection defines the custom authentication providers for an FTP site. When you highlight the &lt;strong style="font-weight: bold;"&gt;providers&lt;/strong&gt; row, an ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt; will appear:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p9qjk1U2qoectIEAkRwAOXdK7VJo922SK6YVJEomgskonse1Nci4Hg2fUoVqe4BHs2eLmmyr6IHHCcNxQRZclFSt6ELPOpELSxRU9Rom-uMVTxfCXWLJNTWO5B9RtHQtT/AddingCustomProviders19.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p9qjk1U2qoectIEAkRwAOXdK7VJo922SK6YVJEomgskonse1Nci4Hg2fUoVqe4BHs2eLmmyr6IHHCcNxQRZclFSt6ELPOpELSxRU9Rom-uMVTxfCXWLJNTWO5B9RtHQtT/AddingCustomProviders19.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you click the ellipsis &lt;strong style="font-weight: bold;"&gt;[...]&lt;/strong&gt;, IIS will display the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your custom authentication providers. When you click &lt;strong style="font-weight: bold;"&gt;Add&lt;/strong&gt; in the &lt;strong style="font-weight: bold;"&gt;Actions&lt;/strong&gt; pane, you need to enter the name of an FTP authentication provider that you entered by following the instructions in &lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/31/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx" target="_blank"&gt;Part 1 of this blog series&lt;/a&gt;:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pToyxUBEMIH2PvciZJlRpcQDeWSy31EpJ-6Q6sBRCNP_iJk4SI3E8e5yGWPJtExuJsgg96LmloU3zxYNDrVVtc6VGif_UyEivhFTMlQ5ckohnnvbg0kWEAmF6_GQ25MWG/AddingCustomProviders20.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pToyxUBEMIH2PvciZJlRpcQDeWSy31EpJ-6Q6sBRCNP_iJk4SI3E8e5yGWPJtExuJsgg96LmloU3zxYNDrVVtc6VGif_UyEivhFTMlQ5ckohnnvbg0kWEAmF6_GQ25MWG/AddingCustomProviders20.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you enter the name of your FTP authentication provider in the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your custom authentication providers, you can close that dialog box. The &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; for your sites will reflect the updated authentication provider count for your FTP site:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p22RRclHKkdMfozIC0fL021JHxI02GyBNysyc_U-Ewsxdw9dA5pCcWQLFQDswd5q6oAGdgM3KfdlCE9V9RY5g5uC0yTP46e5Es_fE0Z9I6KWUGjxjOw1u6gJQ9FDs0s44/AddingCustomProviders21.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p22RRclHKkdMfozIC0fL021JHxI02GyBNysyc_U-Ewsxdw9dA5pCcWQLFQDswd5q6oAGdgM3KfdlCE9V9RY5g5uC0yTP46e5Es_fE0Z9I6KWUGjxjOw1u6gJQ9FDs0s44/AddingCustomProviders21.png" alt="" width="512" height="296" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you close the &lt;strong style="font-weight: bold;"&gt;Collection Editor&lt;/strong&gt; dialog box for your sites, you need to click &lt;strong style="font-weight: bold;"&gt;Apply&lt;/strong&gt; in the &lt;strong style="font-weight: bold;"&gt;Actions&lt;/strong&gt; pane to commit the changes to your IIS settings:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p5cohl6iKW0UPNV_IQTB_bDNTVQOrTOwTmbUR_X7RfZRQnQS3CCAYReMqa5YDYOrf8Zd7u59D-vl7g_dsn_JILRyiOhr4XJYC_0U4uw1WAqnos98EOsHWreEmw8TuvBGc/AddingCustomProviders18.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p5cohl6iKW0UPNV_IQTB_bDNTVQOrTOwTmbUR_X7RfZRQnQS3CCAYReMqa5YDYOrf8Zd7u59D-vl7g_dsn_JILRyiOhr4XJYC_0U4uw1WAqnos98EOsHWreEmw8TuvBGc/AddingCustomProviders18.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="04"&gt;Summary and Parting Thoughts&lt;/h3&gt;
&lt;p&gt;As I mentioned in part 1 of this series, I admit that this might seem like a lot of steps to go through, but it's not that difficult once you understand how the configuration settings are organized and you get the hang of using the IIS Configuration Editor to add or modify these settings.&lt;/p&gt;
&lt;h4 id="04a"&gt;Disabling Custom User Isolation&lt;/h4&gt;
&lt;p&gt;In the &lt;a href="#03a"&gt;Add a custom FTP provider to an FTP site that is not used for authentication&lt;/a&gt; section of this blog, I added a step to specify &lt;strong style="font-weight: bold;"&gt;Custom&lt;/strong&gt; as the User Isolation mode. Since this is something of an advanced feature, there is no user interface for enabling custom user isolation; this was a design decision to keep people from breaking their FTP sites. Here's why: if you enable custom user isolation and you don't install a custom Home Directory provider for FTP, all users will be denied access to your FTP site.&lt;/p&gt;
&lt;p&gt;That being said, once you have enabled custom user isolation, the option to disable custom user isolation will "magically" appear in the &lt;strong style="font-weight: bold;"&gt;FTP User Isolation&lt;/strong&gt; feature in the IIS Manager. To see this for yourself, you would first need to follow the steps to custom user isolation in the &lt;a href="#03a"&gt;Add a custom FTP provider to an FTP site that is not used for authentication&lt;/a&gt; section of this blog.&lt;/p&gt;
&lt;p&gt;Once you have enabled custom user isolation, highlight your FTP site in the list of &lt;strong style="font-weight: bold;"&gt;Sites&lt;/strong&gt; pane of IIS Manager, then open the &lt;strong style="font-weight: bold;"&gt;FTP User Isolation&lt;/strong&gt; feature:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2p4IoflfMILbINgRVGrfACTzM7BDjQOgJcchP2ImNoS1KuDEAFDroVzWmbbTQ1HUDhq0PHRZ4KZX4T6r8M1CH-GDRGyFOy_eOtoI9sFVul5Jmp6LQF3kl0YvHGcW_obpzf/AddingCustomProviders22.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2p4IoflfMILbINgRVGrfACTzM7BDjQOgJcchP2ImNoS1KuDEAFDroVzWmbbTQ1HUDhq0PHRZ4KZX4T6r8M1CH-GDRGyFOy_eOtoI9sFVul5Jmp6LQF3kl0YvHGcW_obpzf/AddingCustomProviders22.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you open the &lt;strong style="font-weight: bold;"&gt;FTP User Isolation&lt;/strong&gt; feature, you will see that an option for &lt;strong style="font-weight: bold;"&gt;Custom&lt;/strong&gt; now appears in the list of user isolation modes:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bay.livefilestore.com/y2pC_10jOvR_Gw6zeCgVZ3JEWDO6pwv6UyXey26l9WTG64RdCOqc46_UDEtp1qsdO80Ze2sj88vboL9zwzvcjAyUI6Wb5iTazt4328ioBHwY29hzF-n8ac2M6Enz_OXvfhb/AddingCustomProviders23.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bay.livefilestore.com/y2pC_10jOvR_Gw6zeCgVZ3JEWDO6pwv6UyXey26l9WTG64RdCOqc46_UDEtp1qsdO80Ze2sj88vboL9zwzvcjAyUI6Wb5iTazt4328ioBHwY29hzF-n8ac2M6Enz_OXvfhb/AddingCustomProviders23.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This option will appear as long as custom user isolation is enabled. If you change the user isolation mode to something other than &lt;strong style="font-weight: bold;"&gt;Custom&lt;/strong&gt;, this option will continue appear in the list of user isolation modes until you navigate somewhere else in IIS Manager. Once you have changed the user isolation mode to one of the built-in modes and you navigate somewhere else, the &lt;strong style="font-weight: bold;"&gt;Custom&lt;/strong&gt; option will not show up in the &lt;strong style="font-weight: bold;"&gt;FTP User Isolation&lt;/strong&gt; feature until you follow the steps to re-enable custom user isolation.&lt;/p&gt;
&lt;h4 id="04b"&gt;Additional Information&lt;/h4&gt;
&lt;p&gt;If you want additional information about configuring the settings for FTP providers, you can find detailed reference documentation at the following URLs:&lt;/p&gt;
&lt;ul&gt;
&lt;li style="line-height: 150%;"&gt;&lt;strong style="font-weight: bold;"&gt;FTP Custom Features &amp;lt;customFeatures&amp;gt;&lt;/strong&gt;&lt;br /&gt; &lt;a href="http://www.iis.net/configreference/system.applicationhost/sites/site/ftpserver/customfeatures" target="_blank"&gt;http://www.iis.net/configreference/system.applicationhost/sites/site/ftpserver/customfeatures&lt;/a&gt;&lt;/li&gt;
&lt;li style="line-height: 150%;"&gt;&lt;strong style="font-weight: bold;"&gt;FTP Custom Authentication &amp;lt;customAuthentication&amp;gt;&lt;/strong&gt;&lt;br /&gt; &lt;a href="http://www.iis.net/configreference/system.applicationhost/sites/site/ftpserver/security/authentication/customauthentication" target="_blank"&gt;http://www.iis.net/configreference/system.applicationhost/sites/site/ftpserver/security/authentication/customauthentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these articles contain "How-To" steps, detailed information about each of the configuration settings, and code samples for AppCmd.exe, C#/VB.NET, and JavaScript/VBScript.&lt;/p&gt;
&lt;p&gt;As always, let me know if you have any questions. &lt;span style="white-space: nowrap;"&gt;;-]&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10415792" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/e1sLEZLyMuw" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/FTP/">FTP</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Extensibility/">Extensibility</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/05/02/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-2.aspx</feedburner:origLink></item><item><title>Feedback Request for Curated Content Views</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/kdB5N3clkv4/feedback-request-for-curated-content-views.aspx</link><pubDate>Tue, 30 Apr 2013 23:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10415250</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/04/30/feedback-request-for-curated-content-views.aspx#comments</comments><description>&lt;p&gt;Publishing technical documentation is an interesting business, and a lot of discussion &amp;amp; deliberation goes into the creation process for articles and videos that we produce at Microsoft. For example, when I am writing an article for IIS, should I publish that on www.iis.net, or technet.microsoft.com, or msdn.microsoft.com? Or should I just write a blog about it? And after I have published an article, how will my intended audience find it? As we continue to publish hundreds of technical articles to the websites that I just mentioned, the navigation hierarchy becomes increasingly complex, and content discoverability suffers.&lt;/p&gt;
&lt;p&gt;Some time ago a few of our writers began to experiment with a new way to consolidate lists of related content into something that we called a "Content Map." The following pages will show you an example of what the Content Map concept looks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://asp.net/whitepapers/aspnet-web-deployment-content-map" target="_blank"&gt;ASP.NET Deployment Content Map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://asp.net/mvc/overview/getting-started/aspnet-mvc-content-map" target="_blank"&gt;ASP.NET MVC 4 Content Map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://asp.net/whitepapers/aspnet-data-access-content-map" target="_blank"&gt;ASP.NET Data Access Content Map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these articles received a great deal of positive feedback from customers, but our team wanted to see if there was a way that customers could help us to improve on this design. We know that there is a great deal of third-party content on the Internet, and we wanted a way to recognize that. We also asked several customers about what kinds of content they need to be successful, and we added their suggestions to our deliberation process.&lt;/p&gt;
&lt;p&gt;As a result of our collective discussions, we came up with an idea for what we are internally calling "Curated Content Views." These "views" are lists of related content topics that are organized to answer a particular question or customer need. A view is assembled by someone at Microsoft based on input from anyone who thinks that an article, blog, video, or code sample might be beneficial as part of the view.&lt;/p&gt;
&lt;p&gt;With that in mind, here are three conceptual content views that a few of the writers on our content team have assembled:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://www.asp.net/mvc/tutorials/deployment/cse-curated-view-deploy-to-waws" target="_blank"&gt;How to deploy an ASP.NET web application to a Windows Azure Web Site using Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://www.asp.net/mvc/overview/getting-started/cse-curated-view-mvc-security" target="_blank"&gt;How to secure an ASP.NET MVC app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style="line-height: 150%;" href="http://www.iis.net/learn/publish/using-the-ftp-service/cse-curated-view-ftp-security-settings" target="_blank"&gt;How Do I Configure FTP Security in IIS?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our team is requesting feedback from members of the community regarding these conceptual views with regard to the level of detail that is included in each view, the conceptual layouts that were used, and any thoughts about how this content compares with existing table of contents topics or content maps. You can &lt;a href="mailto:%61s%70n%65t%75e@m%69c%72o%73o%66t%2Ec%6Fm?subject=C%75r%61t%65d%20C%6Fn%74e%6Et%20V%69e%77%20%46e%65d%62a%63k"&gt;reply to our content team via email&lt;/a&gt;, or you can post a response to this blog.&lt;/p&gt;
&lt;p&gt;While we are interested in any feedback you may have, our team has put together the following list of specific questions to think about:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Each curated view/content map includes a list of suggested content links. Below is a list of additional information that could be provided with each link. Which of these are most important?
&lt;ul&gt;
&lt;li&gt;Date that the content was posted.&lt;/li&gt;
&lt;li&gt;Type of content (video, article, code sample, etc.).&lt;/li&gt;
&lt;li&gt;Author name.&lt;/li&gt;
&lt;li&gt;Short description.&lt;/li&gt;
&lt;li&gt;Level of difficulty of the content.&lt;/li&gt;
&lt;li&gt;Version of software/framework or SDK the content refers to.&lt;/li&gt;
&lt;li&gt;Website the content appears on.&lt;/li&gt;
&lt;li&gt;Number of likes or positive reviews.&lt;/li&gt;
&lt;li&gt;Rating assigned to the content by the community.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you opened a page similar to one of these curated views/content maps from Google or Bing search results, would you be likely to try the links on this page or just return to search results?&lt;/li&gt;
&lt;li&gt;If Microsoft and community experts published a large set of content views similar to these on a website, would you visit that site first when you had technical questions, or would you do an Internet search on Google/Bing first?&lt;/li&gt;
&lt;li&gt;Do the questions addressed by each curated view seem too narrow or too broad in scope to be helpful? If so, which ones?&lt;/li&gt;
&lt;li&gt;Do any of the curated views/content maps provide too much or too little detail for each link in the list? If so, which ones?&lt;/li&gt;
&lt;li&gt;Do you find it helpful to see the profile of the person who created the curated view/content map?&lt;/li&gt;
&lt;li&gt;If we provided an easy way for you to publish your own curated views (with attribution) to a common site together with the Microsoft-created curated views, would you be interested in doing so? Why or why not?&lt;/li&gt;
&lt;li&gt;If we provided an easy way for you to suggest new content items to add to content views/content maps that have already been published, would you be interested in doing so? Why or why not?&lt;/li&gt;
&lt;li&gt;What would make these content views/content maps more helpful?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thanks!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10415250" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/kdB5N3clkv4" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Content/">Content</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/04/30/feedback-request-for-curated-content-views.aspx</feedburner:origLink></item><item><title>IIS 6.0 WebDAV and Compound Document Format Files Revisited with Workarounds</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/1CttXkvuWoU/iis-6-0-webdav-and-compound-document-format-files-revisited-with-workarounds.aspx</link><pubDate>Thu, 25 Apr 2013 01:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10413844</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/04/24/iis-6-0-webdav-and-compound-document-format-files-revisited-with-workarounds.aspx#comments</comments><description>&lt;p&gt;A few years ago I wrote the following blog, wherein I described how the WebDAV functionality in IIS 6.0 worked with files that are &lt;a href="http://msdn.microsoft.com/library/ms693383.aspx" target="_blank"&gt;Compound Document&lt;/a&gt; format:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2010/04/21/iis-6-0-webdav-and-compound-document-format-files.aspx" target="_blank"&gt;IIS 6.0 WebDAV and Compound Document Format Files&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As I explained in that blog post, WebDAV needs somewhere to store "properties" for files that are uploaded to the server, and WebDAV uses the compound document format to accomplish this according to the following implementation logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the file is already in the compound document file format, IIS simply adds the WebDAV properties to the existing file. This data will not be used by the application that created the file - it will only be used by WebDAV. However, the file size will increase because WebDAV properties are added to the compound document.&lt;/li&gt;
&lt;li&gt;For other files, WebDAV stores a compound document in an NTFS &lt;a href="http://msdn.microsoft.com/library/aa364404.aspx" target="_blank"&gt;alternate data stream&lt;/a&gt; that is attached to the file. You will never see this additional data from any directory listing, and the file size doesn't change because it's in an alternate data stream.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I recently had a customer contact me in order to ask if there was a way to disable this functionality since he didn't want his files modified in order to store the WebDAV properties. Unfortunately there is no built-in option for IIS that will disable this functionality, but there are a few workarounds.&lt;/p&gt;
&lt;h4 align="left"&gt;Workaround #1 - Change the File Type&lt;/h4&gt;
&lt;p align="left"&gt;First and foremost - you can change your file type to something other than the compound document format. For example, if you are uploading files that were created in Microsoft Office, if you can upload your files in the newer &lt;a href="http://technet.microsoft.com/library/cc179190.aspx" target="_blank"&gt;Office Open XML formats&lt;/a&gt;, then you will not run into this problem. By way of explanation, older Microsoft Office files are in compound document format, whereas files that are that are created with Microsoft Office 2010 and later are in a zipped, XML-based file format. These files will have extensions like *.DOCX for Microsoft Word documents, *.XLSX for Microsoft Excel spreadsheets, and *.PPTX for Microsoft PowerPoint presentations.&lt;/p&gt;
&lt;h4 align="left"&gt;Workaround #2 - Wrap Compound Document Files in a Separate File Type&lt;/h4&gt;
&lt;p&gt;If you are using a file that must be in compound document format, like a setup package in Microsoft Installer (*.MSI) format, you can upload the file in a *.ZIP file, or you can wrap the setup package inside a self-extracting executable by using a technology like Microsoft's &lt;a href="http://technet.microsoft.com/library/dd346760.aspx" target="_blank"&gt;IExpress Wizard&lt;/a&gt; (which ships as a built-in utility with most versions of Windows).&lt;/p&gt;
&lt;h4 align="left"&gt;Workaround #3 - Block WebDAV Properties&lt;/h4&gt;
&lt;p&gt;If you absolutely cannot change your document from compound document format, I have a completely unsupported workaround that I can suggest. Since the problem arises when properties are added to a file, you can find a way to intercept the WebDAV commands that try to set properties. The actual HTTP verb that is used is PROPPATCH, so if you can find a way to keep this command from being used, then you can prevent files from being modified. Unfortunately you cannot simply suppress PROPPATCH commands by using a security tool like Microsoft's &lt;a href="http://www.iis.net/downloads/microsoft/urlscan" target="_blank"&gt;UrlScan&lt;/a&gt; to block the command, because this will cause many WebDAV clients to fail.&lt;/p&gt;
&lt;p&gt;Instead, what I did as a workaround was to write an example ISAPI filter for IIS 6.0 that intercepts incoming PROPPATCH commands and always sends a successful (e.g. "200 OK") response to the WebDAV client, but in reality the filter does nothing with the properties and ends the request processing. This tricks a WebDAV client into thinking that it succeeded, and it prevents your files in compound document format from being modified. However, this also means that no WebDAV properties will ever be stored with your files; but if that's acceptable to you, (and it usually should be), then you can use this workaround.&lt;/p&gt;
&lt;p&gt;With that in mind, here's the C++ code for my example ISAPI filter, and please remember that this is a completely unsupported workaround that is intended for use only when you cannot repackage your files to use something other than the compound document format.&lt;/p&gt;
&lt;pre style="color: black; background-color: #ffffff; margin-left: 20px;"&gt;&lt;span style="color: #cc6633;"&gt;#define&lt;/span&gt; _WIN32_WINNT 0x0400

&lt;span style="color: #cc6633;"&gt;#include&lt;/span&gt; &amp;lt;windows.h&amp;gt;
&lt;span style="color: #cc6633;"&gt;#include&lt;/span&gt; &amp;lt;httpfilt.h&amp;gt;

&lt;span style="color: #cc6633;"&gt;#define&lt;/span&gt; STRSAFE_LIB
&lt;span style="color: #cc6633;"&gt;#include&lt;/span&gt; &amp;lt;strsafe.h&amp;gt;

&lt;span style="color: #cc6633;"&gt;#define&lt;/span&gt; BUFFER_SIZE 2048

&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; xmlpart1[] = &lt;span style="color: #800000;"&gt;"&amp;lt;?xml version=\"1.0\"?&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;a:multistatus xmlns:a=\"DAV:\"&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;a:response&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;a:href&amp;gt;"&lt;/span&gt;;

&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; xmlpart2[] = &lt;span style="color: #800000;"&gt;"&amp;lt;/a:href&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;a:propstat&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;a:status&amp;gt;HTTP/1.1 200 OK&amp;lt;/a:status&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;/a:propstat&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;/a:response&amp;gt;"&lt;/span&gt;
  &lt;span style="color: #800000;"&gt;"&amp;lt;/a:multistatus&amp;gt;"&lt;/span&gt;;

BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
  HRESULT hr = S_OK;
  &lt;span style="color: #008000;"&gt;// Set the filter's version.&lt;/span&gt;
  pVer-&amp;gt;dwFilterVersion = HTTP_FILTER_REVISION;
  &lt;span style="color: #008000;"&gt;// Set the filter's description.&lt;/span&gt;
  hr = StringCchCopyEx(
    pVer-&amp;gt;lpszFilterDesc,256,&lt;span style="color: #800000;"&gt;"PROPPATCH"&lt;/span&gt;,
    NULL,NULL,STRSAFE_IGNORE_NULLS);
  &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (FAILED(hr)) &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;FALSE&lt;/span&gt;;
  &lt;span style="color: #008000;"&gt;// Set the filter's flags.&lt;/span&gt;
  pVer-&amp;gt;dwFlags = SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_PREPROC_HEADERS;
  &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TRUE&lt;/span&gt;;
}

DWORD WINAPI HttpFilterProc(
  PHTTP_FILTER_CONTEXT pfc,
  DWORD NotificationType,
  LPVOID pvNotification )
{
  &lt;span style="color: #008000;"&gt;// Verify the correct notification.&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ( NotificationType == SF_NOTIFY_PREPROC_HEADERS)
  {
    PHTTP_FILTER_PREPROC_HEADERS pHeaders;
    HRESULT hr = S_OK;
  
    &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; fSecure = false;

    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szServerName[BUFFER_SIZE] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;
    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szSecure[2] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;
    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szResponseXML[BUFFER_SIZE] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;
    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szResponseURL[BUFFER_SIZE] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;
    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szRequestURL[BUFFER_SIZE] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;
    &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; szMethod[BUFFER_SIZE] = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;;

    DWORD dwBuffSize = 0;

    pHeaders = (PHTTP_FILTER_PREPROC_HEADERS) pvNotification;

    &lt;span style="color: #008000;"&gt;// Get the method of the request&lt;/span&gt;
    dwBuffSize = BUFFER_SIZE-1;
    &lt;span style="color: #008000;"&gt;// Exit with an error status if a failure occured.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;GetServerVariable(
      pfc, &lt;span style="color: #800000;"&gt;"HTTP_METHOD"&lt;/span&gt;, szMethod, &amp;amp;dwBuffSize))
      &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;

    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (strcmp(szMethod, &lt;span style="color: #800000;"&gt;"PROPPATCH"&lt;/span&gt;) == 0)
    {
      &lt;span style="color: #008000;"&gt;// Send the HTTP status to the client.&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;ServerSupportFunction(
        pfc, SF_REQ_SEND_RESPONSE_HEADER,&lt;span style="color: #800000;"&gt;"207 Multi-Status"&lt;/span&gt;, 0, 0))
        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;

      &lt;span style="color: #008000;"&gt;// Get the URL of the request.&lt;/span&gt;
      dwBuffSize = BUFFER_SIZE-1;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;GetServerVariable(
        pfc, &lt;span style="color: #800000;"&gt;"URL"&lt;/span&gt;, szRequestURL, &amp;amp;dwBuffSize))
        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;
        
      &lt;span style="color: #008000;"&gt;// Determine if request was sent over secure port.&lt;/span&gt;
      dwBuffSize = 2;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;GetServerVariable(
        pfc, &lt;span style="color: #800000;"&gt;"SERVER_PORT_SECURE"&lt;/span&gt;, szSecure, &amp;amp;dwBuffSize))
        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;
      fSecure = (szSecure[0] == &lt;span style="color: #800000;"&gt;'1'&lt;/span&gt;);
        
      &lt;span style="color: #008000;"&gt;// Get the server name.&lt;/span&gt;
      dwBuffSize = BUFFER_SIZE-1;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;GetServerVariable(
        pfc, &lt;span style="color: #800000;"&gt;"SERVER_NAME"&lt;/span&gt;, szServerName, &amp;amp;dwBuffSize))
        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;
        
      &lt;span style="color: #008000;"&gt;// Set the response URL.&lt;/span&gt;
      hr = StringCchPrintf(
        szResponseURL,BUFFER_SIZE-1, &lt;span style="color: #800000;"&gt;"http%s://%s/%s"&lt;/span&gt;,
        (fSecure ? &lt;span style="color: #800000;"&gt;"s"&lt;/span&gt; : &lt;span style="color: #800000;"&gt;""&lt;/span&gt;), szServerName, &amp;amp;szRequestURL[1]);
      &lt;span style="color: #008000;"&gt;// Exit with an error status if a failure occurs.&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (FAILED(hr)) &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;

      &lt;span style="color: #008000;"&gt;// Set the response body.&lt;/span&gt;
      hr = StringCchPrintf(
        szResponseXML,BUFFER_SIZE-1, &lt;span style="color: #800000;"&gt;"%s%s%s"&lt;/span&gt;,
        xmlpart1, szResponseURL, xmlpart2);
      &lt;span style="color: #008000;"&gt;// Exit with an error status if a failure occurs.&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (FAILED(hr)) &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;

      &lt;span style="color: #008000;"&gt;// Write the response body to the client.&lt;/span&gt;
      dwBuffSize = strlen(szResponseXML);
      &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!pfc-&amp;gt;WriteClient(
        pfc, szResponseXML, &amp;amp;dwBuffSize, 0))
        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_ERROR;

      &lt;span style="color: #008000;"&gt;// Flag the request as completed.&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_FINISHED;
    }
  }
    
  &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; SF_STATUS_REQ_NEXT_NOTIFICATION;
}&lt;/pre&gt;
&lt;p&gt;I hope this helps. &lt;span style="white-space: nowrap;"&gt;;-]&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10413844" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/1CttXkvuWoU" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/WebDAV/">WebDAV</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS+6/">IIS 6</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/04/24/iis-6-0-webdav-and-compound-document-format-files-revisited-with-workarounds.aspx</feedburner:origLink></item><item><title>Adding Custom FTP Providers with the IIS Configuration Editor - Part 1</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/7wlV7fzRhRY/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx</link><pubDate>Mon, 01 Apr 2013 06:03:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10406634</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/31/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx#comments</comments><description>&lt;p&gt;I've written a lot of walkthroughs and blog posts about creating custom FTP providers over the past several years, and I usually include instructions for adding these custom providers to IIS. When you create a custom FTP authentication provider, IIS has a user interface for adding that provider to FTP. But if you are adding a custom home directory or logging provider, there is no dedicated user interface for adding those types of FTP providers. In addition, if you create a custom FTP provider that requires settings that are stored in your IIS configuration, there is no user interface to add or manage those settings.&lt;/p&gt;
&lt;p&gt;With this in mind, I include instructions in my blogs and walkthroughs that describe how to add those type of providers by using AppCmd.exe from a command line. For example, if you take a look at my &lt;em&gt;&lt;a href="http://www.iis.net/learn/develop/developing-for-ftp/how-to-use-managed-code-c-to-create-an-ftp-authentication-and-authorization-provider-using-an-xml-database" target="_blank"&gt;How to Use Managed Code (C#) to Create an FTP Authentication and Authorization Provider using an XML Database&lt;/a&gt;&lt;/em&gt; walkthrough, I include the following instructions:&lt;/p&gt;
&lt;p style="margin-left: 20px; font-size: 12pt; color: #333; background-color: fff;"&gt;&lt;strong&gt;Adding the Provider&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Determine the assembly information for the extensibility provider:
&lt;ul&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;In Windows Explorer, open your "C:\Windows\assembly" path, where C: is your operating system drive.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Locate the &lt;strong&gt;FtpXmlAuthorization&lt;/strong&gt; assembly.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Right-click the assembly, and then click &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Copy the &lt;strong&gt;Culture&lt;/strong&gt; value; for example: &lt;strong&gt;Neutral&lt;/strong&gt;.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Copy the &lt;strong&gt;Version&lt;/strong&gt; number; for example: &lt;strong&gt;1.0.0.0&lt;/strong&gt;.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Copy the &lt;strong&gt;Public Key Token&lt;/strong&gt; value; for example: &lt;strong&gt;426f62526f636b73&lt;/strong&gt;.&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Click &lt;strong&gt;Cancel&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;Using the information from the previous steps, add the extensibility provider to the global list of FTP providers and configure the options for the provider:
&lt;ul&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;At the moment there is no user interface that enables you to add properties for custom authentication or authorization modules, so you will have to use the following command line:&lt;br /&gt; &lt;br /&gt; &lt;code&gt;cd %SystemRoot%\System32\Inetsrv&lt;br /&gt; &lt;br /&gt; appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"[name='FtpXmlAuthorization',type='FtpXmlAuthorization,FtpXmlAuthorization,version=1.0.0.0,Culture=neutral,PublicKeyToken=426f62526f636b73']" /commit:apphost&lt;br /&gt; &lt;br /&gt; appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"activation.[name='FtpXmlAuthorization']" /commit:apphost&lt;br /&gt; &lt;br /&gt; appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"activation.[name='FtpXmlAuthorization'].[key='xmlFileName',value='C:\Inetpub\XmlSample\Users.xml']" /commit:apphost&lt;/code&gt;&lt;/li&gt;
&lt;li style="margin-left: 20px; font-size: 9pt; color: #333; background-color: fff;"&gt;&lt;strong&gt;Note&lt;/strong&gt;: The file path that you specify in the &lt;em&gt;xmlFileName&lt;/em&gt; attribute must match the path where you saved the "Users.xml" file on your computer in the earlier in this walkthrough.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This example adds a custom FTP provider, and then it adds a custom setting for that provider that is stored in your IIS configuration settings.&lt;/p&gt;
&lt;p&gt;That being said, there is actually a way to add custom FTP providers with settings like the ones that I have just described through the IIS interface by using the &lt;strong&gt;IIS Configuration Editor&lt;/strong&gt;. This feature was first available through the &lt;a href="http://www.iis.net/downloads/microsoft/administration-pack" target="_blank"&gt;IIS Administration Pack&lt;/a&gt; for IIS 7.0, and is built-in for IIS 7.5 and IIS 8.0.&lt;/p&gt;
&lt;p&gt;Before I continue, if would probably be prudent to take a look at the settings that we are trying to add, because these settings might help you to understand the rest of steps in this blog. Here is an example from my applicationhost.config file for three custom FTP authentication providers; the first two providers are installed with the FTP service, and the third provider is a custom provider that I created with a single provider-specific configuration setting:&lt;/p&gt;
&lt;p style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&lt;code&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerDefinitions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="IisManagerAuth"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Microsoft.Web.FtpServer.Security.IisManagerAuthenticationProvider, Microsoft.Web.FtpServer, version=7.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="AspNetAuth"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Microsoft.Web.FtpServer.Security.AspNetFtpMembershipProvider, Microsoft.Web.FtpServer, version=7.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization, FtpXmlAuthorization, version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;activation&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerData&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="FtpXmlAuthorization"&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="xmlFileName"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="C:\inetpub\FtpUsers\Users.xml"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerData&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;activation&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;providerDefinitions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.ftpServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With that in mind, in part 1 of this blog series, I will show you how to use the IIS Configuration Editor to add a custom FTP provider with provider-specific configuration settings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; - Open the IIS Manager and click on the &lt;strong&gt;Configuration Editor&lt;/strong&gt; at feature the server level:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pQvThdGUL69bzTfejtWrotYf19S9U8EY_B0pZZGyFMV5j4byqCs79COKdwI8q8H5VbZ6SC_DLwtJM1gGrw_1OoAp1LObGEK9w/AddingCustomProviders01.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pQvThdGUL69bzTfejtWrotYf19S9U8EY_B0pZZGyFMV5j4byqCs79COKdwI8q8H5VbZ6SC_DLwtJM1gGrw_1OoAp1LObGEK9w/AddingCustomProviders01.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; - Click the &lt;strong&gt;Section&lt;/strong&gt; drop-down menu, expand the the &lt;strong&gt;system.ftpServer&lt;/strong&gt; collection, and then highlight the &lt;strong&gt;providerDefinitions&lt;/strong&gt; node:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pn0X0XoiIJBEZlxXNvRMt1TOpxjW-aYazuf7Y5IlRvnpKC2rmEWC9w98WQ2jPWUJo9jvNIAOYPxGSxcSGSB_JZtldrs8g3kZE/AddingCustomProviders02.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pn0X0XoiIJBEZlxXNvRMt1TOpxjW-aYazuf7Y5IlRvnpKC2rmEWC9w98WQ2jPWUJo9jvNIAOYPxGSxcSGSB_JZtldrs8g3kZE/AddingCustomProviders02.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; - A default installation IIS with the FTP service should show a &lt;strong&gt;Count&lt;/strong&gt; of 2 providers in the &lt;strong&gt;Collection&lt;/strong&gt; row, and no settings in the &lt;strong&gt;activation&lt;/strong&gt; row:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pyd-UciuymQRM2OvL32V5ciC4HL8CfvsMX3Th9dazwEu1U6Hf0w62qYFTYf4I5Am900i6E3Y-pfdnJLe85kj3E6m3epvoeaHw/AddingCustomProviders03.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pyd-UciuymQRM2OvL32V5ciC4HL8CfvsMX3Th9dazwEu1U6Hf0w62qYFTYf4I5Am900i6E3Y-pfdnJLe85kj3E6m3epvoeaHw/AddingCustomProviders03.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt; - If you click on the &lt;strong&gt;Collection&lt;/strong&gt; row, an ellipsis &lt;strong&gt;[...]&lt;/strong&gt; will appear, and when you click that, IIS will display the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog for FTP providers. By default you should see just the two built-in providers for the &lt;strong&gt;IisManagerAuth&lt;/strong&gt; and &lt;strong&gt;AspNetAuth&lt;/strong&gt; providers:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pgLH_JidYyZjNck69nmdjCnPzWui9-BuUeMRfnw15UVP5HSabgskBheV2p5kAz3xc01sZwMMStIcnjjU1tZ3rBqJMZ86B5s0u/AddingCustomProviders04.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pgLH_JidYyZjNck69nmdjCnPzWui9-BuUeMRfnw15UVP5HSabgskBheV2p5kAz3xc01sZwMMStIcnjjU1tZ3rBqJMZ86B5s0u/AddingCustomProviders04.png" alt="" width="512" height="280" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt; - When you click &lt;strong&gt;Add&lt;/strong&gt; in the &lt;strong&gt;Actions&lt;/strong&gt; pane, you can enter the registration information for your provider. At a minimum you must provide a &lt;strong&gt;name&lt;/strong&gt; for your provider, but you will need to enter either the &lt;strong&gt;clsid&lt;/strong&gt; for a COM-based provider or the &lt;strong&gt;type&lt;/strong&gt; for a managed-code provider:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pedn5d4wH3RWYRIYtSoVL5S8w9BUOBRbFQ-Q37cMDA97HBi1hNIbJc4b1CH1zPlekGnYjCCWMvEsE8BDlebK5Yy23N_UgML6j/AddingCustomProviders05.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pedn5d4wH3RWYRIYtSoVL5S8w9BUOBRbFQ-Q37cMDA97HBi1hNIbJc4b1CH1zPlekGnYjCCWMvEsE8BDlebK5Yy23N_UgML6j/AddingCustomProviders05.png" alt="" width="512" height="280" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt; - When you close the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog, the &lt;strong&gt;Count&lt;/strong&gt; of providers in the &lt;strong&gt;Collection&lt;/strong&gt; should now reflect the provider that we just added; click &lt;strong&gt;Apply&lt;/strong&gt; in the &lt;strong&gt;Actions&lt;/strong&gt; pane to save the changes:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1ppJvN3Cu_0iih85wKIZktysZQrP3LTgik2j0liJIsp8D5o732ntRdB_AaG2r6baxRxByqNDS_u7TNuZI_l8Jg7D36SR4RfN8-/AddingCustomProviders06.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1ppJvN3Cu_0iih85wKIZktysZQrP3LTgik2j0liJIsp8D5o732ntRdB_AaG2r6baxRxByqNDS_u7TNuZI_l8Jg7D36SR4RfN8-/AddingCustomProviders06.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt; - If you click on the &lt;strong&gt;activation&lt;/strong&gt; row, an ellipsis &lt;strong&gt;[...]&lt;/strong&gt; will appear, and when you click that, IIS will display the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog for provider data; this is where you will enter provider-specific settings. When you click &lt;strong&gt;Add&lt;/strong&gt; in the &lt;strong&gt;Actions&lt;/strong&gt; pane, you must specify the &lt;strong&gt;name&lt;/strong&gt; for your provider's settings, and this name &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;&lt;em&gt;must&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; match the exact name that you provided in &lt;strong&gt;Step 5&lt;/strong&gt; earlier:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pgzm0CA6oMvkdy12bvcQcFdcCASWuvLPYkRMzcaCBs2EgJzmaOYUeF_8yalrPNKwepQ8-jpl1VO27PQa8VVTRhcavzGzCgjai/AddingCustomProviders07.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pgzm0CA6oMvkdy12bvcQcFdcCASWuvLPYkRMzcaCBs2EgJzmaOYUeF_8yalrPNKwepQ8-jpl1VO27PQa8VVTRhcavzGzCgjai/AddingCustomProviders07.png" alt="" width="512" height="280" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 8&lt;/strong&gt; - If you click on the &lt;strong&gt;Collection&lt;/strong&gt; row, an ellipsis &lt;strong&gt;[...]&lt;/strong&gt; will appear, and when you click that, IIS will display the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog for the activation data for an FTP provider. At a minimum you must provide a &lt;strong&gt;key&lt;/strong&gt; for your provider, which will depend on the settings that your provider expects to retrieve from your configuration settings. (For example, in the XML file that I provided earlier, my &lt;strong&gt;&lt;code&gt;FtpXmlAuthorization&lt;/code&gt;&lt;/strong&gt; provider expects to retrieve the path to an XML that contains a list of users, roles, and authorization rules.) You also need to enter the either the &lt;strong&gt;value&lt;/strong&gt; or &lt;strong&gt;encryptedValue&lt;/strong&gt; for your provider; although you can specify either setting, should generally specify the &lt;strong&gt;value&lt;/strong&gt; when the settings are not sensitive in nature, and specify the &lt;strong&gt;encryptedValue&lt;/strong&gt; for settings like usernames and passwords:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pEs3JQDlxThYKp5bDsnc0dzS65TBAZZVfZ4gsyCNE0lErDKxzhg_NvO1jUsJ7FCN7C5Tcah1k5MiluQzGRX_LA9Cmgod55Cpf/AddingCustomProviders08.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pEs3JQDlxThYKp5bDsnc0dzS65TBAZZVfZ4gsyCNE0lErDKxzhg_NvO1jUsJ7FCN7C5Tcah1k5MiluQzGRX_LA9Cmgod55Cpf/AddingCustomProviders08.png" alt="" width="512" height="280" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 9&lt;/strong&gt; - When you close the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog for the activation data, the &lt;strong&gt;Count&lt;/strong&gt; of key/value pairs in the &lt;strong&gt;Collection&lt;/strong&gt; should now reflect the value that we just added:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pplklHsjaVzJV1aRhGqhKDphxLAMJRfqpUu0Qg5Xve-RPMYGG0iY-thFEc3umLYjC4KRlflPCbNYjwb9pBEstqXg2aGuFqJpp/AddingCustomProviders09.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pplklHsjaVzJV1aRhGqhKDphxLAMJRfqpUu0Qg5Xve-RPMYGG0iY-thFEc3umLYjC4KRlflPCbNYjwb9pBEstqXg2aGuFqJpp/AddingCustomProviders09.png" alt="" width="512" height="280" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 10&lt;/strong&gt; - When you close the &lt;strong&gt;Collection Editor&lt;/strong&gt; dialog for the provider data, the &lt;strong&gt;Count&lt;/strong&gt; of provider data settings in the &lt;strong&gt;activation&lt;/strong&gt; row should now reflect the custom settings that we just added; click &lt;strong&gt;Apply&lt;/strong&gt; in the &lt;strong&gt;Actions&lt;/strong&gt; pane to save the changes:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1p3A004-sY0ZvbJyVYhxhBB6vEW62uaDO38yo3Xu9QQ8niSt3ZAwTUByhaMXKcS6Ou_X-PUhk35N41LMbtkkuD2BBgqHri8pDe/AddingCustomProviders10.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1p3A004-sY0ZvbJyVYhxhBB6vEW62uaDO38yo3Xu9QQ8niSt3ZAwTUByhaMXKcS6Ou_X-PUhk35N41LMbtkkuD2BBgqHri8pDe/AddingCustomProviders10.png" alt="" width="512" height="384" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That's all that there is to adding a custom FTP provider with provider-specific settings; I admit that it might seem like a lot of steps until you get the hang of it.&lt;/p&gt;
&lt;p&gt;In the next blog for this series, I will show you how to add custom providers to FTP sites by using the IIS Configuration Editor.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10406634" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/7wlV7fzRhRY" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/FTP/">FTP</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Extensibility/">Extensibility</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/31/adding-custom-ftp-providers-with-the-iis-configuration-editor-part-1.aspx</feedburner:origLink></item><item><title>Automating the Creation of FTP User Isolation Folders</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/wStcRGx0bSg/automating-the-creation-of-ftp-user-isolation-folders.aspx</link><pubDate>Fri, 29 Mar 2013 06:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10406244</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/28/automating-the-creation-of-ftp-user-isolation-folders.aspx#comments</comments><description>&lt;p&gt;A customer asked me a question a little while ago that provided me the opportunity to recycle some code that I had written many years ago. In so doing, I also made a bunch of updates to the code to make it considerably more useful, and I thought that it would make a great blog.&lt;/p&gt;
&lt;p&gt;Here's the scenario: a customer had hundreds of user accounts created, and he wanted to use the FTP service's User Isolation features to restrict each user to a specific folder on his FTP site. Since it would take a long time to manually create a folder for each user account, the customer wanted to know if there was a way to automate the process. As it turns out, I had posted a very simple script in the &lt;a href="http://forums.iis.net/" target="_blank"&gt;IIS.net forums&lt;/a&gt; several years ago that did something like what he wanted; and that script was based off an earlier script that I had written for someone else back in the IIS 6.0 days.&lt;/p&gt;
&lt;p&gt;One quick reminder - FTP User Isolation uses a specific set of folders for user accounts, which are listed in the table below.&lt;/p&gt;
&lt;table style="margin-left: 20px;" border="1" cellspacing="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th width="50%"&gt;User Account Types&lt;/th&gt;&lt;th width="50%"&gt;Home Directory Syntax&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="50%"&gt;Anonymous users&lt;/td&gt;
&lt;td width="50%"&gt;%&lt;em&gt;FtpRoot&lt;/em&gt;%\LocalUser\Public&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="50%"&gt;Local Windows user accounts
&lt;p&gt;(Requires Basic authentication.)&lt;/p&gt;
&lt;/td&gt;
&lt;td width="50%"&gt;%&lt;em&gt;FtpRoot&lt;/em&gt;%\LocalUser\%&lt;em&gt;UserName&lt;/em&gt;%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="50%"&gt;Windows domain accounts
&lt;p&gt;(Requires Basic authentication.)&lt;/p&gt;
&lt;/td&gt;
&lt;td width="50%"&gt;%&lt;em&gt;FtpRoot&lt;/em&gt;%\%UserDomain%\%&lt;em&gt;UserName&lt;/em&gt;%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;strong&gt;Note&lt;/strong&gt;: %&lt;em&gt;FtpRoot&lt;/em&gt;% is the root directory for your FTP site: for example, C:\Inetpub\&lt;em&gt;Ftproot&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That being said, I'm a big believer in recycling code, so I found the last version of that script that I gave to someone and I made a bunch of changes to it so it would be more useful for the customer. What that in mind, here's the resulting script, and I'll explain a little more about what it does after the code sample.&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&lt;span style="color: #0000ff;"&gt;Option Explicit&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Define the root path for the user isolation folders.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' This should be the root directory for your FTP site.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strRootPath : strRootPath = &lt;span style="color: #800000;"&gt;"C:\Inetpub\wwwroot\"&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Define the name of the domain or the computer to use.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Leave this blank for the local computer.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strComputerOrDomain : strComputerOrDomain = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Define the remaining script variables.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; objFSO, objCollection, objUser, objNetwork, strContainerName

&lt;span style="color: #008000;"&gt;' Create a network object; used to query the computer name.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objNetwork = WScript.CreateObject(&lt;span style="color: #800000;"&gt;"WScript.Network"&lt;/span&gt;)

&lt;span style="color: #008000;"&gt;' Create a file system object; used to creat folders.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFSO = CreateObject(&lt;span style="color: #800000;"&gt;"Scripting.FileSystemObject"&lt;/span&gt;)

&lt;span style="color: #008000;"&gt;' Test if the computer name is null.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; Len(strComputerOrDomain)=0 &lt;span style="color: #0000ff;"&gt;Or&lt;/span&gt; strComputerOrDomain=&lt;span style="color: #800000;"&gt;"."&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
  &lt;span style="color: #008000;"&gt;' If so, define the local computer name as the account repository.&lt;/span&gt;
  strComputerOrDomain = objNetwork.ComputerName
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Verify that the root path exists.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objFSO.FolderExists(strRootPath) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;

  &lt;span style="color: #008000;"&gt;' Test if the script is using local users.&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; StrComp(strComputerOrDomain,objNetwork.ComputerName,vbTextCompare)=0 &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' If so, define the local users container path.&lt;/span&gt;
    strContainerName = &lt;span style="color: #800000;"&gt;"LocalUser"&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' And define the users collection as local.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objCollection = GetObject(&lt;span style="color: #800000;"&gt;"WinNT://."&lt;/span&gt;)
  &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Otherwise, use the source name as the path.&lt;/span&gt;
    strContainerName = strComputerOrDomain
    &lt;span style="color: #008000;"&gt;' And define the users collection as remote.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objCollection = GetObject(&lt;span style="color: #800000;"&gt;"WinNT://"&lt;/span&gt; &amp;amp; strComputerOrDomain &amp;amp; &lt;span style="color: #800000;"&gt;""&lt;/span&gt;)
  &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;

  &lt;span style="color: #008000;"&gt;' Append trailing backslash if necessary.&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; Right(strRootPath,1)&amp;lt;&amp;gt;&lt;span style="color: #800000;"&gt;"\"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt; strRootPath = strRootPath &amp;amp; &lt;span style="color: #800000;"&gt;"\"&lt;/span&gt;
  &lt;span style="color: #008000;"&gt;' Define the adjusted root path for the container folder.&lt;/span&gt;
  strRootPath = strRootPath &amp;amp; strContainerName &amp;amp; &lt;span style="color: #800000;"&gt;"\"&lt;/span&gt;

  &lt;span style="color: #008000;"&gt;' Test if the container folder already exists.&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objFSO.FolderExists(strRootPath)=&lt;span style="color: #0000ff;"&gt;False&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Create the container folder if necessary.&lt;/span&gt;
    objFSO.CreateFolder(strRootPath)
  &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;

  &lt;span style="color: #008000;"&gt;' Specify the collection filter for user objects only.&lt;/span&gt;
  objCollection.Filter = Array(&lt;span style="color: #800000;"&gt;"user"&lt;/span&gt;)

  &lt;span style="color: #008000;"&gt;' Loop through the users collection.&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Each&lt;/span&gt; objUser &lt;span style="color: #0000ff;"&gt;In&lt;/span&gt; objCollection
    &lt;span style="color: #008000;"&gt;' Test if the user's account is enabled.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objUser.AccountDisabled = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
      &lt;span style="color: #008000;"&gt;' Test if the user's folder already exists.&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objFSO.FolderExists(strRootPath &amp;amp; &lt;span style="color: #800000;"&gt;"\"&lt;/span&gt; &amp;amp; objUser.Name)=&lt;span style="color: #0000ff;"&gt;False&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Create the user's folder if necessary.&lt;/span&gt;
           objFSO.CreateFolder(strRootPath &amp;amp; &lt;span style="color: #800000;"&gt;"\"&lt;/span&gt; &amp;amp; objUser.Name)
         &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
       &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
     &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;End If&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;I documented this script in great detail, so it should be self-explanatory for the most part. But just to be on the safe side, here's an explanation of what this script is doing when you run it on your FTP server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defines two user-updatable variables:
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;strRootPath&lt;/em&gt; - which specifies the physical path to the root of your FTP site.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;strComputerOrDomain&lt;/em&gt; - which specifies the computer name or the domain name where your user accounts are located. (&lt;strong&gt;Note&lt;/strong&gt;: You can leave this blank if you are using local user accounts on your FTP server.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Creates a few helper objects and determines the local computer name if necessary.&lt;/li&gt;
&lt;li&gt;Checks to see if the physical path to the root of your FTP site actually exists. before continuing.&lt;/li&gt;
&lt;li&gt;Creates a connection to the user account store (local or domain).&lt;/li&gt;
&lt;li&gt;Determines the container folder name that be the parent directory of user account folders, and creates it if necessary. (See my earlier note about the folder names.)&lt;/li&gt;
&lt;li&gt;Defines a filter for user objects in the specifies account repository. (This removes computer accounts and such from the operation.)&lt;/li&gt;
&lt;li&gt;Loops through the collection of user accounts, checks each account to see if it is enables, and creates a folder for each user account if it does not already exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="white-space: nowrap;"&gt;That's all for now. ;-]&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10406244" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/wStcRGx0bSg" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Scripting/">Scripting</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/FTP/">FTP</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/03/28/automating-the-creation-of-ftp-user-isolation-folders.aspx</feedburner:origLink></item><item><title>Advanced Log Parser Part 7 - Creating a Generic Input Format Plug-In</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/5rp1kHXLOYk/advanced-log-parser-part-7-creating-a-generic-input-format-plug-in.aspx</link><pubDate>Fri, 01 Mar 2013 02:34:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10398391</guid><dc:creator>robmcm</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/02/28/advanced-log-parser-part-7-creating-a-generic-input-format-plug-in.aspx#comments</comments><description>&lt;p&gt;In Part 6 of this series, I showed how to create a very basic COM-based input format provider for Log Parser. I wrote that blog post as a follow-up to an &lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2012/05/25/advanced-log-parser-charts-part-4-adding-custom-input-formats.aspx" target="_blank"&gt;earlier blog post&lt;/a&gt; where I had written a more complex COM-based input format provider for Log Parser that worked with FTP RSCA events. My original blog post had resulted in several requests for me to write some easier examples about how to get started writing COM-based input format providers for Log Parser, and those appeals led me to write my last blog post:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2013/02/27/advanced-log-parser-part-6-creating-a-simple-custom-input-format-plug-in.aspx" target="_blank"&gt;Advanced Log Parser Part 6 - Creating a Simple Custom Input Format Plug-In&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The example in that blog post simply returns static data, which was the easiest example that I could demonstrate.&lt;/p&gt;
&lt;p&gt;For this follow-up blog post, I will illustrate how to create a simple COM-based input format plug-in for Log Parser that you can use as a generic provider for consuming data in text-based log files. Please bear in mind that this is just an example to help developers get started writing their own COM-based input format providers; you might be able to accomplish some of what I will demonstrate in this blog post by using the built-in Log Parser functionality. That being said, this still seems like the best example to help developers get started because consuming data in text-based log files was the most-often-requested example that I received.&lt;/p&gt;
&lt;h3&gt;In Review: Creating COM-based plug-ins for Log Parser&lt;/h3&gt;
&lt;p&gt;In my earlier blog posts, I mentioned that a COM plug-in has to support several public methods. You can look at those blog posts when you get the chance, but it is a worthwhile endeavor for me to copy the following information from those blog posts since it is essential to understanding how the code sample in this blog post is supposed to work.&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="1" cellspacing="1" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="padding: 3px; text-align: left;"&gt;Method Name&lt;/th&gt;&lt;th style="padding: 3px; text-align: left;"&gt;Description&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;OpenInput&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Opens your data source and sets up any initial environment settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;GetFieldCount&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the number of fields that your plug-in will provide.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;GetFieldName&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the name of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;GetFieldType&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the datatype of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;GetValue&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the value of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;ReadRecord&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Reads the next record from your data source.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;tt&gt;CloseInput&lt;/tt&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Closes your data source and cleans up any environment settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Once you have created and registered a COM-based input format plug-in, you call it from Log Parser by using something like the following syntax:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser.exe &lt;span style="white-space: nowrap;"&gt;"SELECT * FROM FOO"&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:BAR&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;In the preceding example, &lt;strong&gt;&lt;em&gt;FOO&lt;/em&gt;&lt;/strong&gt; is a data source that makes sense to your plug-in, and &lt;em&gt;&lt;strong&gt;BAR&lt;/strong&gt;&lt;/em&gt; is the COM class name for your plug-in.&lt;/p&gt;
&lt;h3&gt;Creating a Generic COM plug-in for Log Parser&lt;/h3&gt;
&lt;p&gt;As I have done in my previous two blog posts about creating COM-based input format plug-ins, I'm going to demonstrate how to create a COM component by using a scriptlet since no compilation is required. This generic plug-in will parse any text-based log files where records are delimited by CRLF sequences and fields/columns are delimited by a separator that is defined as a constant in the code sample.&lt;/p&gt;
&lt;p&gt;To create the sample COM plug-in, copy the following code into a text file, and save that file as "&lt;em&gt;Generic.LogParser.Scriptlet.sct&lt;/em&gt;" to your computer. (Note: The *.SCT file extension tells Windows that this is a scriptlet file.)&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #f0f0f0;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPTLET&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;registration&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Description&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Simple Log Parser Scriptlet"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Progid&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Generic.LogParser.Scriptlet"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Classid&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{4e616d65-6f6e-6d65-6973-526f62657274}"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Version&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1.00"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Remotable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="False"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;comment&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="background-color: #f0f0f0;"&gt;EXAMPLE: logparser "&lt;span style="white-space: nowrap;"&gt;SELECT * FROM 'C:\foo\bar.log'&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;comment&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Automation"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Automation"&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="OpenInput"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="strFileName"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldCount"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldName"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldType"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ReadRecord"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetValue"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="CloseInput"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="blnAbort"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;LANGUAGE&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="VBScript"&amp;gt;&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Option&lt;/span&gt; Explicit

&lt;span style="color: #008000;"&gt;' Define the column separator in the log file.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; strSeparator = &lt;span style="color: #800000;"&gt;"|"&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Define whether the first row contains column names.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; blnHeaderRow = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' Define the field type constants.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_INTEGER   = 1
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_REAL      = 2
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_STRING    = 3
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_TIMESTAMP = 4
&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_NULL      = 5

&lt;span style="color: #008000;"&gt;' Declare variables.&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; objFSO, objFile, blnFileOpen
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; arrFieldNames, arrFieldTypes
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; arrCurrentRecord

&lt;span style="color: #008000;"&gt;' Indicate that no file has been opened.&lt;/span&gt;
blnFileOpen = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Open the input session.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; OpenInput(strFileName)
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; tmpCount
    &lt;span style="color: #008000;"&gt;' Test for a file name.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; Len(strFileName)=0 &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Return a status that the parameter is incorrect.&lt;/span&gt;
        OpenInput = 87
        blnFileOpen = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test for single-quotes.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; Left(strFileName,1)=&lt;span style="color: #800000;"&gt;"'"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;And&lt;/span&gt; Right(strFileName,1)=&lt;span style="color: #800000;"&gt;"'"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Strip the single-quotes from the file name.&lt;/span&gt;
            strFileName = Mid(strFileName,2,Len(strFileName)-2)
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Open the file system object.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFSO = CreateObject(&lt;span style="color: #800000;"&gt;"Scripting.Filesystemobject"&lt;/span&gt;)
        &lt;span style="color: #008000;"&gt;' Verify that the specified file exists.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objFSO.FileExists(strFileName) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Open the specified file.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFile = objFSO.OpenTextFile(strFileName,1,&lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;)
            &lt;span style="color: #008000;"&gt;' Set a flag to indicate that the specified file is open.&lt;/span&gt;
            blnFileOpen = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Retrieve an initial record.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Call&lt;/span&gt; ReadRecord()
            &lt;span style="color: #008000;"&gt;' Redimension the array of field names.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;ReDim&lt;/span&gt; arrFieldNames(UBound(arrCurrentRecord))
            &lt;span style="color: #008000;"&gt;' Loop through the record fields.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; tmpCount = 0 &lt;span style="color: #0000ff;"&gt;To&lt;/span&gt; (UBound(arrFieldNames))
                &lt;span style="color: #008000;"&gt;' Test for a header row.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; blnHeaderRow = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    arrFieldNames(tmpCount) = arrCurrentRecord(tmpCount)
                &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
                    arrFieldNames(tmpCount) = &lt;span style="color: #800000;"&gt;"Field"&lt;/span&gt; &amp;amp; (tmpCount+1)
                &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Test for a header row.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; blnHeaderRow = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                &lt;span style="color: #008000;"&gt;' Retrieve a second record.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;Call&lt;/span&gt; ReadRecord()
            &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Redimension the array of field types.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;ReDim&lt;/span&gt; arrFieldTypes(UBound(arrCurrentRecord))
            &lt;span style="color: #008000;"&gt;' Loop through the record fields.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; tmpCount = 0 &lt;span style="color: #0000ff;"&gt;To&lt;/span&gt; (UBound(arrFieldTypes))
                &lt;span style="color: #008000;"&gt;' Test if the current field contains a date.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; IsDate(arrCurrentRecord(tmpCount)) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    &lt;span style="color: #008000;"&gt;' Specify the field type as a timestamp.&lt;/span&gt;
                    arrFieldTypes(tmpCount) = TYPE_TIMESTAMP
                &lt;span style="color: #008000;"&gt;' Test if the current field contains a number.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;ElseIf&lt;/span&gt; IsNumeric(arrCurrentRecord(tmpCount)) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    &lt;span style="color: #008000;"&gt;' Test if the current field contains a decimal.&lt;/span&gt;
                    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; InStr(arrCurrentRecord(tmpCount),&lt;span style="color: #800000;"&gt;"."&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                        &lt;span style="color: #008000;"&gt;' Specify the field type as a real number.&lt;/span&gt;
                        arrFieldTypes(tmpCount) = TYPE_REAL
                    &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
                        &lt;span style="color: #008000;"&gt;' Specify the field type as an integer.&lt;/span&gt;
                        arrFieldTypes(tmpCount) = TYPE_INTEGER
                    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
                &lt;span style="color: #008000;"&gt;' Test if the current field is null.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;ElseIf&lt;/span&gt; IsNull(arrCurrentRecord(tmpCount)) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    &lt;span style="color: #008000;"&gt;' Specify the field type as NULL.&lt;/span&gt;
                    arrFieldTypes(tmpCount) = TYPE_NULL
                &lt;span style="color: #008000;"&gt;' Test if the current field is empty.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;ElseIf&lt;/span&gt; IsEmpty(arrCurrentRecord(tmpCount)) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    &lt;span style="color: #008000;"&gt;' Specify the field type as NULL.&lt;/span&gt;
                    arrFieldTypes(tmpCount) = TYPE_NULL
                &lt;span style="color: #008000;"&gt;' Otherwise, assume it's a string.&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
                    &lt;span style="color: #008000;"&gt;' Specify the field type as a string.&lt;/span&gt;
                    arrFieldTypes(tmpCount) = TYPE_STRING
                &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Temporarily close the log file.&lt;/span&gt;
            objFile.Close
            &lt;span style="color: #008000;"&gt;' Re-open the specified file.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFile = objFSO.OpenTextFile(strFileName,1,&lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;)
            &lt;span style="color: #008000;"&gt;' Test for a header row.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; blnHeaderRow = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                &lt;span style="color: #008000;"&gt;' Skip the first row.&lt;/span&gt;
                objFile.SkipLine
            &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return success status.&lt;/span&gt;
            OpenInput = 0
        &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return a file not found status.&lt;/span&gt;
            OpenInput = 2
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Close the input session.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; CloseInput(blnAbort)
    &lt;span style="color: #008000;"&gt;' Free the objects.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFile = &lt;span style="color: #0000ff;"&gt;Nothing&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFSO = &lt;span style="color: #0000ff;"&gt;Nothing&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Set a flag to indicate that the specified file is closed.&lt;/span&gt;
    blnFileOpen = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the count of fields.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldCount()
    &lt;span style="color: #008000;"&gt;' Specify the default value.&lt;/span&gt;
    GetFieldCount = 0
    &lt;span style="color: #008000;"&gt;' Test if a file is open.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; (blnFileOpen = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test for the number of field names.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; UBound(arrFieldNames) &amp;gt; 0 &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return the count of fields.&lt;/span&gt;
            GetFieldCount = UBound(arrFieldNames) + 1
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's name.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldName(intFieldIndex)
    &lt;span style="color: #008000;"&gt;' Specify the default value.&lt;/span&gt;
    GetFieldName = Null
    &lt;span style="color: #008000;"&gt;' Test if a file is open.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; (blnFileOpen = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test if the index is valid.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; intFieldIndex&amp;lt;=UBound(arrFieldNames) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return the specified field name.&lt;/span&gt;
            GetFieldName = arrFieldNames(intFieldIndex)
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's type.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldType(intFieldIndex)
    &lt;span style="color: #008000;"&gt;' Specify the default value.&lt;/span&gt;
    GetFieldType = Null
    &lt;span style="color: #008000;"&gt;' Test if a file is open.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; (blnFileOpen = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test if the index is valid.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; intFieldIndex&amp;lt;=UBound(arrFieldTypes) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return the specified field type.&lt;/span&gt;
            GetFieldType = arrFieldTypes(intFieldIndex)
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's value.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetValue(intFieldIndex)
    &lt;span style="color: #008000;"&gt;' Specify the default value.&lt;/span&gt;
    GetValue = Null
    &lt;span style="color: #008000;"&gt;' Test if a file is open.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; (blnFileOpen = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test if the index is valid.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; intFieldIndex&amp;lt;=UBound(arrCurrentRecord) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Return the specified field value based on the field type.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; arrFieldTypes(intFieldIndex)
                &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; TYPE_INTEGER:
                    GetValue = &lt;span style="color: #0000ff;"&gt;CInt&lt;/span&gt;(arrCurrentRecord(intFieldIndex))
                &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; TYPE_REAL:
                    GetValue = &lt;span style="color: #0000ff;"&gt;CDbl&lt;/span&gt;(arrCurrentRecord(intFieldIndex))
                &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; TYPE_STRING:
                    GetValue = &lt;span style="color: #0000ff;"&gt;CStr&lt;/span&gt;(arrCurrentRecord(intFieldIndex))
                &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; TYPE_TIMESTAMP:
                    GetValue = &lt;span style="color: #0000ff;"&gt;CDate&lt;/span&gt;(arrCurrentRecord(intFieldIndex))
                &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
                    GetValue = Null
            &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;
  
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Read the next record, and return true or false if there is more data.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; ReadRecord()
    &lt;span style="color: #008000;"&gt;' Specify the default value.&lt;/span&gt;
    ReadRecord = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Test if a file is open.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; (blnFileOpen = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        &lt;span style="color: #008000;"&gt;' Test if there is more data.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; objFile.AtEndOfStream &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Flag the log file as having no more data.&lt;/span&gt;
            ReadRecord = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Read the current record.&lt;/span&gt;
            arrCurrentRecord = Split(objFile.ReadLine,strSeparator)
            &lt;span style="color: #008000;"&gt;' Flag the log file as having more data to process.&lt;/span&gt;
            ReadRecord = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPT&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPTLET&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;After you have saved the scriptlet code to your computer, you register it by using the following syntax:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;regsvr32 &lt;span style="white-space: nowrap;"&gt;Generic.LogParser.Scriptlet.sct&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;At the very minimum, you can now use the COM plug-in with Log Parser by using syntax like the following:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser &lt;span style="white-space: nowrap;"&gt;"SELECT * FROM 'C:\Foo\Bar.log'"&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Next, let's analyze what this sample does.&lt;/p&gt;
&lt;h3&gt;Examining the Generic Scriptlet in Detail&lt;/h3&gt;
&lt;p&gt;Here are the different parts of the scriptlet and what they do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;registration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; section of the scriptlet sets up the COM registration information; you'll notice the COM component class name and GUID, as well as version information and a general description. (Note that you should generate your own GUID for each scriptlet that you create.)&lt;/li&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; section declares the public methods that the COM plug-in has to support.&lt;/li&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;section contains the actual implementation:
&lt;ul&gt;
&lt;li&gt;The first part of the script section declares the global variables that will be used:
&lt;ul&gt;
&lt;li&gt;The &lt;tt&gt;strSeparator&lt;/tt&gt;&amp;nbsp; constant defines the delimiter that is used to separate the data between fields/columns in a text-based log file.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;blnHeaderRow&lt;/tt&gt;&amp;nbsp; constant defines whether the first row in a text-based log file contains the names of the fields/columns:
&lt;ul&gt;
&lt;li&gt;If set to &lt;tt&gt;True&lt;/tt&gt;, the plug-in will use the data in the first line of the log file to name the fields/columns.&lt;/li&gt;
&lt;li&gt;If set to &lt;tt&gt;False&lt;/tt&gt;, the plug-in will define generic field/column names like "Field1", "Field2", etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The second part of the script contains the required methods:
&lt;ul&gt;
&lt;li&gt;The &lt;tt&gt;OpenInput()&lt;/tt&gt;&amp;nbsp; method performs several tasks:
&lt;ul&gt;
&lt;li&gt;Locates and opens the log file that you specify in your SQL statement, or returns an error if the log file cannot be found.&lt;/li&gt;
&lt;li&gt;Determines the number, names, and data types of fields/columns in the log file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;CloseInput()&lt;/tt&gt;&amp;nbsp; method cleans up the session by closing the log file and destroying objects.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;GetFieldCount()&lt;/tt&gt;&amp;nbsp; method returns the number of fields/columns in the log file.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;GetFieldName()&lt;/tt&gt;&amp;nbsp; method returns the name of a field/column in the log file.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;GetFieldType()&lt;/tt&gt;&amp;nbsp; method returns the data type of a field/column in the log file. As a reminder, Log Parser supports the following five data types for COM plug-ins: &lt;tt&gt;TYPE_INTEGER&lt;/tt&gt;, &lt;tt&gt;TYPE_REAL&lt;/tt&gt;, &lt;tt&gt;TYPE_STRING&lt;/tt&gt;, &lt;tt&gt;TYPE_TIMESTAMP&lt;/tt&gt;, and &lt;tt&gt;TYPE_NULL&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;GetValue()&lt;/tt&gt;&amp;nbsp; method returns the data value of a field/column in the log file.&lt;/li&gt;
&lt;li&gt;The &lt;tt&gt;ReadRecord()&lt;/tt&gt;&amp;nbsp; method moves to the next line in the log file. This method returns &lt;em&gt;True &lt;/em&gt;if there is additional data to read, or &lt;em&gt;False &lt;/em&gt;when the end of data is reached.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, let's look at how to use the sample.&lt;/p&gt;
&lt;h3&gt;Using the Generic Scriptlet with Log Parser&lt;/h3&gt;
&lt;p&gt;As a sample log file for this blog, I'm going to use the data in the &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms762271.aspx" target="_blank"&gt;Sample XML File (books.xml)&lt;/a&gt;&lt;/em&gt; from MSDN. By running a quick Log Parser query that I will show later, I was able to export data from the XML file into text file named "books.log" that represents an example of a simple log file format that I have had to work with in the past:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;&lt;span style="white-space: nowrap;"&gt;id|publish_date|author|title|price&lt;br /&gt; bk101|2000-10-01|Gambardella, Matthew|XML Developer's Guide|44.950000&lt;br /&gt; bk102|2000-12-16|Ralls, Kim|Midnight Rain|5.950000&lt;br /&gt; bk103|2000-11-17|Corets, Eva|Maeve Ascendant|5.950000&lt;br /&gt; bk104|2001-03-10|Corets, Eva|Oberon's Legacy|5.950000&lt;br /&gt; bk105|2001-09-10|Corets, Eva|The Sundered Grail|5.950000&lt;br /&gt; bk106|2000-09-02|Randall, Cynthia|Lover Birds|4.950000&lt;br /&gt; bk107|2000-11-02|Thurman, Paula|Splish Splash|4.950000&lt;br /&gt; bk108|2000-12-06|Knorr, Stefan|Creepy Crawlies|4.950000&lt;br /&gt; bk109|2000-11-02|Kress, Peter|Paradox Lost|6.950000&lt;br /&gt; bk110|2000-12-09|O'Brien, Tim|Microsoft .NET: The Programming Bible|36.950000&lt;br /&gt; bk111|2000-12-01|O'Brien, Tim|MSXML3: A Comprehensive Guide|36.950000&lt;br /&gt; bk112|2001-04-16|Galos, Mike|Visual Studio 7: A Comprehensive Guide|49.950000&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;In this example, the data is pretty easy to understand - the first row contains the list of field/column names, and the fields/columns are separated by the pipe ("|") character throughout the log file. That being said, you could easily change my sample code to use a different delimiter that your custom log files use.&lt;/p&gt;
&lt;p&gt;With that in mind, let's look at some Log Parser examples.&lt;/p&gt;
&lt;h4&gt;Example #1: Retrieving Data from a Custom Log&lt;/h4&gt;
&lt;p&gt;The first thing that you should try is to simply retrieve data from your custom plug-in, and the following query should serve as an example:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser "SELECT * &lt;span style="white-space: nowrap;"&gt;FROM 'C:\sample\books.log'&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;The above query will return results like the following:&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;id&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;publish_date&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;author&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;title&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;price&lt;/tt&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;-----&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;--------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;-------------------------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;---------&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk101&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;10/1/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Gambardella, Matthew&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;XML Developer's Guide&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;44.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk102&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/16/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Ralls, Kim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Midnight Rain&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk103&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/17/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Maeve Ascendant&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk104&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;3/10/2001 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Oberon's Legacy&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk105&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;9/10/2001 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;The Sundered Grail&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk106&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;9/2/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Randall, Cynthia&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Lover Birds&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk107&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/2/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Thurman, Paula&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Splish Splash&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk108&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/6/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Knorr, Stefan&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Creepy Crawlies&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk109&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/2/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Kress, Peter&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Paradox Lost&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;6.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk110&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/9/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;O'Brien, Tim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Microsoft .NET: The Programming Bible&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;36.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk111&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/1/2000 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;O'Brien, Tim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;MSXML3: A Comprehensive Guide&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;36.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk112&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4/16/2001 0:00:00&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Galos, Mike&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Visual Studio 7: A Comprehensive Guide&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;49.950000&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;" colspan="5"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Statistics:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;-----------&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements processed:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements output:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Execution time:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;0.16 seconds&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;While the above example works a good proof-of-concept for functionality, it's not overly useful, so let's look at additional examples.&lt;/p&gt;
&lt;h4&gt;Example #2: Reformatting Log File Data&lt;/h4&gt;
&lt;p&gt;Once you have established that you can retrieve data from your custom plug-in, you can start taking advantage of Log Parser's features to process your log file data. In this example, I will use several of the built-in functions to reformat the data:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser "SELECT id AS ID, TO_DATE(publish_date) AS Date, author AS Author, SUBSTR(title,0,20) AS Title, STRCAT(TO_STRING(TO_INT(FLOOR(price))),SUBSTR(TO_STRING(price),INDEX_OF(TO_STRING(price),'.'),3)) AS Price &lt;span style="white-space: nowrap;"&gt;FROM 'C:\sample\books.log'&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;The above query will return results like the following:&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;ID&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Date&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Author&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Title&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Price&lt;/tt&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;-----&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;----------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;--------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;--------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;-----&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk101&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;10/1/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Gambardella, Matthew&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;XML Developer's Guid&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;44.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk102&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/16/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Ralls, Kim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Midnight Rain&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk103&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/17/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Maeve Ascendant&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk104&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;3/10/2001&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Oberon's Legacy&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk105&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;9/10/2001&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;The Sundered Grail&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;5.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk106&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;9/2/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Randall, Cynthia&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Lover Birds&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk107&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/2/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Thurman, Paula&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Splish Splash&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk108&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/6/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Knorr, Stefan&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Creepy Crawlies&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk109&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;11/2/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Kress, Peter&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Paradox Lost&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;6.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk110&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/9/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;O'Brien, Tim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Microsoft .NET: The&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;36.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk111&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12/1/2000&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;O'Brien, Tim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;MSXML3: A Comprehens&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;36.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;bk112&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;4/16/2001&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Galos, Mike&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Visual Studio 7: A C&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;49.95&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;" colspan="5"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Statistics:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;-----------&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements processed:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements output:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Execution time:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;0.02 seconds&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;This example reformats the dates and prices a little nicer, and it truncates the book titles at 20 characters so they fit a little better on some screens.&lt;/p&gt;
&lt;h4&gt;Example #3: Processing Log File Data&lt;/h4&gt;
&lt;p&gt;In addition to simply reformatting your data, you can use Log Parser to group, sort, count, total, etc., your data. The following example illustrates how to use Log Parser to count the number of books by author in the log file:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser "SELECT author AS Author, COUNT(Title) AS Books &lt;span style="white-space: nowrap;"&gt;FROM 'C:\sample\books.log'&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;GROUP BY Author&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;ORDER BY Author&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;The above query will return results like the following:&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Author&lt;/tt&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Books&lt;/tt&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;--------------------&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;-----&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Corets, Eva&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;3&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Galos, Mike&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Gambardella, Matthew&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Knorr, Stefan&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Kress, Peter&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;O'Brien, Tim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;2&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Ralls, Kim&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Randall, Cynthia&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Thurman, Paula&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;1&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;" colspan="2"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Statistics:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;-----------&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements processed:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;12&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Elements output:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;9&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;Execution time:&lt;/tt&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;tt&gt;0.03 seconds&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The results are pretty straight-forward: Log Parser parses the data and presents you with a list of alphabetized authors and the total number of books that were written by each author.&lt;/p&gt;
&lt;h4&gt;Example #4: Creating Charts&lt;/h4&gt;
&lt;p&gt;You can also use data from your custom log file to create charts through Log Parser. If I modify the above example, all that I need to do is add a few parameters to create a chart:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser "SELECT author AS Author, COUNT(Title) AS Books &lt;span style="white-space: nowrap;"&gt;INTO Authors.gif&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;FROM 'C:\sample\books.log'&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;GROUP BY Author&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;ORDER BY Author&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:COM&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iProgID:Generic.LogParser.Scriptlet&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-fileType:GIF&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-groupSize:800x600&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-chartType:Pie&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-categories:OFF&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-values:ON&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-legend:ON&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;The above query will create a chart like the following:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="https://1kzzfw.bn1.livefilestore.com/y1ppJN6qyPD5EL8H7r1efHfXgjVfmpHPOB0BgFz2gr8VXxcUUO4T6VTO1-2NhsrKobBSWqnIhTOUinB0GMNJ7WctzdB0xzYyoHB/Part7a.png" target="_blank"&gt;&lt;img src="https://1kzzfw.bn1.livefilestore.com/y1ppJN6qyPD5EL8H7r1efHfXgjVfmpHPOB0BgFz2gr8VXxcUUO4T6VTO1-2NhsrKobBSWqnIhTOUinB0GMNJ7WctzdB0xzYyoHB/Part7a.png" alt="" width="400" height="300" border="2" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I admit that it's not a very pretty-looking chart - you can look at the other posts in my &lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/logparser/" target="_blank"&gt;Log Parser series&lt;/a&gt; for some examples about making Log Parser charts more interesting.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;In this blog post and my last post, I have illustrated a few examples that should help developers get started writing their own custom input format plug-ins for Log Parser. As I mentioned in each of the blog posts where I have used scriptlets for the COM objects, I would typically use C# or C++ to create a COM component, but using a scriptlet is much easier for demos because it doesn't require installing Visual Studio and compiling a DLL.&lt;/p&gt;
&lt;p&gt;There is one last thing that I would like to mention before I finish this blog; I mentioned earlier that I had used Log Parser to reformat the sample Books.xml file into a generic log file that I could use for the examples in this blog. Since Log Parser supports XML as an input format and it allows you to customize your output, I wrote the following simple Log Parser query to reformat the XML data into a format that I had often seen used for text-based log files:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser.exe "SELECT id,publish_date,author,title,price &lt;span style="white-space: nowrap;"&gt;INTO books.log&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;FROM books.xml&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:xml&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-o:tsv&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-headers:ON&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-oSeparator:"|"&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Actually, this ability to change data formats is one of the hidden gems of Log Parser; I have often used Log Parser to change the data from one type of log file to another - usually so that a different program can access the data. For example, if you were given the log file with a pipe ("|") delimiter like I used as an example, you could easily use Log Parser to convert that data into the CSV format so you could open it in Excel:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser.exe "SELECT id,publish_date,author,title,price &lt;span style="white-space: nowrap;"&gt;INTO books.csv&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;FROM books.log&lt;/span&gt;" &lt;span style="white-space: nowrap;"&gt;-i:tsv&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-o:csv&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-headers:ON&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-iSeparator:"|"&lt;/span&gt; &lt;span style="white-space: nowrap;"&gt;-oDQuotes:on&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;I hope these past few blog posts help you to get started writing your own custom input format plug-ins for Log Parser.&lt;/p&gt;
&lt;p&gt;That's all for now. &lt;span style="white-space: nowrap;"&gt;;-)&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10398391" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/5rp1kHXLOYk" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Scripting/">Scripting</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/LogParser/">LogParser</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/XML/">XML</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/02/28/advanced-log-parser-part-7-creating-a-generic-input-format-plug-in.aspx</feedburner:origLink></item><item><title>Advanced Log Parser Part 6 - Creating a Simple Custom Input Format Plug-In</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/OfdczHCN6h4/advanced-log-parser-part-6-creating-a-simple-custom-input-format-plug-in.aspx</link><pubDate>Wed, 27 Feb 2013 09:38:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10397511</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/02/27/advanced-log-parser-part-6-creating-a-simple-custom-input-format-plug-in.aspx#comments</comments><description>&lt;p&gt;In Part 4 of this series, I illustrated how to create a new COM-based input provider for Log Parser from a custom input format:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2012/05/25/advanced-log-parser-charts-part-4-adding-custom-input-formats.aspx" target="_blank"&gt;Advanced Log Parser Charts Part 4 - Adding Custom Input Formats&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the sample that I published in that blog, I wrote a plug-in that consumed FTP RSCA events, which is highly structured data, and it added a lot of complexity to my example. In the past ten months or so since I published my original blog, I've had several requests for additional information about how to get started writing COM-based input formats for Log Parser, so it occurred to me that perhaps I could have shown a simpler example to get people started instead of diving straight into parsing RSCA data. &lt;span style="white-space: nowrap;"&gt;;-)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With that in mind, I thought that I would write a couple of blog posts with simpler examples to help anyone who wants to get started writing custom input formats for Log Parser.&lt;/p&gt;
&lt;p&gt;For this blog post, I will show you how to create a very basic COM-based input format provider for Log Parser that simply returns static data; you could use this sample as a template to quickly get up-and-running with the basic concepts. (I promise to follow this blog with another real-world example that is still easier-to-use than my RSCA example.)&lt;/p&gt;
&lt;h3&gt;A Reminder about Creating COM-based plug-ins for Log Parser&lt;/h3&gt;
&lt;p&gt;In the blog that I referred to earlier, I mentioned that a COM plug-in has to support the following public methods:&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="1" cellspacing="1" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="padding: 3px; text-align: left;"&gt;Method Name&lt;/th&gt;&lt;th style="padding: 3px; text-align: left;"&gt;Description&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;OpenInput&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Opens your data source and sets up any initial environment settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;GetFieldCount&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the number of fields that your plug-in will provide.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;GetFieldName&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the name of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;GetFieldType&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the datatype of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;GetValue&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Returns the value of a specified field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;ReadRecord&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Reads the next record from your data source.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;&lt;code&gt;CloseInput&lt;/code&gt;&lt;/td&gt;
&lt;td style="padding: 3px; text-align: left;"&gt;Closes your data source and cleans up any environment settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Once you have created and registered a COM plug-in, you call it by using something like the following syntax:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser.exe "SELECT * FROM FOO" -i:COM -iProgID:BAR&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;In the preceding example, &lt;strong&gt;&lt;em&gt;FOO&lt;/em&gt;&lt;/strong&gt; is a data source that makes sense to your plug-in, and &lt;em&gt;&lt;strong&gt;BAR&lt;/strong&gt;&lt;/em&gt; is the COM class name for your plug-in.&lt;/p&gt;
&lt;h3&gt;Creating a Simple COM plug-in for Log Parser&lt;/h3&gt;
&lt;p&gt;Once again, I'm going to demonstrate how to create a COM component by using a scriptlet, which I like to use for demos because they are quick to design, they're easily portable, and updates take place immediately since no compilation is required. (All of that being said, if I were writing a real COM plug-in for Log Parser, I would use C# or C++.)&lt;/p&gt;
&lt;p&gt;To create the sample COM plug-in, copy the following code into a text file, and save that file as "&lt;em&gt;Simple.LogParser.Scriptlet.sct&lt;/em&gt;" to your computer. (Note: The *.SCT file extension tells Windows that this is a scriptlet file.)&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #f0f0f0;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPTLET&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;registration&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Description&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Simple Log Parser Scriptlet"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Progid&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Simple.LogParser.Scriptlet"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Classid&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{4e616d65-6f6e-6d65-6973-526f62657274}"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Version&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1.00"&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;Remotable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="False"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;comment&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="background-color: #f0f0f0;"&gt;EXAMPLE: logparser "SELECT * FROM FOOBAR" -i:COM -iProgID:Simple.LogParser.Scriptlet&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;comment&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Automation"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Automation"&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="OpenInput"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="strValue"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldCount"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldName"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetFieldType"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ReadRecord"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="GetValue"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="intFieldIndex"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="CloseInput"&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;parameter&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="blnAbort"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;LANGUAGE&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="VBScript"&amp;gt;&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Option&lt;/span&gt; Explicit

&lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; MAX_RECORDS = 5
&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; intRecordCount

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Open the input session.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; OpenInput(strValue)
    intRecordCount = 0
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Close the input session.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; CloseInput(blnAbort)
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the count of fields.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldCount()
    GetFieldCount = 5
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's name.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldName(intFieldIndex)
    &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CInt&lt;/span&gt;(intFieldIndex)
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 0:
            GetFieldName = &lt;span style="color: #800000;"&gt;"INTEGER"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 1:
            GetFieldName = &lt;span style="color: #800000;"&gt;"REAL"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 2:
            GetFieldName = &lt;span style="color: #800000;"&gt;"STRING"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 3:
            GetFieldName = &lt;span style="color: #800000;"&gt;"TIMESTAMP"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 4:
            GetFieldName = &lt;span style="color: #800000;"&gt;"NULL"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            GetFieldName = Null
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's type.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFieldType(intFieldIndex)
    &lt;span style="color: #008000;"&gt;' Define the field type constants.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_INTEGER   = 1
    &lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_REAL      = 2
    &lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_STRING    = 3
    &lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_TIMESTAMP = 4
    &lt;span style="color: #0000ff;"&gt;Const&lt;/span&gt; TYPE_NULL      = 5
    &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CInt&lt;/span&gt;(intFieldIndex)
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 0:
            GetFieldType = TYPE_INTEGER
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 1:
            GetFieldType = TYPE_REAL
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 2:
            GetFieldType = TYPE_STRING
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 3:
            GetFieldType = TYPE_TIMESTAMP
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 4:
            GetFieldType = TYPE_NULL
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            GetFieldType = Null
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Return the specified field's value.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetValue(intFieldIndex)
    &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CInt&lt;/span&gt;(intFieldIndex)
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 0:
            GetValue = 1
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 1:
            GetValue = 1.0
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 2:
            GetValue = &lt;span style="color: #800000;"&gt;"One"&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; 3:
            GetValue = Now
        &lt;span style="color: #0000ff;"&gt;Case&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            GetValue = Null
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Select&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;
  
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' Read the next record, and return true or false if there is more data.&lt;/span&gt;
&lt;span style="color: #008000;"&gt;' --------------------------------------------------------------------------------&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; ReadRecord()
    intRecordCount = intRecordCount + 1
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; intRecordCount &amp;lt;= MAX_RECORDS &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        ReadRecord = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
        ReadRecord = &lt;span style="color: #0000ff;"&gt;False&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;

  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPT&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;

&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;SCRIPTLET&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;After you have saved the scriptlet code to your computer, you register it by using the following syntax:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;regsvr32 Simple.LogParser.Scriptlet.sct&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;At the very minimum, you can now use the COM plug-in with Log Parser by using syntax like the following:&lt;/p&gt;
&lt;p style="margin-left: 20px; background-color: #f0f0f0; color: #000000; padding: 5px;"&gt;&lt;tt&gt;logparser "SELECT * FROM FOOBAR" -i:COM -iProgID:Simple.LogParser.Scriptlet&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;This will return results like the following:&lt;/p&gt;
&lt;div style="margin-left: 20px;"&gt;
&lt;table style="border-collapse: collapse;" border="0" cellpadding="4"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;REAL&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;STRING&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;NULL&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-------&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;--------&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;------&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;------------------&lt;/code&gt;&lt;/th&gt;&lt;th style="text-align: left; padding: 3px;"&gt;&lt;code&gt;----&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1.000000&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;One&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;2/26/2013 19:42:12&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1.000000&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;One&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;2/26/2013 19:42:12&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1.000000&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;One&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;2/26/2013 19:42:12&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1.000000&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;One&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;2/26/2013 19:42:12&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;1.000000&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;One&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;2/26/2013 19:42:12&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;Statistics:&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;-----------&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;Elements processed:&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;Elements output:&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;Execution time:&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&lt;code&gt;0.01 seconds&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left; padding: 3px;"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Next, let's analyze what this sample does.&lt;/p&gt;
&lt;h3&gt;Examining the Sample Scriptlet Contents in Detail&lt;/h3&gt;
&lt;p&gt;Here are the different parts of the scriptlet and what they do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;registration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; section of the scriptlet sets up the COM registration information; you'll notice the COM component class name and GUID, as well as version information and a general description. (Note that you should generate your own GUID for each scriptlet that you create.)&lt;/li&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;implements&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; section declares the public methods that the COM plug-in has to support.&lt;/li&gt;
&lt;li&gt;The &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;section contains the actual implementation:
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;OpenInput()&lt;/code&gt; method opens your data source, although in this example it only initializes the record count. (Note that the value that is passed to the method will be ignored in this example.)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;CloseInput()&lt;/code&gt; method would normally clean up your session, (e.g. close a data file or database, etc.), but it doesn't do anything in this example.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GetFieldCount()&lt;/code&gt; method returns the number of data fields in each record of your data, which is static in this example.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GetFieldName()&lt;/code&gt; method returns the name of a field that is passed to the method as a number; the names are static in this example.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GetFieldType()&lt;/code&gt; method returns the data type of a field that is passed to the method as a number, which are statically-defined in this example. As a reminder, Log Parser supports the following five data types for COM plug-ins: &lt;code&gt;TYPE_INTEGER&lt;/code&gt;, &lt;code&gt;TYPE_REAL&lt;/code&gt;, &lt;code&gt;TYPE_STRING&lt;/code&gt;, &lt;code&gt;TYPE_TIMESTAMP&lt;/code&gt;, and &lt;code&gt;TYPE_NULL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GetValue()&lt;/code&gt; method returns the data value of a field that is passed to the method as a number. Once again, the data values are statically-defined in this example.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ReadRecord()&lt;/code&gt; method moves to the next record in your data set; this method returns &lt;em&gt;True &lt;/em&gt;if there is data to read, or &lt;em&gt;False &lt;/em&gt;when the end of data is reached. In this example, the method increments the record counter and sets the status based on whether the maximum number of records has been reached.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;That wraps up the simplest example that I could put together of a COM-based input provider for Log Parser. In my next blog, I'll show how to create a generic COM-based input provider for Log Parser that you can use to parse text-based log files.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10397511" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/OfdczHCN6h4" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Scripting/">Scripting</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/LogParser/">LogParser</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/02/27/advanced-log-parser-part-6-creating-a-simple-custom-input-format-plug-in.aspx</feedburner:origLink></item><item><title>FTP Clients - Part 12: BitKinex</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/IKxPUlCAS2k/ftp-clients-part-12-bitkinex.aspx</link><pubDate>Fri, 01 Feb 2013 07:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10390184</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/01/31/ftp-clients-part-12-bitkinex.aspx#comments</comments><description>&lt;p&gt;For this installment in my series about FTP clients, I want to take a look at &lt;a href="http://www.bitkinex.com/" target="_blank"&gt;&lt;em&gt;BitKinex 3&lt;/em&gt;&lt;/a&gt;, which is an FTP client from &lt;a href="http://www.bitkinex.com/aboutus" target="_blank"&gt;Barad-Dur, LLC&lt;/a&gt;. For this blog I used BitKinex 3.2.3, and it is available from the following URL:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="http://www.bitkinex.com/" target="_blank"&gt;http://www.bitkinex.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the time of this blog post, &lt;em&gt;BitKinex 3&lt;/em&gt; is available for free, and it contains a bunch of features that make it an appealing FTP and WebDAV client.&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1ppCg2LIfE6UtGvDzkQNOJcmbMQ8wwoQbi43BiIRl-LqHCg7JS2FdKWdTD1N93yoNj1jjlfI1VOpRLf-lbiywR9UAYhxwsOnhZ/BitKinex01.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1ppCg2LIfE6UtGvDzkQNOJcmbMQ8wwoQbi43BiIRl-LqHCg7JS2FdKWdTD1N93yoNj1jjlfI1VOpRLf-lbiywR9UAYhxwsOnhZ/BitKinex01.png" alt="" width="324" height="240" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 1 - The &lt;strong&gt;Help/About&lt;/strong&gt; dialog in &lt;em&gt;BitKinex 3&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;BitKinex 3 Overview&lt;/h3&gt;
&lt;p&gt;When you open &lt;em&gt;BitKinex 3&lt;/em&gt;, it shows four connection types (which it refers to as Data Sources): &lt;strong&gt;FTP&lt;/strong&gt;, &lt;strong&gt;HTTP/WebDAV&lt;/strong&gt;, &lt;strong&gt;SFTP/SSH&lt;/strong&gt;, and &lt;strong&gt;My Computer&lt;/strong&gt;. The main interface is analogous to what you would expect in a Site Manager with other FTP clients - you can define new data sources (connections) to FTP sites and websites:&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1pR0l5rMbCMD5pOcrL0K9c3DpxC2nzWss3ulEVdJ86zqKgrpMACkUERX4h_3KdtNmQtQobnaHlCdDNHD6D899PWIAyaJ6YnJzL/BitKinex02.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1pR0l5rMbCMD5pOcrL0K9c3DpxC2nzWss3ulEVdJ86zqKgrpMACkUERX4h_3KdtNmQtQobnaHlCdDNHD6D899PWIAyaJ6YnJzL/BitKinex02.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 2 - The main &lt;em&gt;BitKinex 3&lt;/em&gt; window.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Creating an FTP data source is pretty straight-forward, and there are a fair number of options that you can specify. What's more, data sources can have individual options specified, or they can inherit from a parent note.&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1p1s8eBGOvRqV9_QCOMMuL8qBchEulg0z4gqUjpez4mw8Wi7sQoT9yS9OwKoCKsL9CYth8rPxBrKYP0LDmibEFVhnSJGQjFbYr/BitKinex03.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1p1s8eBGOvRqV9_QCOMMuL8qBchEulg0z4gqUjpez4mw8Wi7sQoT9yS9OwKoCKsL9CYth8rPxBrKYP0LDmibEFVhnSJGQjFbYr/BitKinex03.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 3 - Creating a new FTP data source.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1pvexddVh1enYsxDqg9wc-xf3YgW81R4z6PRkmehmNT-Df18Dxm9fYjtlWUjLK_Fr9LtWtCVFAdb04vUHEOOUkgTQ7Iyp-x-4H/BitKinex04.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1pvexddVh1enYsxDqg9wc-xf3YgW81R4z6PRkmehmNT-Df18Dxm9fYjtlWUjLK_Fr9LtWtCVFAdb04vUHEOOUkgTQ7Iyp-x-4H/BitKinex04.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 4 - Specifying the options for an FTP data source.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Once a data source has connected, a child window will open and display the folder trees for your local and remote content. (Note: there are several options for customizing how each data source can be displayed.)&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1pXkKGLHSJz2KNb8HaA6Y5PPP96peeT-jfVtkWZvtuf-k0TZytZjNgRbjlvoMQGCP9GqAkrVRpPMcFEqCR2-CRmqc8E9TzW0n0/BitKinex05.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1pXkKGLHSJz2KNb8HaA6Y5PPP96peeT-jfVtkWZvtuf-k0TZytZjNgRbjlvoMQGCP9GqAkrVRpPMcFEqCR2-CRmqc8E9TzW0n0/BitKinex05.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 5 - An open FTP data source.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;BitKinex 3&lt;/em&gt; has support for command-line automation, which is pretty handy if you do a lot of scripting like I do. Documentation about automating &lt;em&gt;BitKinex 3&lt;/em&gt; from the command line is available on the BitKinex website at the following URL:&lt;/p&gt;
&lt;p style="margin-left: 20px;"&gt;&lt;a href="http://www.bitkinex.com/ftp/help/html/cmdline.html" target="_blank"&gt;BitKinex Command Line Interface&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That being said, the documentation is a bit sparse and there are few examples, so I didn't attempt anything ambitious from a command line during my testing.&lt;/p&gt;
&lt;h3&gt;Using BitKinex 3 with FTP over SSL (FTPS)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;BitKinex 3&lt;/em&gt; has built-in support for FTP over SSL (FTPS) supports both &lt;a href="http://blogs.msdn.com/robert_mcmurray/archive/2008/11/10/ftp-clients-part-2-explicit-ftps-versus-implicit-ftps.aspx" target="_blank"&gt;Explicit and Implicit FTPS&lt;/a&gt;. To specify the FTPS mode, you need to choose the correct mode from the &lt;strong&gt;Security&lt;/strong&gt; drop-down menu for your FTP data source.&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1phvkCtnMIiDBNP2ax0XwyphWFlGmXTaw-9xeUIUSZnl97jWDUsNHqwuFnL8UiijQt5mz-p3qXYXJZLANNsVZ7DCutaK6cf8ap/BitKinex06.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1phvkCtnMIiDBNP2ax0XwyphWFlGmXTaw-9xeUIUSZnl97jWDUsNHqwuFnL8UiijQt5mz-p3qXYXJZLANNsVZ7DCutaK6cf8ap/BitKinex06.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 6 - Specifying the FTPS mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Once you have established an FTPS connection through &lt;em&gt;BitKinex 3&lt;/em&gt;, the user experience is the same as it is for a standard FTP connection.&lt;/p&gt;
&lt;h3&gt;Using Using BitKinex 3 with True FTP Hosts&lt;/h3&gt;
&lt;p&gt;True FTP hosts are not supported natively, and even though &lt;em&gt;BitKinex 3&lt;/em&gt; allows you to send a custom command after a data source has been opened, I could not find a way to send a custom command before sending user credentials, so true FTP hosts cannot be used.&lt;/p&gt;
&lt;h3&gt;Using Using BitKinex 3 with Virtual FTP Hosts&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;BitKinex 3's&lt;/em&gt; login settings allow you to specify the virtual host name as part of the user credentials by using syntax like "ftp.example.com|username" or "ftp.example.com\username", so you can use virtual FTP hosts with &lt;em&gt;BitKinex 3&lt;/em&gt;.&lt;/p&gt;
&lt;table style="background: #ffffff; border: 2px solid #000000; width: 400px; color: #000000; margin-left: 20px; border-collapse: collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;&lt;a href="https://yy0ipa.bn1.livefilestore.com/y1p4EZ62Rl5eLLHQzvYUv1k4-wNVXPC75ZpG3Hw4ExBWfdR4f92otiCEv8dDT4AiHBnd0CjvEuCRVKpm6-yFfkZUX7oo6InSpse/BitKinex07.png" target="_blank"&gt;&lt;img src="https://yy0ipa.bn1.livefilestore.com/y1p4EZ62Rl5eLLHQzvYUv1k4-wNVXPC75ZpG3Hw4ExBWfdR4f92otiCEv8dDT4AiHBnd0CjvEuCRVKpm6-yFfkZUX7oo6InSpse/BitKinex07.png" alt="" width="400" height="300" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="top" nowrap="nowrap" width="100%"&gt;Fig. 7 - Specifying an FTP virtual host.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Scorecard for BitKinex 3&lt;/h3&gt;
&lt;p&gt;This concludes my quick look at a few of the FTP features that are available with &lt;em&gt;BitKinex 3&lt;/em&gt;, and here are the scorecard results:&lt;/p&gt;
&lt;table id="table1" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;Client&lt;br /&gt; Name&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;Directory&lt;br /&gt; Browsing&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=89117" target="_blank"&gt;Explicit&lt;br /&gt; FTPS&lt;/a&gt;&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=89117" target="_blank"&gt;Implicit&lt;br /&gt; FTPS&lt;/a&gt;&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=89119" target="_blank"&gt;Virtual&lt;br /&gt; Hosts&lt;/a&gt;&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=89119" target="_blank"&gt;True&lt;br /&gt; HOSTs&lt;/a&gt;&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;Site&lt;br /&gt; Manager&lt;/th&gt;&lt;th align="center" valign="middle" nowrap="nowrap"&gt;Extensibility&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;&lt;a href="http://www.bitkinex.com/" target="_blank"&gt;BitKinex 3.2.3&lt;/a&gt;&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;Rich&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;Y&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;Y&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;Y&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;N&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;Y&lt;/td&gt;
&lt;td align="center" valign="middle" nowrap="nowrap"&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="8" align="left" valign="top"&gt;Note: I could not find anyway to extend the functionality of &lt;em&gt;BitKinex 3&lt;/em&gt;; but as I&lt;br /&gt; mentioned earlier, it does support command-line automation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That wraps it up this blog - &lt;em&gt;BitKinex 3&lt;/em&gt; is pretty cool FTP client with a lot of options, and I think that my next plan of action is to try out the WebDAV features that are available in &lt;em&gt;BitKinex 3&lt;/em&gt;. ;-)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10390184" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/IKxPUlCAS2k" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/FTP/">FTP</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/01/31/ftp-clients-part-12-bitkinex.aspx</feedburner:origLink></item><item><title>Restarting the FTP Service Orphans a DLLHOST.EXE Process</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/LrexkpjnND0/restarting-the-ftp-service-orphans-a-dllhost-exe-process.aspx</link><pubDate>Thu, 31 Jan 2013 10:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10389866</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/01/31/restarting-the-ftp-service-orphans-a-dllhost-exe-process.aspx#comments</comments><description>&lt;p&gt;I was recently creating a new authentication provider using FTP extensibility, and I ran into a weird behavior that I had seen before. With that in mind, I thought my situation would make a great blog subject because someone else may run into it.&lt;/p&gt;
&lt;p&gt;Here are the details of the situation: let's say that you are developing a new FTP provider for IIS, and your code changes never seem to take effect. Your provider appears to be working, it's just that any new functionality is not reflected in your provider's behavior. You restart the FTP service as a troubleshooting step, but that does not appear to make any difference.&lt;/p&gt;
&lt;p&gt;I'll bypass mentioning any other troubleshooting tasks and cut to the chase - if you read my &lt;em&gt;&lt;a href="http://blogs.msdn.com/b/robert_mcmurray/archive/2011/12/01/changing-the-identity-of-the-ftp-extensibility-process.aspx" target="_blank"&gt;Changing the Identity of the FTP 7 Extensibility Process&lt;/a&gt;&lt;/em&gt; blog post a year ago, you will recall that I mentioned that all custom FTP extensibility providers are executed through COM+ in a DLLHOST.exe process. When you restart the FTP service, that &lt;em&gt;should&lt;/em&gt; clean up the DLLHOST.EXE process that is being used for FTP extensibility. However, if you are developing custom FTP providers and the DLLHOST.EXE process is not terminated by the FTP service, you may find yourself in a situation where you have a DLLHOST.EXE process in memory that contains an older copy of your provider, which will not be removed from memory until the DLLHOST.EXE process for FTP extensibility has been forcibly terminated.&lt;/p&gt;
&lt;p style="padding-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1p3kzaZwNRV2UTIQaG7LFp8BgkwqLs6kLrlKTYWkIT7iTILwmiMZMsIU7e7zWktAtqri7cEYo_tq-UUDf060ajfFhTqzTEelms/DLLHOST.EXE.1.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1p3kzaZwNRV2UTIQaG7LFp8BgkwqLs6kLrlKTYWkIT7iTILwmiMZMsIU7e7zWktAtqri7cEYo_tq-UUDf060ajfFhTqzTEelms/DLLHOST.EXE.1.png" alt="" width="450" height="337" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have read some of my earlier blog posts or walkthroughs on IIS.NET, you may have noticed that I generally like to use a few pre-build and post-build commands in my FTP projects; usually I add these commands in order to to automatically register/unregister my FTP providers in the Global Assembly Cache (GAC).&lt;/p&gt;
&lt;p style="padding-left: 20px;"&gt;&lt;a href="https://bxs1ug.bn1.livefilestore.com/y1pUdeQ7JvBeUk6jlUMutsMLxA52CsfPVxak_lUnUh9Ym7SIz6a6qRbcffVI3R2PRMz8_QVIKUuT6Zs1_fwtEZY61ylnSJxnHHy/DLLHOST.EXE.2.png" target="_blank"&gt;&lt;img src="https://bxs1ug.bn1.livefilestore.com/y1pUdeQ7JvBeUk6jlUMutsMLxA52CsfPVxak_lUnUh9Ym7SIz6a6qRbcffVI3R2PRMz8_QVIKUuT6Zs1_fwtEZY61ylnSJxnHHy/DLLHOST.EXE.2.png" alt="" width="450" height="337" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With a little modification and some command-line wizardry, you can automate the termination of any orphaned DLLHOST.EXE processes that are being used for FTP extensibility. With that in mind, here are some example pre-build/post-build commands that will unregister/reregister your provider in the GAC, restart the FTP service, and terminate any orphaned FTP extensibility DLLHOST.EXE processes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: The following syntax was written using Visual Studio 2010; you would need to change &lt;span style="white-space: nowrap;"&gt;"%VS100COMNTOOLS%"&lt;/span&gt; to &lt;span style="white-space: nowrap;"&gt;"%VS90COMNTOOLS%"&lt;/span&gt; for Visual Studio 2008 or &lt;span style="white-space: nowrap;"&gt;"%VS110COMNTOOLS%"&lt;/span&gt; for Visual Studio 2012.&lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left: 20px;"&gt;&lt;strong&gt;Pre-build Commands&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;net stop ftpsvc&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;call "%VS100COMNTOOLS%\vsvars32.bat"&amp;gt;nul&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;cd /d "$(TargetDir)"&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;gacutil.exe /uf "$(TargetName)"&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;for /f "usebackq tokens=1,2* delims=," %%a in (`tasklist /fi "MODULES eq Microsoft.Web.FtpServer.*" /fi "IMAGENAME eq DLLHOST.EXE" /fo csv ^| find /i "dllhost.exe"`) do taskkill /f /pid %%b&lt;/tt&gt;&lt;/p&gt;
&lt;p style="padding-left: 20px;"&gt;&lt;strong&gt;Post-build Commands&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;call "%VS100COMNTOOLS%\vsvars32.bat"&amp;gt;nul&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;gacutil.exe /if "$(TargetPath)"&lt;/tt&gt;&lt;/p&gt;
&lt;p style="text-indent: -20px; padding-left: 60px;"&gt;&lt;tt&gt;net start ftpsvc&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;The syntax is a little tricky for the &lt;tt&gt;FOR&lt;/tt&gt; statement, so be carefully when typing or copying/pasting that into your projects. For example, you need to make sure that all of the code from the &lt;tt&gt;FOR&lt;/tt&gt; statement through the &lt;tt&gt;TASKKILL&lt;/tt&gt; command are on the same line in your project's properties.&lt;/p&gt;
&lt;p&gt;When you compile your provider, Visual Studio should display something like the following:&lt;/p&gt;
&lt;p style="padding-left: 20px;"&gt;&lt;tt&gt;------ Rebuild All started: Project: FtpBlogEngineNetAuthentication, Configuration: Release Any CPU ------ &lt;br /&gt;The Microsoft FTP Service service is stopping. &lt;br /&gt;The Microsoft FTP Service service was stopped successfully. &lt;br /&gt; &lt;br /&gt;Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1 &lt;br /&gt;Copyright (c) Microsoft Corporation. All rights reserved. &lt;br /&gt; &lt;br /&gt;Assembly: FtpBlogEngineNetAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73, processorArchitecture=MSIL &lt;br /&gt;Uninstalled: FtpBlogEngineNetAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73, processorArchitecture=MSIL &lt;br /&gt;Number of assemblies uninstalled = 1 &lt;br /&gt;Number of failures = 0 &lt;br /&gt;SUCCESS: The process with PID 12656 has been terminated. &lt;br /&gt;FtpBlogEngineNetAuthentication -&amp;gt; C:\Users\dude\Documents\Visual Studio 2010\Projects\FtpBlogEngineNetAuthentication\FtpBlogEngineNetAuthentication\bin\Release\FtpBlogEngineNetAuthentication.dll &lt;br /&gt;Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1 &lt;br /&gt;Copyright (c) Microsoft Corporation. All rights reserved. &lt;br /&gt; &lt;br /&gt;Assembly successfully added to the cache &lt;br /&gt;The Microsoft FTP Service service is starting. &lt;br /&gt;The Microsoft FTP Service service was started successfully. &lt;br /&gt; &lt;br /&gt;========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;If you analyze the output from the build process, you will see that the commands in my earlier samples stopped the FTP service, removed the existing assembly from the GAC, terminated any orphaned DLLHOST.EXE processes, registered the newly-built DLL in the GAC, and then restarted the FTP service.&lt;/p&gt;
&lt;p&gt;By utilizing these pre-build/post-build commands, I have been able to work around situations where a DLLHOST.EXE process is being orphaned and caching old assemblies in memory.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10389866" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/LrexkpjnND0" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Scripting/">Scripting</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/FTP/">FTP</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Extensibility/">Extensibility</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2013/01/31/restarting-the-ftp-service-orphans-a-dllhost-exe-process.aspx</feedburner:origLink></item><item><title>Using Classic ASP and URL Rewrite for Dynamic SEO Functionality</title><link>http://feedproxy.google.com/~r/RobertMcMurraysMsdnBlog/~3/9nuImvzTIU8/using-classic-asp-and-url-rewrite-for-dynamic-seo-functionality.aspx</link><pubDate>Tue, 01 Jan 2013 00:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10381558</guid><dc:creator>robmcm</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/b/robert_mcmurray/archive/2012/12/31/using-classic-asp-and-url-rewrite-for-dynamic-seo-functionality.aspx#comments</comments><description>&lt;p&gt;I had another interesting situation present itself recently that I thought would make a good blog: how to use Classic ASP with the IIS URL Rewrite module to dynamically generate &lt;em&gt;Robots.txt&lt;/em&gt; and &lt;em&gt;Sitemap.xml&lt;/em&gt; files.&lt;/p&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Here's the situation: I host a website for one of my family members, and like everyone else on the Internet, he wanted some better SEO rankings. We discussed a few things that he could do to improve his visibility with search engines, and one of the suggestions that I gave him was to keep his &lt;em&gt;Robots.txt&lt;/em&gt; and &lt;em&gt;Sitemap.xml&lt;/em&gt; files up-to-date. But there was an additional caveat - he uses two separate DNS names for the same website, and that presents a problem for absolute URLs in either of those files. Before anyone points out that it's usually not a good idea to host multiple DNS names on the same content, there are times when this is acceptable; for example, if you are trying to decide which of several DNS names is the best to use, you might want to bind each name to the same IP address and parse your logs to find out which address is getting the most traffic.&lt;/p&gt;
&lt;p&gt;In any event, the syntax for both &lt;em&gt;Robots.txt&lt;/em&gt; and &lt;em&gt;Sitemap.xml&lt;/em&gt; files is pretty easy, so I wrote a couple of simple Classic ASP &lt;em&gt;Robots.asp&lt;/em&gt; and &lt;em&gt;Sitemap.asp&lt;/em&gt; pages that output the correct syntax and DNS-specific URLs for each domain name, and I wrote some simple URL Rewrite rules that rewrite inbound requests for &lt;em&gt;Robots.txt&lt;/em&gt; and &lt;em&gt;Sitemap.xml&lt;/em&gt; files to the ASP pages, while blocking direct access to the Classic ASP pages themselves.&lt;/p&gt;
&lt;p&gt;All of that being said, there are a couple of quick things that I would like to mention before I get to the code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First of all, I chose Classic ASP for the files because it allows the code to run without having to load any additional framework; I could have used ASP.NET or PHP just as easily, but either of those would require additional overhead that isn't really required.&lt;/li&gt;
&lt;li&gt;Second, the specific website for which I wrote these specific examples consists of all static content that is updated a few times a month, so I wrote the example to parse the physical directory structure for the website's URLs and specified a weekly interval for search engines to revisit the website. All of these options can easily be changed; for example, I reused this code a little while later for a website where all of the content was created dynamically from a database, and I updated the code in the &lt;em&gt;Sitemap.asp&lt;/em&gt; file to create the URLs from the dynamically-generated content. (That's really easy to do, but outside the scope of this blog.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That being said, let's move on to the actual code.&lt;/p&gt;
&lt;h3&gt;Creating the Required Files&lt;/h3&gt;
&lt;p&gt;There are three files that you will need to create for this example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;em&gt;Robots.asp&lt;/em&gt; file to which URL Rewrite will send requests for &lt;em&gt;Robots.txt&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;Sitemap.asp&lt;/em&gt; file to which URL Rewrite will send requests for &lt;em&gt;Sitemap.xml&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;Web.config&lt;/em&gt; file that contains the URL Rewrite rules&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Step 1 - Creating the Robots.asp File&lt;/h4&gt;
&lt;p&gt;You need to save the following code sample as &lt;em&gt;Robots.asp&lt;/em&gt; in the root of your website; this page will be executed whenever someone requests the &lt;em&gt;Robots.txt&lt;/em&gt; file for your website. This example is very simple: it checks for the requested hostname and uses that to dynamically create the absolute URL for the website's &lt;em&gt;Sitemap.xml&lt;/em&gt; file.&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&amp;lt;%
    &lt;span style="color: #0000ff;"&gt;Option Explicit&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;On Error Resume Next&lt;/span&gt;
    
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strUrlRoot
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strHttpHost
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strUserAgent

    Response.Clear
    Response.Buffer = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;
    Response.ContentType = &lt;span style="color: #800000;"&gt;"text/plain"&lt;/span&gt;
    Response.CacheControl = &lt;span style="color: #800000;"&gt;"public"&lt;/span&gt;

    Response.Write &lt;span style="color: #800000;"&gt;"# Robots.txt"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"# For more information on this file see:"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"# http://www.robotstxt.org/"&lt;/span&gt; &amp;amp; vbCrLf &amp;amp; vbCrLf

    strHttpHost = LCase(Request.ServerVariables(&lt;span style="color: #800000;"&gt;"HTTP_HOST"&lt;/span&gt;))
    strUserAgent = LCase(Request.ServerVariables(&lt;span style="color: #800000;"&gt;"HTTP_USER_AGENT"&lt;/span&gt;))
    strUrlRoot = &lt;span style="color: #800000;"&gt;"http://"&lt;/span&gt; &amp;amp; strHttpHost

    Response.Write &lt;span style="color: #800000;"&gt;"# Define the sitemap path"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"Sitemap: "&lt;/span&gt; &amp;amp; strUrlRoot &amp;amp; &lt;span style="color: #800000;"&gt;"/sitemap.xml"&lt;/span&gt; &amp;amp; vbCrLf &amp;amp; vbCrLf

    Response.Write &lt;span style="color: #800000;"&gt;"# Make changes for all web spiders"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"User-agent: *"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"Allow: /"&lt;/span&gt; &amp;amp; vbCrLf
    Response.Write &lt;span style="color: #800000;"&gt;"Disallow: "&lt;/span&gt; &amp;amp; vbCrLf
    Response.End
%&amp;gt;&lt;/pre&gt;
&lt;h4&gt;Step 2 - Creating the Sitemap.asp File&lt;/h4&gt;
&lt;p&gt;The following example file is also pretty simple, and you would save this code as &lt;em&gt;Sitemap.asp&lt;/em&gt; in the root of your website. There is a section in the code where it loops through the file system looking for files with the *.html file extension and only creates URLs for those files. If you want other files included in your results, or you want to change the code from static to dynamic content, this is where you would need to update the file accordingly.&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&amp;lt;%
    &lt;span style="color: #0000ff;"&gt;Option Explicit&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;On Error Resume Next&lt;/span&gt;
    
    Response.Clear
    Response.Buffer = &lt;span style="color: #0000ff;"&gt;True&lt;/span&gt;
    Response.AddHeader &lt;span style="color: #800000;"&gt;"Connection"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"Keep-Alive"&lt;/span&gt;
    Response.CacheControl = &lt;span style="color: #800000;"&gt;"public"&lt;/span&gt;
    
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strFolderArray, lngFolderArray
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strUrlRoot, strPhysicalRoot, strFormat
    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; strUrlRelative, strExt

    &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; objFSO, objFolder, objFile

    strPhysicalRoot = Server.MapPath(&lt;span style="color: #800000;"&gt;"/"&lt;/span&gt;)
    &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFSO = Server.CreateObject(&lt;span style="color: #800000;"&gt;"Scripting.Filesystemobject"&lt;/span&gt;)
    
    strUrlRoot = &lt;span style="color: #800000;"&gt;"http://"&lt;/span&gt; &amp;amp; Request.ServerVariables(&lt;span style="color: #800000;"&gt;"HTTP_HOST"&lt;/span&gt;)
    
    &lt;span style="color: #008000;"&gt;' Check for XML or TXT format.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; UCase(Trim(Request(&lt;span style="color: #800000;"&gt;"format"&lt;/span&gt;)))=&lt;span style="color: #800000;"&gt;"XML"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        strFormat = &lt;span style="color: #800000;"&gt;"XML"&lt;/span&gt;
        Response.ContentType = &lt;span style="color: #800000;"&gt;"text/xml"&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
        strFormat = &lt;span style="color: #800000;"&gt;"TXT"&lt;/span&gt;
        Response.ContentType = &lt;span style="color: #800000;"&gt;"text/plain"&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;

    &lt;span style="color: #008000;"&gt;' Add the UTF-8 Byte Order Mark.&lt;/span&gt;
    Response.Write Chr(&lt;span style="color: #0000ff;"&gt;CByte&lt;/span&gt;(&lt;span style="color: #800000;"&gt;"&amp;amp;hEF"&lt;/span&gt;))
    Response.Write Chr(&lt;span style="color: #0000ff;"&gt;CByte&lt;/span&gt;(&lt;span style="color: #800000;"&gt;"&amp;amp;hBB"&lt;/span&gt;))
    Response.Write Chr(&lt;span style="color: #0000ff;"&gt;CByte&lt;/span&gt;(&lt;span style="color: #800000;"&gt;"&amp;amp;hBF"&lt;/span&gt;))
    
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; strFormat = &lt;span style="color: #800000;"&gt;"XML"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        Response.Write &lt;span style="color: #800000;"&gt;"&amp;lt;?xml version=""1.0"" encoding=""UTF-8""?&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
        Response.Write &lt;span style="color: #800000;"&gt;"&amp;lt;urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9""&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;
    
    &lt;span style="color: #008000;"&gt;' Always output the root of the website.&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Call&lt;/span&gt; WriteUrl(strUrlRoot,Now,&lt;span style="color: #800000;"&gt;"weekly"&lt;/span&gt;,strFormat)

    &lt;span style="color: #008000;"&gt;' &lt;/span&gt;&lt;span style="color: #008000;"&gt;--------------------------------------------------&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' This following section contains the logic to parse&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' the directory tree and return URLs based on the&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' static *.html files that it locates. This is where&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' you would change the code for dynamic content.&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' &lt;/span&gt;&lt;span style="color: #008000;"&gt;-------------------------------------------------- &lt;/span&gt;
    strFolderArray = GetFolderTree(strPhysicalRoot)

    &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; lngFolderArray = 1 &lt;span style="color: #0000ff;"&gt;to&lt;/span&gt; UBound(strFolderArray)
        strUrlRelative = Replace(Mid(strFolderArray(lngFolderArray),Len(strPhysicalRoot)+1),&lt;span style="color: #800000;"&gt;"\"&lt;/span&gt;,&lt;span style="color: #800000;"&gt;"/"&lt;/span&gt;)
        &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; objFolder = objFSO.GetFolder(Server.MapPath(&lt;span style="color: #800000;"&gt;"."&lt;/span&gt; &amp;amp; strUrlRelative))
        &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Each&lt;/span&gt; objFile &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; objFolder.Files
            strExt = objFSO.GetExtensionName(objFile.Name)
            &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; StrComp(strExt,&lt;span style="color: #800000;"&gt;"html"&lt;/span&gt;,vbTextCompare)=0 &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; StrComp(Left(objFile.Name,6),&lt;span style="color: #800000;"&gt;"google"&lt;/span&gt;,vbTextCompare)&amp;lt;&amp;gt;0 &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
                    &lt;span style="color: #0000ff;"&gt;Call&lt;/span&gt; WriteUrl(strUrlRoot &amp;amp; strUrlRelative &amp;amp; &lt;span style="color: #800000;"&gt;"/"&lt;/span&gt; &amp;amp; objFile.Name, objFile.DateLastModified, &lt;span style="color: #800000;"&gt;"weekly"&lt;/span&gt;, strFormat)
                &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;

    &lt;span style="color: #008000;"&gt;' &lt;/span&gt;&lt;span style="color: #008000;"&gt;--------------------------------------------------&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' End of file system loop.&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' &lt;/span&gt;&lt;span style="color: #008000;"&gt;-------------------------------------------------- &lt;/span&gt;    
    &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; strFormat = &lt;span style="color: #800000;"&gt;"XML"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
        Response.Write &lt;span style="color: #800000;"&gt;"&amp;lt;/urlset&amp;gt;"&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    
    Response.End

    &lt;span style="color: #008000;"&gt;' ======================================================================&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;'&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Outputs a sitemap URL to the client in XML or TXT format.&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' &lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' tmpStrFreq = always|hourly|daily|weekly|monthly|yearly|never &lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' tmpStrFormat = TXT|XML&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;'&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' ======================================================================&lt;/span&gt;

    &lt;span style="color: #0000ff;"&gt;Sub&lt;/span&gt; WriteUrl(tmpStrUrl,tmpLastModified,tmpStrFreq,tmpStrFormat)
        &lt;span style="color: #0000ff;"&gt;On&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Error&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Resume&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; tmpDate : tmpDate = &lt;span style="color: #0000ff;"&gt;CDate&lt;/span&gt;(tmpLastModified)
        &lt;span style="color: #008000;"&gt;' Check if the request is for XML or TXT and return the appropriate syntax.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt; tmpStrFormat = &lt;span style="color: #800000;"&gt;"XML"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Then&lt;/span&gt;
            Response.Write &lt;span style="color: #800000;"&gt;" &amp;lt;url&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
            Response.Write &lt;span style="color: #800000;"&gt;" &amp;lt;loc&amp;gt;"&lt;/span&gt; &amp;amp; Server.HtmlEncode(tmpStrUrl) &amp;amp; &lt;span style="color: #800000;"&gt;"&amp;lt;/loc&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
            Response.Write &lt;span style="color: #800000;"&gt;" &amp;lt;lastmod&amp;gt;"&lt;/span&gt; &amp;amp; Year(tmpLastModified) &amp;amp; &lt;span style="color: #800000;"&gt;"-"&lt;/span&gt; &amp;amp; Right(&lt;span style="color: #800000;"&gt;"0"&lt;/span&gt; &amp;amp; Month(tmpLastModified),2) &amp;amp; &lt;span style="color: #800000;"&gt;"-"&lt;/span&gt; &amp;amp; Right(&lt;span style="color: #800000;"&gt;"0"&lt;/span&gt; &amp;amp; Day(tmpLastModified),2) &amp;amp; &lt;span style="color: #800000;"&gt;"&amp;lt;/lastmod&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
            Response.Write &lt;span style="color: #800000;"&gt;" &amp;lt;changefreq&amp;gt;"&lt;/span&gt; &amp;amp; tmpStrFreq &amp;amp; &lt;span style="color: #800000;"&gt;"&amp;lt;/changefreq&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
            Response.Write &lt;span style="color: #800000;"&gt;" &amp;lt;/url&amp;gt;"&lt;/span&gt; &amp;amp; vbCrLf
        &lt;span style="color: #0000ff;"&gt;Else&lt;/span&gt;
            Response.Write tmpStrUrl &amp;amp; vbCrLf
        &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;If&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Sub&lt;/span&gt;

    &lt;span style="color: #008000;"&gt;' ======================================================================&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;'&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' Returns a string array of folders under a root path&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;'&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;' ======================================================================&lt;/span&gt;

    &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt; GetFolderTree(strBaseFolder)
        &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; tmpFolderCount,tmpBaseCount
        &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; tmpFolders()
        &lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; tmpFSO,tmpFolder,tmpSubFolder
        &lt;span style="color: #008000;"&gt;' Define the initial values for the folder counters.&lt;/span&gt;
        tmpFolderCount = 1
        tmpBaseCount = 0
        &lt;span style="color: #008000;"&gt;' Dimension an array to hold the folder names.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;ReDim&lt;/span&gt; tmpFolders(1)
        &lt;span style="color: #008000;"&gt;' Store the root folder in the array.&lt;/span&gt;
        tmpFolders(tmpFolderCount) = strBaseFolder
        &lt;span style="color: #008000;"&gt;' Create file system object.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; tmpFSO = Server.CreateObject(&lt;span style="color: #800000;"&gt;"Scripting.Filesystemobject"&lt;/span&gt;)
        &lt;span style="color: #008000;"&gt;' Loop while we still have folders to process.&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;While&lt;/span&gt; tmpFolderCount &amp;lt;&amp;gt; tmpBaseCount
            &lt;span style="color: #008000;"&gt;' Set up a folder object to a base folder.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; tmpFolder = tmpFSO.GetFolder(tmpFolders(tmpBaseCount+1))
              &lt;span style="color: #008000;"&gt;' Loop through the collection of subfolders for the base folder.&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;For&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Each&lt;/span&gt; tmpSubFolder &lt;span style="color: #0000ff;"&gt;In&lt;/span&gt; tmpFolder.SubFolders
                &lt;span style="color: #008000;"&gt;' Increment the folder count.&lt;/span&gt;
                tmpFolderCount = tmpFolderCount + 1
                &lt;span style="color: #008000;"&gt;' Increase the array size&lt;/span&gt;
                &lt;span style="color: #0000ff;"&gt;ReDim&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Preserve&lt;/span&gt; tmpFolders(tmpFolderCount)
                &lt;span style="color: #008000;"&gt;' Store the folder name in the array.&lt;/span&gt;
                tmpFolders(tmpFolderCount) = tmpSubFolder.Path
            &lt;span style="color: #0000ff;"&gt;Next&lt;/span&gt;
            &lt;span style="color: #008000;"&gt;' Increment the base folder counter.&lt;/span&gt;
            tmpBaseCount = tmpBaseCount + 1
        &lt;span style="color: #0000ff;"&gt;Wend&lt;/span&gt;
        GetFolderTree = tmpFolders
    &lt;span style="color: #0000ff;"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Function&lt;/span&gt;
%&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: There are two helper methods in the preceding example that I should call out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;GetFolderTree()&lt;/strong&gt; function returns a string array of all the folders that are located under a root folder; you could remove that function if you were generating all of your URLs dynamically.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;WriteUrl()&lt;/strong&gt; function outputs an entry for the sitemap file in either XML or TXT format, depending on the file type that is in use. It also allows you to specify the frequency that the specific URL should be indexed (&lt;em&gt;always&lt;/em&gt;, &lt;em&gt;hourly&lt;/em&gt;, &lt;em&gt;daily&lt;/em&gt;, &lt;em&gt;weekly&lt;/em&gt;, &lt;em&gt;monthly&lt;/em&gt;, &lt;em&gt;yearly&lt;/em&gt;, or &lt;em&gt;never&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Step 3 - Creating the Web.config File&lt;/h4&gt;
&lt;p&gt;The last step is to add the URL Rewrite rules to the &lt;em&gt;Web.config&lt;/em&gt; file in the root of your website. The following example is a complete &lt;em&gt;Web.config&lt;/em&gt; file, but you could merge the rules into your existing &lt;em&gt;Web.config&lt;/em&gt; file if you have already created one for your website. These rules are pretty simple, they rewrite all inbound requests for &lt;em&gt;Robots.txt&lt;/em&gt; to &lt;em&gt;Robots.asp&lt;/em&gt;, and they rewrite all requests for &lt;em&gt;Sitemap.xml&lt;/em&gt; to &lt;em&gt;&lt;span style="white-space: nowrap;"&gt;Sitemap.asp?format=XML&lt;/span&gt;&lt;/em&gt; and requests for &lt;em&gt;Sitemap.txt&lt;/em&gt; to &lt;em&gt;&lt;span style="white-space: nowrap;"&gt;Sitemap.asp?format=TXT&lt;/span&gt;&lt;/em&gt;; this allows requests for both the XML-based and text-based sitemaps to work, even though the &lt;em&gt;Robots.txt&lt;/em&gt; file contains the path to the XML file. The last part of the URL Rewrite syntax returns HTTP 404 errors if anyone tries to send direct requests for either the &lt;em&gt;Robots.asp&lt;/em&gt; or &lt;em&gt;&lt;span style="white-space: nowrap;"&gt;Sitemap.asp&lt;/span&gt;&lt;/em&gt; files; this isn't absolutely necesary, but I like to mask what I'm doing from prying eyes. (I'm kind of geeky that way.)&lt;/p&gt;
&lt;pre style="margin-left: 20px; color: black; background-color: #ffffff;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #800000;"&gt;xml&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1.0"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;encoding&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="UTF-8"&lt;/span&gt;?&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.webServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewrite&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMaps&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;clear&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMap&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Static URL Rewrites"&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/robots.txt"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/robots.asp"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/sitemap.xml"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/sitemap.asp?format=XML"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/sitemap.txt"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/sitemap.asp?format=TXT"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMap&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMap&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Static URL Failures"&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/robots.asp"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/sitemap.asp"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMap&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewriteMaps&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rules&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;clear&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Static URL Rewrites"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;patternSyntax&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ECMAScript"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;stopProcessing&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;match&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;url&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=".*"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;ignoreCase&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;negate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="false"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;input&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{Static URL Rewrites:{REQUEST_URI}}"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;pattern&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="(.+)"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;action&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Rewrite"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;url&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{C:1}"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;appendQueryString&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="false"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;redirectType&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Temporary"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Static URL Failures"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;patternSyntax&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ECMAScript"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;stopProcessing&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;match&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;url&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=".*"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;ignoreCase&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;negate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="false"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;input&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{Static URL Failures:{REQUEST_URI}}"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;pattern&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="(.+)"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;action&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="CustomResponse"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;statusCode&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="404"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;subStatusCode&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="0"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Prevent rewriting for static files"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;patternSyntax&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Wildcard"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;stopProcessing&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;match&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;url&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="*"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
             &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;input&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="{REQUEST_FILENAME}"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;matchType&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="IsFile"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;conditions&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
          &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;action&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="None"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rule&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rules&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;rewrite&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;system.webServer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;That sums it up for this blog; I hope that you get some good ideas from it.&lt;/p&gt;
&lt;p&gt;For more information about the syntax in &lt;em&gt;Robots.txt&lt;/em&gt; and &lt;em&gt;Sitemap.xml&lt;/em&gt; files, see the following URLs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sitemaps.org/protocol.php"&gt;http://www.sitemaps.org/protocol.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.robotstxt.org/"&gt;http://www.robotstxt.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10381558" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/RobertMcMurraysMsdnBlog/~4/9nuImvzTIU8" height="1" width="1"/&gt;</description><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/IIS/">IIS</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/URL+Rewrite/">URL Rewrite</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/SEO/">SEO</category><category domain="http://blogs.msdn.com/b/robert_mcmurray/archive/tags/Classic+ASP/">Classic ASP</category><feedburner:origLink>http://blogs.msdn.com/b/robert_mcmurray/archive/2012/12/31/using-classic-asp-and-url-rewrite-for-dynamic-seo-functionality.aspx</feedburner:origLink></item></channel></rss>
