<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6354979324932603051</id><updated>2011-08-09T23:18:37.673+10:00</updated><title type='text'>Gluegood Software</title><subtitle type='html'>Gluegood Software provides freeware, source code and advice on integrating into various Microsoft technologies.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-6218428813427145808</id><published>2010-07-09T22:56:00.002+10:00</published><updated>2010-07-09T23:25:10.321+10:00</updated><title type='text'>VSTO, ClickOnce, MSBuild equals happiness</title><content type='html'>After spending several frustrating days working on VSTO and ClickOnce deployment I thought I'd share the experiences in the below guidance and instructions for newbie’s to follow (like I was a few days ago). There are some great articles out there, but a lot of misinformation because of differences between VS2008 and VS2005.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The objective :-&lt;/strong&gt;From an intranet hosting a VSTO package enable a use to click on a URL of the document (http://mysebserver/VSTO/vstogluegood.docx) that is opened on their PC and the required VSTO file is installed and ran. The VSTO ClickOnce package I wanted to be created using MSBuild project file.&lt;br /&gt;&lt;br /&gt;Target development environment and Office version&lt;br /&gt;- VSTO developed using Visual Studio 2008&lt;br /&gt;- Office 2007 (specifically targeting Word 2007)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Client side components required&lt;/strong&gt;&lt;br /&gt;The below are a list of client side components required to run VSTO packages using ClickOnce.&lt;br /&gt;- .NET Framework 3.5&lt;br /&gt;- Microsoft Office 2007 System Update Redistributable PIA (o2007pia.msi)&lt;br /&gt;- Microsoft Visual Studio Tools for the Microsoft Office system (vstor30.exe)&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Client side component installs note&lt;/em&gt;&lt;br /&gt;- I opted for a pre-deployment of the packages through ActiveDirectory group policy. The o2007pia.msi is easy to place in the OU, however the vstor30.exe isn't because it is an .exe. The solution we found was to extract the vstor30.exe using the below command :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;vstor30.exe /x:Extract&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Using the extracted contents in &lt;span style="font-family:courier new;"&gt;&amp;lt;current directory&amp;gt;\Extract\&lt;/span&gt;, we simply placed the &lt;span style="font-family:courier new;"&gt;trin_trir.msi&lt;/span&gt; in the OU. I suspect this is less than ideal, but worked for us.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Certificates&lt;/strong&gt;&lt;br /&gt;You need a certificate to deploy and run VSTO packages. There are 3 choices :-&lt;br /&gt;a) Purchase a certificate (mandatory if you are deploying beyond your internal network)&lt;br /&gt;b) Use the Temporary Visual Studio certificate created (downside - expires in 1 year)&lt;br /&gt;c) Create a Certificate using makecert.&lt;br /&gt;&lt;br /&gt;I'm using the 3rd choice as it provides you with a more robust certificate which can be deployed using ActiveDirectory. Below are the steps :-&lt;br /&gt;&lt;br /&gt;1. Open the Visual Studio Command Prompt&lt;br /&gt;2. Type &lt;span style="font-family:courier new;"&gt;makecert -r -pe -n "CN=&amp;lt;yourCertificateName&amp;gt;" -b 01/01/2000 -e 01/01/2099 -ss My&lt;br /&gt;&lt;/span&gt;3. We have made a .cer certificate, but for Visual Studio we need a .pfx certificate. Within Internet Explorer under Options-&amp;gt;Content-&amp;gt;Certificates find your certificate and export it as a .pfx, (Choose export private key). Now keep this certificate for the VSTO packages.&lt;br /&gt;4. To create a .cer which isn't exportable (and can be pushed out onto client PCs), simple delete the existing certificate created in step 3 and double click on the .pfx file created in step 4. Install the certificate (mark as not exportable) and then export it as a .cer.&lt;br /&gt;&lt;br /&gt;You will need to install the non-exportable .cer on the users' PCs, while using the .pfx file in Visual Studio when you create your packages.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Certificate installation&lt;/strong&gt;&lt;br /&gt;The certificate created above needs to be installed in&lt;br /&gt;a) Trusted Root Certificate Authorities&lt;br /&gt;b) Trusted Publishers&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Manual&lt;/em&gt;&lt;br /&gt;- On each PC double click on the .cer file created above as administrator and install into the 2 locations.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;OU&lt;br /&gt;&lt;/em&gt;- In the Group Policy Object Editor add the certificates to Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Public Key Policies. For a full walkthrough see this (don't forget to place in both certificate locations).:-&lt;a href="https://support.smoothwall.net/index.php?_m=knowledgebase&amp;amp;_a=viewarticle&amp;amp;kbarticleid=180"&gt;https://support.smoothwall.net/index.php?_m=knowledgebase&amp;amp;_a=viewarticle&amp;amp;kbarticleid=180&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Word configuration&lt;br /&gt;&lt;/strong&gt;To automatically allow the Word document to run the ClickOnce deployment it must have the location of the website in its Trusted locations.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Manual&lt;/em&gt;&lt;br /&gt;- Within Word goto Office menu-&amp;gt;Word Options-&amp;gt;Trust Center-&amp;gt;Trust Center Settings-&amp;gt;Trusted Locations.&lt;br /&gt;a. Allow Trusted Locations on my network – checked&lt;br /&gt;b. The following list of locations :- e.g.&lt;br /&gt;           &lt;a href="http://website-prod/VSTO/"&gt;http://website-Prod/VSTO/&lt;/a&gt;&lt;br /&gt;           &lt;a href="http://website-uat/VSTO/"&gt;http://website-UAT/VSTO/&lt;/a&gt;&lt;br /&gt;           &lt;a href="http://website-test/VSTO/"&gt;http://website-TEST/VSTO/&lt;/a&gt;&lt;br /&gt;           &lt;a href="http://website-dev/VSTO/"&gt;http://website-DEV/VSTO/&lt;/a&gt;&lt;br /&gt;* Ensure Subfolders of this location are also trusted is checked when added.&lt;br /&gt;&lt;br /&gt;Note: Word has a quirk where the VSTOs must be installed in the subfolder of the site (for Trusted Locations), so you can't use http://MyWebSite/Gluegood.docx, while you can use http://MyWebSite/VSTO/Gluegood.docx&lt;br /&gt;&lt;br /&gt;&lt;em&gt;OU&lt;br /&gt;&lt;/em&gt;- Follow instructions here on how to set the above in an OU (&lt;a href="http://technet.microsoft.com/en-us/library/cc178948(office.12).aspx"&gt;http://technet.microsoft.com/en-us/library/cc178948(office.12).aspx&lt;/a&gt; )&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Web site configuration&lt;/strong&gt;&lt;br /&gt;So that the VSTO runs correctly you need to add the MIME type of extension .vsto and application/x-ms-vsto. See this article for instructions (&lt;a href="http://msdn.microsoft.com/en-us/library/bb608629.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb608629.aspx&lt;/a&gt; )&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;MSBuild project file&lt;/strong&gt; (aka the Magic happens here)&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;VS2008 comes with a nice 'Publish' UI, however it lacks features in the following ways :-&lt;br /&gt;1. You are unable to differentiate builds between the environments.&lt;br /&gt;2. It can't be part of a scheduled build&lt;br /&gt;&lt;br /&gt;There seem lots of other ways of doing the below, but I like the simplicity of building and creating the VSTO in once step using MSBuild without needing to fiddle with other tools.&lt;br /&gt;&lt;br /&gt;Below I have provided VB.NET code to generate the MSBuild file and kick off an install. The below however can easily be converted to .msbuild file and .cmd file with hard coded values.&lt;br /&gt;&lt;br /&gt;There are 2 parts to the MSBuild file :-&lt;br /&gt;a) The properties created in the Property Group&lt;br /&gt;b) The Actual MSBuild settings&lt;br /&gt;&lt;br /&gt;Below are parameters which are passed to the code :-&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SolutionFile&lt;/span&gt; - This is the location of the .sln file to be compiled. e.g. C:\Projects\VSTOGluegood.sln&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Version&lt;/span&gt; - This is the version of the VSTO project. e.g. 3.1.2.29&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Environment&lt;/span&gt; - We use this to determine the SolutionId (see below)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Destination &lt;/span&gt;- This is the network address in which you want to create the VSTO. e.g. &lt;a href="file://mywebserver/e$/Site/VSTO/"&gt;\\MyWebServer\e$\Site\VSTO\&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DestinationURL&lt;/span&gt; - This is the public address in which the VSTO will be installed, when new versions are checked by the clients this is the location they will use. e.g. http://MySite/VSTO&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SolutionId&lt;/span&gt; - To make the VSTOs unique for each environment they must have different AssemblyName and different SolutionId – (&lt;a href="http://briannoyes.net/2006/11/03/ClickOnceDeploymentApplicationIdentity.aspx"&gt;http://briannoyes.net/2006/11/03/ClickOnceDeploymentApplicationIdentity.aspx&lt;/a&gt;) . The function CompileVSTOReports_GetSolutionId in the below code looks for the .vbproj and extracts the SolutionId, however it replaces the last character so each environment is unique, e.g. Our ProjId is &lt;span style="font-family:courier new;"&gt;dd0d7e0e-7913-4e9a-8541-d3ef27387d16&lt;/span&gt;, for VSTO deployments the &lt;span style="font-family:courier new;"&gt;6&lt;/span&gt; becomes an '&lt;span style="font-family:courier new;"&gt;a&lt;/span&gt;' in DEV, '&lt;span style="font-family:courier new;"&gt;b&lt;/span&gt;' in TEST, '&lt;span style="font-family:courier new;"&gt;c&lt;/span&gt;' in UAT and '&lt;span style="font-family:courier new;"&gt;d&lt;/span&gt;' in PROD.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ManifestCertificateThumbprint&lt;/span&gt; - This value you extract from the .vbproj file and is the password you created for the .pfx file encrypted by Visual Studio. To get this value in Visual Studio sign the project with the .pfx file and then open up the .vbproj file and find the value and paste it below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;Private Sub CompileVSTOReports_CompileSolutionFile(ByVal SolutionFile As System.IO.FileInfo, _&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ByVal Version As String, _&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ByVal Environment As String, _&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ByVal Destination As String, _&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ByVal DestinationURL As String)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim oStreamWriter As System.IO.StreamWriter = Nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim sBuildFile As String = My.Computer.FileSystem.GetTempFileName&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim sMSBuild As System.Text.StringBuilder = New System.Text.StringBuilder&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;Project DefaultTargets=&amp;quot;&amp;quot;Main&amp;quot;&amp;quot; xmlns=&amp;quot;&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&amp;quot;&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;PropertyGroup&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;SourceSolution&amp;gt;&amp;quot; &amp; SolutionFile.FullName &amp; &amp;quot;&amp;lt;/SourceSolution&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' If you change the PFX file you must change the Thumbprint below.&amp;nbsp;This comes from the .vbproj file if you manually&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' use the PFX file - when seen in a text editor.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;KeyFileLocation&amp;gt;&amp;quot; &amp; My.Application.Info.DirectoryPath &amp; &amp;quot;\gluegood.pfx&amp;lt;/KeyFileLocation&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;VersionNumber&amp;gt;&amp;quot; &amp; Version &amp; &amp;quot;&amp;lt;/VersionNumber&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;AssemblyName&amp;gt;&amp;quot; &amp; &amp;quot;VSTO_&amp;quot; &amp; Replace(SolutionFile.Name, &amp;quot;.sln&amp;quot;, &amp;quot;&amp;quot;) &amp; &amp;quot;_&amp;quot; &amp; Environment &amp; &amp;quot;&amp;lt;/AssemblyName&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;PublishDir&amp;gt;&amp;quot; &amp; Destination &amp; &amp;quot;&amp;lt;/PublishDir&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;InstallUrl&amp;gt;&amp;quot; &amp; DestinationURL &amp; &amp;quot;&amp;lt;/InstallUrl&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;SolutionID&amp;gt;&amp;quot; &amp; CompileVSTOReports_GetSolutionId(Environment, SolutionFile) &amp; &amp;quot;&amp;lt;/SolutionID&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;/PropertyGroup&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;Target Name=&amp;quot;&amp;quot;Main&amp;quot;&amp;quot;&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp; &amp;lt;MSBuild Projects=&amp;quot;&amp;quot;$(SourceSolution)&amp;quot;&amp;quot;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; Properties = &amp;quot;&amp;quot;Configuration=Release;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InstallUrl=$(InstallUrl);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublishDir=$(PublishDir);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublishUrl=$(InstallUrl);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SignAssembly=true;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DelaySign=false;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AssemblyOriginatorKeyFile=$(KeyFileLocation);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManifestKeyFile=($KeyFileLocation);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' If you change the PFX file you must change the Thumbprint below.&amp;nbsp;This comes from the .vbproj file if you manually&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' use the PFX file - when seen in a text editor.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManifestCertificateThumbprint=84489FD07E578BBA71CC67E9EB4F49E1B4EE740A;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SignManifests=true;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ApplicationVersion=$(VersionNumber);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BootstrapperEnabled=true;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UpdateEnabled=true;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UpdateInterval=0;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AssemblyName=$(AssemblyName);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SolutionID=$(SolutionId);&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsWebBootstrapper=True&amp;quot;&amp;quot;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; ContinueOnError = &amp;quot;&amp;quot;false&amp;quot;&amp;quot;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; Targets=&amp;quot;&amp;quot;Publish&amp;quot;&amp;quot; /&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;/Target&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sMSBuild.Append(&amp;quot;&amp;lt;/Project&amp;gt;&amp;quot; &amp; vbCrLf)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oStreamWriter = New System.IO.StreamWriter(sBuildFile, False)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oStreamWriter.Write(sMSBuild.ToString)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oStreamWriter.Close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oStreamWriter = Nothing&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Running the compile in code :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim sBuildLogFileName As String = &amp;quot;MSBuild_VSTO_&amp;quot; &amp; Now.ToString(&amp;quot;yyyyMMdd_hhmmss&amp;quot;) &amp; &amp;quot;.log&amp;quot;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' Run the build&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim oProcessInfo As System.Diagnostics.ProcessStartInfo = New ProcessStartInfo(&amp;quot;C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe&amp;quot;, &amp;quot;&amp;quot;&amp;quot;&amp;quot; &amp; sBuildFile &amp; &amp;quot;&amp;quot;&amp;quot; /clp:errorsonly /l:FileLogger,Microsoft.Build.Engine;logfile=&amp;quot; &amp; sBuildLogFileName &amp; &amp;quot; /filelogger&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oProcessInfo.WindowStyle = ProcessWindowStyle.Hidden&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim oProcess = Process.Start(oProcessInfo)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oProcess.WaitForExit()&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If oProcess.ExitCode &amp;lt;&amp;gt; 0 Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Error&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Throw New Exception(&amp;quot;Build failed for solution &amp;quot; &amp; SolutionFile.FullName &amp; &amp;quot;.&amp;nbsp;See log file &amp;quot; &amp; sBuildLogFileName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End If&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notes:&lt;br /&gt;&lt;strong&gt;Debugging&lt;/strong&gt; - VSTO and ClickOnce is 'fun' to debug. Below are some suggestions :-&lt;br /&gt;1. Run the .vsto deployment file to install the package first. Do this directly by copying the file and then clicking on the link. If you get a security warning you know that Office is going to silently discard the VSTO, so troubleshoot this first.&lt;br /&gt;2. In add/remove programs you can see the VSTO, so check it exists. Remove it manually between tests.&lt;br /&gt;3. Initially run the .docx or .dotx locally from the C:\ of the test PC. This gets around any security issues.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Passing query string / parameters via URL&lt;/strong&gt; - We required to deliver some parameters to the VSTO. A really simple way of doing this is by passing Me.Fullname to the below function e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;Private Sub ThisDocument_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt; GetParameterIntFromQueryString(&amp;quot;UserId&amp;quot;, Me.Fullname)&lt;br /&gt;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Public Shared Function GetParameterIntFromQueryString(Byval ParameterName as String, ByVal Location As String) As Integer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;' Retrieve the ParameterName from the QueryString used to launch the document.&amp;nbsp;Pass to this function me.Fullname&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim oURI As UriBuilder = New UriBuilder(Location)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim sQueryString = oURI.Query.ToString&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If sQueryString = vbNullString Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Return 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim NameValueTable As New Collections.Specialized.NameValueCollection()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NameValueTable = System.Web.HttpUtility.ParseQueryString(sQueryString)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If IsNumeric(NameValueTable(ParameterName)) Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Return CInt(NameValueTable(ParameterName))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Return 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End If&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End If&lt;br /&gt;&amp;nbsp;&amp;nbsp;End Function&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;e.g. Opening the VSTO from a website with &lt;a href="http://myvstoserver/VSTO/UserReport.docx?UserId=123"&gt;http://myvstoserver/VSTO/UserReport.docx?UserId=123&lt;/a&gt; would return 123 from the above function.&lt;br /&gt;&lt;br /&gt;I would strongly suggest to prompt for the parameters if not supplied (use Inputbox) so it can be run in debug mode, or your users can run off website.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;VSTO run once from .docx&lt;/strong&gt; - We required our VSTO to run once and then not again. Unfortunately the original developer created the VSTO as a Word Document (.docx) which meant once the code the Word Document that was saved continue to embed in it the VSTO relationship, so when the user opened it again it would re-run wiping any manual changes they made.. The work around is either to change the project to a Document Template (.dotx), or in the &lt;span style="font-family:courier new;"&gt;ThisDocument_Startup&lt;/span&gt; at the end of the Finally block place the command &lt;span style="font-family:courier new;"&gt;Me.RemoveCustomization()&lt;/span&gt; - which strips the relationship between the document and VSTO.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-6218428813427145808?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/6218428813427145808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=6218428813427145808&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6218428813427145808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6218428813427145808'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2010/07/namecode-classc-sharp.html' title='VSTO, ClickOnce, MSBuild equals happiness'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-4970876078213332050</id><published>2009-08-01T06:07:00.003+10:00</published><updated>2009-08-01T07:02:16.626+10:00</updated><title type='text'>Freeware - LogParser.TFSQuery (Team Foundation Server)</title><content type='html'>I recently found myself needing to query Team Foundatin Server (TFS) like &lt;a href="http://gluegood.blogspot.com/2008/03/freeware-logparservssjournal.html"&gt;I had previously done&lt;/a&gt; with Visual Source Safe (VSS). I found I needed to following capabilities :-&lt;br /&gt;- Querying and notification of recent work items&lt;br /&gt;- Querying and notification of the most recent check-ins&lt;br /&gt;- Querying and notification of check-outs which were over a time threshold&lt;br /&gt;- Querying and notification of shelvesets (parked code) which expired a certain amount of time&lt;br /&gt;- Querying and notification across linked work items&lt;br /&gt;&lt;p&gt;I could have used out of the box TFS functionality to provide some of the above, but some don't exist without reaching into the database. Therefore given I have &lt;a href="http://gluegood.blogspot.com/2009/05/freeware-logparseremail.html"&gt;LogParser.Email&lt;/a&gt; capabilities (ability to e-mail LogParser results) I decided to write a LogParser COM input format plugin for TFS to perform all the above.&lt;br /&gt;&lt;br /&gt;Initially I thought I could provide the tool using the direct TFS web services, however after reading online documentation I decided against this approach, mostly because Microsoft haven't got any documentation, nor will guarentee they won't break it between releases. I additionally considered simply parsing the output from TF.EXE, however thought this was inelegant as a solution and prone to error and additionally wouldn’t provide Work Item querying I was looking for.&lt;br /&gt;&lt;br /&gt;I therefore decided to look at TFS APIs available in VB.Net. The available functionality is extensive and blogs like &lt;a href="http://blogs.msdn.com/jmanning/"&gt;James Manning&lt;/a&gt; make it much easier to navigate various examples of using the APIs.&lt;br /&gt;&lt;br /&gt;Below are details on the solution.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Freeware with VB.NET 2005 source code included &lt;/li&gt;&lt;li&gt;Can query Team Foundation Server (TFS) work items, check-ins (ChangeSets), check-outs (Pending ChangeSets), and Shelvesets. This has been tested on TFS 2005 - it may work on earlier or later versions. &lt;/li&gt;&lt;li&gt;For work items supports either querying using existing Stored Queries, or using direct work item query language (WIQL). The queries can be run across a specific project, or multiple projects.&lt;/li&gt;&lt;li&gt;For check-ins, check-outs and shelveset queries it reports the file details and associated work items. In addition supports a single or multiple project paths in the same query and the recursion level. &lt;/li&gt;&lt;li&gt;Work items and check-ins (changesets) support iCheckPoint functionality to enable you to retrieve only the latest changes since the last query. Works on recording the time (UTC) and then querying for item greater than that time. &lt;/li&gt;&lt;li&gt;The Work items query can retrieve specified fields (either in Stored Query, or WIQL) or return all fields available for that work item. &lt;/li&gt;&lt;li&gt;Can query multiple different TFS projects, or even different TFS servers and combine the results. Internally used Dataset.Merge functionality.&lt;/li&gt;&lt;li&gt;Work item query allows for LEFT JOIN-ing linked Work Items. You can specific the fields you want returned in the LEFT JOIN.&lt;/li&gt;&lt;li&gt;To provide extra querying features Implements a number of custom columns (as per standard LogParser).&lt;/li&gt;&lt;li&gt;Logs any errors to console and to EventLog.Application &lt;/li&gt;&lt;li&gt;Supports Log Parser data types. &lt;/li&gt;&lt;li&gt;Uses the ILogParserInputContext interface to enable LogParser COM interface to directly call. i.e, you can code against this plugin.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;a href="http://www.box.net/shared/yugq15jmd6"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt; VB.NET source is included in download.&lt;br /&gt;*************************************************&lt;br /&gt;To install:&lt;/p&gt;&lt;p&gt;Assume that TeamFoundation*.dll (Team Explorer or Visual Studio) is installed in the GAC and working on your system. Stand-alone Team Explorer install &lt;a href="http://blogs.msdn.com/jeffbe/archive/2007/11/24/standalone-team-explorer-2008-download-available.aspx"&gt;instructions&lt;/a&gt;. Both &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163498.aspx"&gt;Team Explorer &lt;/a&gt;and Visual Studio install the dlls into the GAC.&lt;/p&gt;&lt;p&gt;1. Copy the LogParser.TFSQuery folder to a location on your harddrive&lt;/p&gt;&lt;p&gt;2. Run the command .\LogParser.TFSQuery\InstalldotNETasCOM.bat. &lt;/p&gt;&lt;p&gt;3. Run your Log Parser query. &lt;/p&gt;&lt;p&gt;e.g. &lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From 'http://tfsserver:8080/TestProject/My Work Items'" -iProgId:Gluegood.LogParser.TFSQuery -o:DataGrid&lt;/span&gt;&lt;/p&gt;&lt;p&gt;A number of samples are available in the downloaded file in SampleQuery.bat&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From '{Path1}','{Path2}',..." -iProgId:Gluegood.LogParser.TFSQuery -iComParams:"iAllFields={TrueFalse},iCheckPoint={Path},iWIQL={WIQL query},iQueryCheckOuts={TrueFalse},iQueryShelvesets={TrueFalse}, iRecursive={TrueFalse},iWorkItemLinksQuery={TrueWIQL queryField list}"&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;{Pathx}&lt;/em&gt; - a formatted path that adheres to the following standard.&lt;br /&gt;    - &lt;em&gt;Work items&lt;/em&gt; – {server:port}/{project}/{query} e.g. ‘&lt;a href="http://tfsserver:8080/ProjectTest/All"&gt;http://tfsserver:8080/ProjectTest/All&lt;/a&gt; Work Items’ or ‘tfsserver/*/All Work Items’. Expect the 3 slashes as delimiters even when item isn’t required..&lt;br /&gt;    - &lt;em&gt;Check-ins, Check-outs, shelvesets&lt;/em&gt; - {server:port}/{path} e.g. ‘&lt;a href="http://tfsserver:8080/$/ProjectTest/Release"&gt;http://tfsserver:8080/$/ProjectTest/Release&lt;/a&gt;’ or ‘&lt;a href="http://tfsserver:8080/$/ProjectTest/Release"&gt;tfsserver/$/&lt;/a&gt;’&lt;br /&gt;Supports multiple Paths as long as they are deliminated with a comma (,). &lt;/li&gt;&lt;li&gt;&lt;em&gt;iAllFields&lt;/em&gt; - Ignore the columns defined in the query (or WIQL) and retrieve all columns. Default = False &lt;/li&gt;&lt;li&gt;&lt;em&gt;iCheckPoint&lt;/em&gt; – Path to a checkpoint file. Default is no checkpoint.&lt;/li&gt;&lt;li&gt;&lt;em&gt;iWIQL&lt;/em&gt; – WIQL query. Overrides any stored queries specified. Defaults to no iWIQL Hint: If using from command line any commas must be escaped with \u002c. &lt;/li&gt;&lt;li&gt;&lt;em&gt;iQueryCheckOuts&lt;/em&gt; - Query the path specified looking for CheckOuts. If iQueryCheckOuts and iQueryShelvesets are not provided, or both false, then assume querying for Check-ins. Default is false.&lt;/li&gt;&lt;li&gt;&lt;em&gt;iQueryShelvesets&lt;/em&gt; - Query the path specified looking for Shelvesets. If iQueryCheckOuts and iQueryShelvesets are not provided, or both false, then assume querying for Check-ins. Default is false.&lt;/li&gt;&lt;li&gt;&lt;em&gt;iRecursive&lt;/em&gt; – defines wether to recusively scan subfolders, or stay within the current folder/project defined. Default is true.&lt;/li&gt;&lt;li&gt;&lt;em&gt;iWorkItemLinksQuery&lt;/em&gt; – Defines whether to LEFT JOIN all linked Work Items. Extra columns returned will be prefixed with ‘LogParserTFSRelated’. Setting to True will return Linked Work Item Id, Type, State, and Title. Can additionally define your own WIQL (with only SELECT and FROM clause) or a field list. Default is "" (not enabled).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Columns returned (Work items)&lt;br /&gt;&lt;em&gt;LogParserTFSServer&lt;/em&gt; – Server in which the query is being executed.&lt;br /&gt;&lt;em&gt;LogParserTFSProject&lt;/em&gt; – TFS Project which this query has been executed&lt;br /&gt;&lt;em&gt;LogParserTFSQuery&lt;/em&gt; – TFS Stored Query, or WIQL query&lt;br /&gt;&lt;em&gt;LogParserTFSWorkItemId&lt;/em&gt; – Work Item Id for this item&lt;br /&gt;&lt;em&gt;LogParserRecordNumber&lt;/em&gt; – Record number for this item in the query.&lt;br /&gt;&lt;em&gt;LogParserTFSRelated&lt;column&gt;&lt;/em&gt; – If using iWorkItemLinksQuery Columns in the query or all Columns&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Columns returned (Check-ins / changesets)&lt;br /&gt;&lt;em&gt;LogParserTFSServer&lt;/em&gt; – Server in which the query is being executed.&lt;br /&gt;&lt;em&gt;LogParserRecordNumber&lt;/em&gt; – Record number for this item in the query.&lt;br /&gt;&lt;em&gt;ChangeType&lt;/em&gt; – Type of change&lt;br /&gt;&lt;em&gt;User&lt;/em&gt; – User who checked in this item.&lt;br /&gt;&lt;em&gt;Date&lt;/em&gt; – Date that this check-in occurred.&lt;br /&gt;&lt;em&gt;Comment&lt;/em&gt; – Comment associated to this check-in&lt;br /&gt;&lt;em&gt;Path&lt;/em&gt; – File path (server side) of this check-in&lt;br /&gt;&lt;em&gt;WorkItemId&lt;/em&gt; – Associated Work Item Ids. Will display multiple seperated by a comma.&lt;br /&gt;&lt;em&gt;ChangeSetId &lt;/em&gt;– ChangeSet Id.&lt;br /&gt;&lt;em&gt;PolicyOverrideComment&lt;/em&gt; – Policy override comment if entered.&lt;br /&gt;&lt;em&gt;PolicyFailures&lt;/em&gt; – Number of policy failures&lt;/p&gt;&lt;p&gt;Columns returned (Check-outs / pendingsets)&lt;br /&gt;&lt;em&gt;LogParserTFSServer&lt;/em&gt; – Server in which the query is being executed.&lt;br /&gt;&lt;em&gt;LogParserRecordNumber&lt;/em&gt; – Record number for this item in the query.&lt;br /&gt;&lt;em&gt;ChangeType&lt;/em&gt; – Type of change&lt;br /&gt;&lt;em&gt;User&lt;/em&gt; – User who checked out this item.&lt;br /&gt;&lt;em&gt;Date&lt;/em&gt; – Date that this check-out occurred.&lt;br /&gt;&lt;em&gt;Path&lt;/em&gt; – File path (server side) of this check-out&lt;br /&gt;&lt;em&gt;PendingSetId&lt;/em&gt; – PendingSet Id.&lt;br /&gt;&lt;em&gt;Computer&lt;/em&gt; – Computer in which this check-out was conducted against.&lt;/p&gt;&lt;p&gt;Columns returned (Shelvesets)&lt;br /&gt;&lt;em&gt;LogParserTFSServer&lt;/em&gt; – Server in which the query is being executed.&lt;br /&gt;&lt;em&gt;LogParserRecordNumber&lt;/em&gt; – Record number for this item in the query.&lt;br /&gt;&lt;em&gt;ChangeType&lt;/em&gt; – Type of change&lt;br /&gt;&lt;em&gt;User&lt;/em&gt; – User who shelved this item.&lt;br /&gt;&lt;em&gt;Date&lt;/em&gt; – Date that this shelve occurred.&lt;br /&gt;&lt;em&gt;Path&lt;/em&gt; – File path (server side) of this shelve&lt;br /&gt;&lt;em&gt;PendingSetId&lt;/em&gt; – PendingSet Id.&lt;br /&gt;Computer – Computer in which this Shelve occurred from.&lt;br /&gt;&lt;em&gt;Name&lt;/em&gt; – Name of this shelveset&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Challenges&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;CheckPoint, WIQL and store.Query&lt;/strong&gt;&lt;br /&gt;When using iCheckPoint with Work Items I had to modifying the supplied stored query or WIQL provided with an additional clause returning the latest items based on System.ChangeDate. I ran into a problem using {string}.replace to look for the existence of existing WHERE clause as it’s case sensitive and I didn’t think I could rely on the case, therefore I ended up using Regex.Replace thanks to &lt;a href="http://weblogs.asp.net/jgalloway/archive/2004/02/11/71188.aspx"&gt;this&lt;/a&gt;. In addition because the CheckPoint stores date and time I had to modify the way I executed the query from the standard store.Query approach listed in many examples to a more &lt;a href="http://teamfoundation.blogspot.com/2008/01/specifying-date-and-time-in-wiql.html"&gt;obscure method&lt;/a&gt; using the Query object and setting the dayPrecision flag.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Performance and WorkItems&lt;/strong&gt;&lt;br /&gt;There is a lot of documentation stating that performance is degraded if you query every work item field beyond those returned in the WIQL query (as TFS needs to round trip to the server) , therefore I ensure that when returning fields (without the iAllFields setting) I only reference those fields specified. In addition I bumped up the PageSize to 200.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Changeset, Pendingset and Shelveset and querying&lt;/strong&gt;&lt;br /&gt;There seems to be some complexity around this (using APIs QueryPendingSets, QueryShelvedChanges, and QueryHistory) and I conducted some research and found this &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/a1e3b5ac-1963-4b83-82b1-d4d79bee7566)"&gt;entry&lt;/a&gt; helpful in providing directions. In addition I leaned heavily on James Manning’s site and numerous examples provided e.g. &lt;a href="http://blogs.msdn.com/jmanning/archive/2005/11/06/attempt-to-find-your-already-committed-shelvesets.aspx"&gt;Shelvesets&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Querying Linked WorkItems and Performance&lt;/strong&gt;&lt;br /&gt;The easy way would have been to return the Linked Work Item details on each Work Item that had a link. However this performs terribly (as multiple trips are made for every Work Item link). Another better way I found was to &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Add the RelatedLinkCount field to the initial WIQL query (to determine if there were any links), &lt;/li&gt;&lt;li&gt;Then loop through the WorkItem.Links collection (performance hit on this one and doesn't seem to be a way around this) determining if any are WorkItems and then storing any found WorkItem link ids into a BatchReadParameter. &lt;/li&gt;&lt;li&gt;Then after cycling all Work Items I then execute a new WIQL store.query using the BatchReadParameterCollection (a list of Work Item Ids). &lt;/li&gt;&lt;li&gt;Then I link the original Work Item dataset to the Linked Work Item dataset by moving through all the DataTable.rows. There is a few tricks around this code to support when a Work Item cannot be referenced due to permissions.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;GACUTIL and REGASM&lt;br /&gt;&lt;/strong&gt;My current approach with LogParser COM Input addins was to always install them in the GAC as I mistakenly thought that LogParser when reading the COM components both needed the item registered and installed in the GAC. I realised with this project that I really didn’t want to have to get the entire TeamFoundation assemblies in the GAC and played around with the install and I made 2 discoveries. &lt;/p&gt;&lt;p&gt;a) the TeamFoundation assemblies appear to already be installed in the GAC (if you have Visual Studio Installed, or &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163498.aspx"&gt;Team Explorer&lt;/a&gt;) and &lt;/p&gt;&lt;p&gt;b) that using REGASM with the &lt;span style="font-family:courier new;"&gt;/codebase&lt;/span&gt; (as per MSDN - The Codebase entry specifies the file path for an assembly that is not installed in the global assembly cache) means you don't need to install into the GAC.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;*************************************************&lt;/p&gt;&lt;p&gt;** Legal **&lt;/p&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-4970876078213332050?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/4970876078213332050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=4970876078213332050&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4970876078213332050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4970876078213332050'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2009/08/freeware-logparsertfsquery-team.html' title='Freeware - LogParser.TFSQuery (Team Foundation Server)'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-5879448990882829565</id><published>2009-05-30T22:35:00.007+10:00</published><updated>2009-05-31T22:11:52.996+10:00</updated><title type='text'>Freeware - LogParser.Email</title><content type='html'>Monitoring logs is always very challenging. You can use very expensive software which has its own interfaces and nuances, or you can write your own (can be just as painful).&lt;br /&gt;&lt;br /&gt;A few years ago I had the responsibily of monitoring a buggy 3rd party web application. I would often be awoken in the middle of the night to simply bounce the IIS service by overseas users. To enjoy a more peaceful nights sleep I created a tool that monitored IIS logs and when a particular string appeared I would know that the 3rd party software had crashed and thus issue a command to restart IIS. The tool worked and I got some rest.&lt;br /&gt;&lt;br /&gt;I wish at the time I had known of LogParser and had written the tool I've created in this post which would have solved the problem very quickly and very cleanly.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;LogParser.Email&lt;/strong&gt; can take the output from any LogParser query and deliver a 'nicely' formatted SMTP e-mail. In addition the tool has a 'trigger' concept that can determine if the email should be sent. It also as an extension can run batch commands (e.g. restart IIS). Used in combination with a scheduling software you have an extremely powerful monitoring solution.&lt;br /&gt;&lt;br /&gt;LogParser.exe -i:EVT "Select Top 10 * into STDOUT from System" -tpl:EmailTemplate.tpl -stats:off &amp;#124; &lt;strong&gt;LogParser.Email.exe&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Suggested usage&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A cheaper alternative to some of the monitoring features in Microsoft Operations Manager (MOM), or Heroix RoboMon, HP Openview etc&lt;/li&gt;&lt;li&gt;Used to 'test' if a specific rule being introduced into an enterprise monitoring product is valid&lt;/li&gt;&lt;li&gt;SharePoint Alert replacement (in conjunction with &lt;a href="http://gluegood.blogspot.com/2008/11/freeware-logparserwss30-sharepoint.html"&gt;LogParser.WSS30&lt;/a&gt;) where an e-mail can list items, or changes across multiple lists, wikis or document libraries&lt;/li&gt;&lt;li&gt;Query databases and send alerts for specific detials (in conjunction with &lt;a href="http://gluegood.blogspot.com/2008/04/freeware-logparseroledb.html"&gt;Logparser.OLEDB&lt;/a&gt;) which can e-mail row from multiple data sources. e.g. a poor man's security breach tool&lt;/li&gt;&lt;li&gt;Check for Low Disk Space, or Unexpected Server restarts&lt;/li&gt;&lt;li&gt;Notify when WLBS (monitor EventLog), or other Load Balancing product is down (monitor logs)&lt;/li&gt;&lt;li&gt;E-mail daily a combined list of file versions running on particular servers (using -i:FS)&lt;/li&gt;&lt;li&gt;Monitor IIS performance daily, weekly, monthly, or the health of the server (using -:IISW3C)&lt;/li&gt;&lt;li&gt;Check anything you have a log file for which you need to monitor.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Solution overview&lt;/strong&gt;&lt;br /&gt;1. Create a LogParser query which returns the data in exactly the way you'd want in presented in an e-mail. e.g. formatting, column positions, column names etc.&lt;br /&gt;&lt;br /&gt;2. Create a SharePoint Template file that matches the E-mail Template format. e.g., Create a LogParser Template File Named C:\Template.tpl. The Template should follow the format in the samples provided (simple one listed below). Add more or less FieldName_X as per the number of columns in the LogParser query. Also update the EmailAddress and SMTPServer address.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;LPHEADER&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Email&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Trigger Operator="&amp;gt;" Value="0" /&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Actions&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Action Type="EMAIL" EmailAddress="&lt;/span&gt;&lt;a href="mailto:destination@destination.com"&gt;&lt;span style="font-family:courier new;"&gt;destination@destination.com&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt;" SMTPServer="mail"/&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/Actions&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Rows&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/LPHEADER&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;LPBODY&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Row&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Field Name="%FIELDNAME_1%"&gt;%FIELD_1%&amp;lt;/Field&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Field Name="%FIELDNAME_2%"&gt;%FIELD_2%&amp;lt;/Field&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Field Name="%FIELDNAME_x%"&gt;%FIELD_x%&amp;lt;/Field&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/Row&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/LPBODY&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;LPFOOTER&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/Rows&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/Email&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/LPFOOTER&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3. Run the LogParser query ensuring&lt;br /&gt;a) that the INTO STDOUT clause is used&lt;br /&gt;b) that -stats:off is used to ensure that only the XML is generated to STDOUT&lt;br /&gt;c) that your LogParser results escape any XML characters. Use the REPLACE_STR function in LogParser e.g. escape &lt; &gt; " ' &amp;amp;&lt;br /&gt;d) that you pipe the result to LogParser.Email.exe&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:EVT "Select Top 10 * into STDOUT from System" -tpl:EmailTemplate.tpl -stats:off &amp;#124; LogParser.Email.exe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;a href="http://2.bp.blogspot.com/_0anrDjvtUao/SiE8ABVm4pI/AAAAAAAAAAw/YlV7RtNl-rE/s1600-h/SampleEmail.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5341616604094849682" style="WIDTH: 443px; CURSOR: hand; HEIGHT: 235px" alt="" src="http://2.bp.blogspot.com/_0anrDjvtUao/SiE8ABVm4pI/AAAAAAAAAAw/YlV7RtNl-rE/s320/SampleEmail.gif" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;strong&gt;Features of LogParser.Email.exe&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Freeware with VB.NET 2005 source code included &lt;/li&gt;&lt;li&gt;LogParser.Email can take the output from any LogParser query and deliver a 'nicely' formatted HTML SMTP e-mail. Can deliver to multiple recipients in a single e-mail, or seperate e-mails via multiple EMAIL 'Actions'&lt;/li&gt;&lt;li&gt;Used the LogParser template (-tpl) flag and a specially crafted (not too complex) Template file to pass results to the tool. &lt;/li&gt;&lt;li&gt;The tool displays the LogParser results in a grid within the e-mail. Using LogParser native facilities you can name and order the columns and format the row results (e.g. date/time formats)&lt;/li&gt;&lt;li&gt;The tool works on the concept of 'Triggers' which allow you to define when to send the e-mail based on a threshold being e.g. only send an e-mail if more than 50 LogParser rows are returned (Rows&gt;50 then send e-mail)&lt;/li&gt;&lt;li&gt;Can specify the SMTPServer, e-mail address, e-mail source address, e-mail subject, e-mail notes, e-mail footer text, and choose the colours (columns headings, and even and odd rows)&lt;/li&gt;&lt;li&gt;Using a special prefix 'NOHTMLESCAPE' on any results you can espace the HTML formatting and created HTML tags within the e-mails. e.g. Hyperlinks&lt;/li&gt;&lt;li&gt;The tool can execute a batch command (or multiple via COMMAND 'Actions') based on the Trigger&lt;/li&gt;&lt;li&gt;Logs any errors to console, EventLog.Application, and a AppPath\Trace folder&lt;/li&gt;&lt;li&gt;Can be used without LogParser by piping contents of an XML file (formatted as directed) to the utility.&lt;/li&gt;&lt;/ul&gt;*************************************************&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/nn1ntfefxa"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; VB.NET source is included in download.&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;To install:&lt;br /&gt;1. Copy the LogParser.Email.exe to C:\Program Files\Log Parser 2.2\&lt;br /&gt;&lt;br /&gt;2. Setup the Template file required. Ensure you set the fields names equal to the Sharepoint names in your Logparser query and the number also matches the FIELD_X values in the Template file.&lt;br /&gt;&lt;br /&gt;3. Run your Log Parser query.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;{STDIN Sharepoint Batch XML} LogParser.Email.exe {Optional Debug Template}"&lt;br /&gt;e.g. TYPE &amp;#124; c:\Email LogParser.Email.exe True&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;strong&gt;XML Attribues&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Below are details of the XML attributes within the Template file&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Operator&lt;/em&gt; - This is the operator that will be used to test the value against the returned Rows from LogParser. e.g. &amp;gt; &gt; or =. It must be escaped so &amp;gt; or &amp;lt; e.g. &gt;0 will mean that if the Logparser query returns any rows the trigger will be fired.&lt;br /&gt;&lt;em&gt;Value&lt;/em&gt; - This is the value which the returned rows and operator are tested against.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Action&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Type&lt;/em&gt;- Mandatory. EMAIL or COMMAND.&lt;br /&gt;&lt;em&gt;EmailAddress&lt;/em&gt; - Mandatory. SMTP destination e-mail address.&lt;br /&gt;&lt;em&gt;SMTPServer&lt;/em&gt; - Mandatory. SMTP Server name.&lt;br /&gt;&lt;em&gt;EmailText&lt;/em&gt; - Optional. Text that you'd like to appear above the results. Usually used to provide some guideance on what the result contains or what should be done to rectify.&lt;br /&gt;&lt;em&gt;EmailTextFullControl&lt;/em&gt; - Optional. Allows to override the standard header text with your own text (with NOHTMLESCAPE you can markup the text.&lt;br /&gt;&lt;em&gt;EmailSourceAddress&lt;/em&gt; - Optional. Source e-mail address.&lt;br /&gt;&lt;em&gt;EmailSubject&lt;/em&gt; - Optional. Email subject&lt;br /&gt;&lt;em&gt;EmailFooter&lt;/em&gt; - Optional. Text you'd like displayed at the bottom of the e-mail.&lt;br /&gt;&lt;em&gt;EmailColumnColour&lt;/em&gt; - Optional. The HTML colour used for the column heading.&lt;br /&gt;&lt;em&gt;EmailRowColour&lt;/em&gt; - Optional. The HTML colour used for the even rows.&lt;br /&gt;&lt;em&gt;EmailRowAlternateColour&lt;/em&gt; - Optional. The HTML colour used for the odd rows.&lt;br /&gt;&lt;em&gt;Command&lt;/em&gt; - Mandatory. Used for COMMAND type only and the full path to the command that needs to be executed.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Row&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Field name attribute&lt;/em&gt; - Name of the field&lt;br /&gt;&lt;em&gt;Field node value&lt;/em&gt; - Value for the field in this row. Values with NOHTMLESCAPE will display without their characters being escaped. e.g. hyperlinks.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-5879448990882829565?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/5879448990882829565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=5879448990882829565&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/5879448990882829565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/5879448990882829565'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2009/05/freeware-logparseremail.html' title='Freeware - LogParser.Email'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0anrDjvtUao/SiE8ABVm4pI/AAAAAAAAAAw/YlV7RtNl-rE/s72-c/SampleEmail.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-2786124646718882463</id><published>2009-04-01T22:46:00.001+11:00</published><updated>2009-04-01T23:01:47.240+11:00</updated><title type='text'>Bitten by the cloud</title><content type='html'>Software as a service, cloud computing, SOA etc or whatever the buzz word is. They all rely on trust. Trust that we won't do anything naughty with with their service, and our trust that the service is reliable and that you get plenty of warning of closure.&lt;br /&gt;&lt;br /&gt;I've been happily using &lt;a href="http://www.openomy.com/"&gt;Openomy.com&lt;/a&gt; for about 2 years after &lt;a href="http://en.wikipedia.org/wiki/Omnidrive"&gt;Omnidrive&lt;/a&gt; died. At least with Omnidrive it was around for a few months before it disappeared, while Openomy simplied died on the 24th March after 10 days notice from this &lt;a href="http://blog.openomy.com/2009/03/openomy-is-closing-down-march-24-2009.html"&gt;site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So once again I've moved content to a new provider - Box.net.&lt;br /&gt;&lt;br /&gt;P.S. Some content will be unavailable temporarily while I recover it from various locations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-2786124646718882463?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/2786124646718882463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=2786124646718882463&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/2786124646718882463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/2786124646718882463'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2009/04/bitten-by-cloud.html' title='Bitten by the cloud'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-1231255396848637633</id><published>2008-11-13T22:18:00.013+11:00</published><updated>2009-05-31T22:16:05.087+10:00</updated><title type='text'>Freeware - WSS30ListUpload (Sharepoint)</title><content type='html'>&lt;p&gt;I recently published a &lt;a href="http://gluegood.blogspot.com/2008/11/freeware-logparserwss30-sharepoint.html"&gt;solution&lt;/a&gt; to query Sharepoint lists/document libraries using LogParser. I then thought about how you could output LogParser results directly to Sharepoint (WSS 3.0) lists.&lt;/p&gt;&lt;p&gt;Some advantages that I can see of using Sharepoint as a Log Parser output is that you have a more managed location for results and additionally you could utilise the alert facilities. e.g. provide a monthly IIS statistics report that is automatically distributed to required people.&lt;/p&gt;&lt;p&gt;After some thinking I decided upon a solution involving using the LogParser output 'Template' format (-o:TPL) to generate the Sharepoint batch XML. Outputing the resultant XML to STDOUT (in the LogParser query) and then redirecting (using pipe i.e, ) to a small tool named WSS30ListUpload (which I wrote) which uploads to a SharePoint site list or document library. This allows for a solution utilising features within Log Parser and therefore provides a very clean solution with a great amount of flexibility.&lt;/p&gt;&lt;p&gt;Note: The WSS30ListUpload tool can be used without Log Parser. In essence using this tool you have a command line driven Sharepoint list uploading tool. e.g. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;type c:\listdata.xml &amp;#124; WSS30ListUpload.exe "&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;http://mysite/site/Lists/MyList/AllItems.aspx&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;"&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Solution overview&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;1. Create a SharePoint Template file that matches the SharePoint Batch XML format. e.g., Create a LogParser Template File Named &lt;span style="font-family:courier new;"&gt;&lt;em&gt;C:\Template.tpl&lt;/em&gt;&lt;/span&gt;. The Template should follow the below example. You can download a working XML in below. Add more FieldName_X as per the number of columns uploaded into SharePoint. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;LPHEADER&amp;gt;&amp;lt;Batch OnError="Continue" PreCalc="TRUE" ListVersion="0" ViewName=""&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt; &amp;lt;/LPHEADER&amp;gt;&lt;br /&gt;&amp;lt;LPBODY&amp;gt; &amp;lt;Method ID="%FIELD_1%" Cmd="New"&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_2%"&amp;gt;%FIELD_2%&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_3%"&amp;gt;%FIELD_3%&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_4%"&amp;gt;%FIELD_4%&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_5%"&amp;gt;%FIELD_5%&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_6%"&amp;gt;%FIELD_6%&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;Field Name="%FIELDNAME_7%"&amp;gt;%FIELD_7%&amp;lt;/Field&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Field Name="%FIELDNAME_8%"&amp;gt;%FIELD_8%&amp;lt;/Field&amp;gt;&lt;br /&gt;&amp;lt;/Method&amp;gt;&lt;br /&gt;&amp;lt;/LPBODY&amp;gt;&lt;br /&gt;&amp;lt;LPFOOTER&amp;gt;&amp;lt;/Batch&amp;gt;&lt;br /&gt;&amp;lt;/LPFOOTER&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2. Place &lt;em&gt;WSS30ListUpload.exe&lt;/em&gt; in &lt;em&gt;C:\Program Files\LogParser 2.2\&lt;/em&gt;&lt;/p&gt;&lt;p&gt;3. Run the LogParser query ensuring&lt;br /&gt;a) that the first column is a unique number per row. e.g. RecordNumber&lt;br /&gt;b) that a column [ID] is generated with the text 'New'&lt;br /&gt;c) that the column names match either the SharePoint 'DisplayName' (the title in SharePoint), or the underlying Name (e.g. 'This_x0020_Field' vs 'This Field') within the list.&lt;br /&gt;d) that the INTO STDOUT clause is used.&lt;br /&gt;e) that -stats:off is used to ensure that only the XML is generated to STDOUT.&lt;br /&gt;f) that you pipe the result to WSS30ListUpload.exe which takes a single command line parameter of the SharePoint List URL.&lt;br /&gt;&lt;br /&gt;e.g. &lt;span style="font-family:courier new;"&gt;LogParser.exe -i:EVT "Select Top 10 RecordNumber,'New' as [ID],EventLog,RecordNumber,TimeGenerated,TimeWritten,EventID,EventType into STDOUT from System" -tpl:c:\SharePointTemplate.tpl -stats:off &amp;#124; WSS30ListUpload.exe "&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;http://mysite/site/Lists/Test/AllItems.aspx&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;"&lt;/span&gt; &lt;/p&gt;&lt;p&gt;Note: The result from the execution is the Sharepoint Lists.asmx -&gt; UpdateListItems XML response. Any errors resulting from the upload will be in this file. If you want to capture it to file redirect to a file. e.g. add &lt;span style="font-family:courier new;"&gt;&gt; C:\Output.xml&lt;/span&gt; at the end of the example above.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Features of WSS30ListUpload&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Freeware with VB.NET 2005 source code included &lt;/li&gt;&lt;li&gt;Can execute any Sharepoint Batch XML file against WSS 3.0 list, wiki, or document library content. Have only tested on WSS 3.0 - it may work on earlier or later versions. Uses the web service Lists.asmx -&gt; UpdateListItems.&lt;/li&gt;&lt;li&gt;Single command line parameter is SharePoint URL to List/Document Library. Internally resolves Site and List Name based on the URL.&lt;/li&gt;&lt;li&gt;STDIN supports Batch XML&lt;/li&gt;&lt;li&gt;The STDOUT from WSS30ListUpload is the result of Sharepoint Lists.asmx -&gt; UpdateListItems in XML format. This includes any errors.&lt;/li&gt;&lt;li&gt;Supports both Name and DisplayName for the Sharepoint column names. To do this it automatically translates Sharepoint column DisplayNames into Name (e.g 'This Field' becomes 'This_x0020_Field'). In addition if duplicate DisplayNames are found then will abort the upload.&lt;/li&gt;&lt;li&gt;Logs any errors to console and to EventLog.Application&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;*************************************************&lt;br /&gt;&lt;a href="http://www.box.net/shared/g8chbt2j3y"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt; VB.NET source is included in download.&lt;br /&gt;*************************************************&lt;/p&gt;&lt;p&gt;To install:&lt;/p&gt;&lt;p&gt;1. Copy the WSS30ListUpload.exe to C:\Program Files\Log Parser 2.2\&lt;/p&gt;&lt;p&gt;2. Setup the Template file required. Ensure you set the fields names equal to the Sharepoint names in your Logparser query and the number also matches the FIELD_X values in the Template file. &lt;/p&gt;&lt;p&gt;3. Run your Log Parser query. &lt;/p&gt;&lt;p&gt;*************************************************&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;{STDIN Sharepoint Batch XML} WSS30ListUpload.exe {SharePointListURL}"&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;e.g. TYPE c:\batch.xml &amp;#124; WSS30ListUpload.exe &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;http://mysite/site/lists/MyList/AllItems.aspx&lt;/span&gt;&lt;/p&gt;&lt;p&gt;*************************************************&lt;/p&gt;&lt;p&gt;** Legal **&lt;/p&gt;&lt;p&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-1231255396848637633?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/1231255396848637633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=1231255396848637633&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1231255396848637633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1231255396848637633'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/11/freeware-wss30listupload-sharepoint.html' title='Freeware - WSS30ListUpload (Sharepoint)'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-6341090726569645075</id><published>2008-11-08T16:27:00.008+11:00</published><updated>2009-04-01T22:35:43.731+11:00</updated><title type='text'>Freeware - Logparser.WSS30 (SharePoint)</title><content type='html'>&lt;em&gt;Also see the next post concerning &lt;a href="http://gluegood.blogspot.com/2008/11/freeware-wss30listupload-sharepoint.html"&gt;Log Parser Sharepoint output&lt;/a&gt; solution&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I recently came across the need query a SharePoint Document and List libraries programatically . I played with CAML and found the experience fairly miserable. I played with LINQ and warmed a little to the technology, but in the end came back to Logparser and writing a custom input format plugin.&lt;br /&gt;&lt;br /&gt;I decided that LogParser needed a SharePoint (WSS 3.0) Log Parser COM input format plugin. I've been playing with the plugin for a couple of months as the complexities in Sharepoint web services soon became obvious.&lt;br /&gt;&lt;br /&gt;Hope you find the utility useful, and if not the utility then the code. Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Features&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Freeware with VB.NET 2005 source code included &lt;/li&gt;&lt;li&gt;Can query WSS 3.0 list, wiki, or document library content. Have only tested on WSS 3.0 - it may work on earlier or later versions.&lt;/li&gt;&lt;li&gt;Supports retrieving columns and rows back to the LogParser engine based on your existing defined views in the list, wiki, or document library. Additionally can ignore columns in the view and returning all fields (including hidden).&lt;/li&gt;&lt;li&gt;No CAML. Create a SharePoint view and call it with LogParser using all its querying techniques on the returned data.&lt;/li&gt;&lt;li&gt;Supports multiple list, wiki, or document library querying.&lt;/li&gt;&lt;li&gt;Supports version (check in) details for list, wiki or document libraries. This enables you to retrieve all historical changes for a list if version control is enabled on the list, wiki, or document library.&lt;/li&gt;&lt;li&gt;Implements iCheckPoint to support only showing the latest added content to the list, wiki, or document library&lt;/li&gt;&lt;li&gt;Implements a number of custom columns (as per standard LogParser). They are listed below. This is to provide extra querying features. &lt;/li&gt;&lt;li&gt;Logs any errors to console and to EventLog.Application&lt;/li&gt;&lt;li&gt;Supports Log Parser data types.&lt;/li&gt;&lt;li&gt;Uses the ILogParserInputContext interface to enable LogParser COM interface to directly call. i.e, you can code against this plugin.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;*************************************************&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.box.net/shared/7uv5ia9k0x"&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Download&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt; VB.NET source is included in download.&lt;/p&gt;&lt;p&gt;*************************************************&lt;/p&gt;To install:&lt;br /&gt;1. Copy the LogParser.WSS30 folder to a location on your harddrive&lt;br /&gt;2. Run the command .\LogParser.WSS30\InstalldotNETasCOM.bat (need GACUTIL.EXE - part of the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec"&gt;.NET FW 2.0 SDK&lt;/a&gt; - &lt;a href="http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx"&gt;why&lt;/a&gt;?). This will install into the GAC the Gluegood.LogParser.WSS30.&lt;br /&gt;3. Run your Log Parser query. e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From 'http://sharepoint.net/topsite/mysite/Lists/Change Control/AllItems.aspx'" -iProgId:Gluegood.LogParser.WSS30 -o:DataGrid&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Syntax :-&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From '{URL1}','{URL2}',..." -iProgId:Gluegood.LogParser.WSS30 -o:DataGrid -iComParams:"iVersion={TrueFalse},iAllFields={TrueFalse},iSiteCollection={SiteURL},iListName={ListName or ListGUID},iViewGUID={ListGUID},"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;{URLx}&lt;/strong&gt; - a URL to the path of the SharePoint list and including the view name. Within Sharepoint open a document library, choose your view and then copy the link. Supports multiple URLs as long as they are deliminated with a comma (,).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;iVersion&lt;/strong&gt; - Whether the history for each record should be included. Default = False.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;iAllFields &lt;/strong&gt;- Ignore the columns defined in the view and retrieve all columns including hidden columns. Default = False&lt;/li&gt;&lt;li&gt;&lt;strong&gt;iSiteCollection&lt;/strong&gt;, &lt;strong&gt;iListName&lt;/strong&gt;, &lt;strong&gt;iViewGUID&lt;/strong&gt; - You can manually define the site, list name and GUID for the view. This shouldn't be required except for where the code's logic fails to determine these 3 values from the {URL}. If using these settings set {URL} = '.' - see SampleQuery.bat for example. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Columns returned&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;LogParserListName&lt;/em&gt; - The name, or GUID of the list, wiki or document library. GUID is returned where the title of the list is different from the URL path. SharePoint strips special characters from the URL path name. e.g. v2.4 vs v24 &lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserRecordNumber&lt;/em&gt; - A counter used to uniquely identify the row.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserItemURL&lt;/em&gt; - The URL to the item in the list, wiki or document library.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserListItemId&lt;/em&gt; - (iVersion only) The unique item id.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserVersionId&lt;/em&gt; - (iVersion only) The Version number of the check in.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserVersionModified&lt;/em&gt; - (iVersion only) Time that the check in occurred.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserVersionModifiedBy&lt;/em&gt; - (iVersion only) Who checked in the change.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LogParserVersionComments&lt;/em&gt; - (iVersion only) Provides the check in comments. Available only for Wiki and Document Libraries.&lt;/li&gt;&lt;li&gt;&lt;em&gt;{Columns defined in the view}&lt;/em&gt; - beyond the fields above only the columns defined in the view. Sharepoint provides a DisplayName and Name for each column defined. Where possible I try to name the columns (as per the view) by their DisplayName. When however I find that the DisplayName is non-unique I revert to its unique Name.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Challenges&lt;/span&gt;&lt;/strong&gt; -&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Version&lt;/strong&gt; - The implementation of retrieving version details in Sharepoint isn't straight forward.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Trap 1&lt;/em&gt; - There isn't a single call to retrieve version details for a view. To retrieve history for items you must retrieve all the nodes using &lt;em&gt;Lists.asmx -&gt; GetListItems&lt;/em&gt; and then loop through each node and &lt;em&gt;&lt;strong&gt;each column&lt;/strong&gt;&lt;/em&gt; in that node using &lt;em&gt;Lists.asmx -&gt; GetVersionCollection&lt;/em&gt;. That's right &lt;em&gt;GetVersionCollection&lt;/em&gt; provides history per column. Performance is therefore fairly horrible so if you are looking for version details ensure that&lt;br /&gt;a) create a view in SharePoint that has the fields you require (reduce the number of columns) and&lt;br /&gt;b) consider using checkpoint to reduce the amount of rows returned.&lt;br /&gt;Thanks to this &lt;a href="http://www.sharepointkings.com/2008/09/working-with-versions-in-list.html"&gt;site&lt;/a&gt; for pointing me in the right direction in regards to versions and Sharepoint. &lt;/li&gt;&lt;li&gt;&lt;em&gt;Trap 2&lt;/em&gt; - You'd think that Version comments using the Sharepoint field &lt;em&gt;ows__CheckinComments&lt;/em&gt; would come through using Lists.asmx -&gt; GetVersionCollection, especially because it it part of GetListItems. Not in Sharepoint land. You do get the Comments, but only the last one (miserable!). To get all comments you need to make a call to Versions.asmx -&gt; GetVersions and look at the comments attribute and then match up the version to the rest of the list details. &lt;/li&gt;&lt;li&gt;&lt;em&gt;Trap 3&lt;/em&gt; - I really struggled in ensuring that all parts of the version details aligned. The simpliest way I could find was creating a datatable with the columns I required and then creating a base entry for all the versions available for that item based on the &lt;em&gt;ows__UIVersionString&lt;/em&gt; field and using its Modified field (date/time). Then because every &lt;em&gt;GetVersionCollection&lt;/em&gt; for a field returns a &lt;em&gt;Modified&lt;/em&gt; field in addition to the field you are after you are able to sync it up against the row version (why it doesn't return the&lt;em&gt; ows__UIVersionString&lt;/em&gt; is beyond me). Because in &lt;em&gt;Versions.asmx -&gt; GetVersions&lt;/em&gt; you can't rely on the &lt;em&gt;Modified&lt;/em&gt; time we are fortunate that version is returned (equivalent to &lt;em&gt;ows__UIVersionString&lt;/em&gt;) as a matching row. &lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;&lt;/strong&gt;&lt;p&gt;&lt;strong&gt;Column headings&lt;/strong&gt; - If you call &lt;em&gt;Lists.asmx -&gt; GetListItems&lt;/em&gt; you get a list of &lt;strong&gt;ALL&lt;/strong&gt; fields available and secondly their column name is based on the internal Sharepoint name, not the name displayed to end user (these names are truncated by the way, so not very nice). To get around this I make an initial call to &lt;em&gt;Lists.asmx -&gt; GetListAndView&lt;/em&gt; which supplies for the view the internal Sharepoint name (&lt;em&gt;Name&lt;/em&gt;) and its friendly name (&lt;em&gt;DisplayName&lt;/em&gt;). . A userful trick is that in the datatable I create and store the &lt;em&gt;Name&lt;/em&gt; as the &lt;em&gt;Column.Name&lt;/em&gt; and the &lt;em&gt;DisplayName &lt;/em&gt;as the &lt;em&gt;Column.Caption&lt;/em&gt; - useful as they are often different. Sharepoint allows for the same &lt;em&gt;DisplayName&lt;/em&gt; therefore you need to (and I do) revert to &lt;em&gt;Name&lt;/em&gt; for the &lt;em&gt;Column.Caption&lt;/em&gt; if I find a duplicate. When I return back to Log Parser I use the &lt;em&gt;Column.Caption&lt;/em&gt;. By using the &lt;em&gt;GetListandView&lt;/em&gt; method you are also able to get the data types of the field, which I can then map to LogParser datatypes. All up by making this extra web service call you are able to get the columns in this view, their friendly name, and their datatype.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ViewName (you mean ViewGUID)&lt;/strong&gt; - Sharepoint documentation for its web services provide a field named ViewName. e.g. GetListItems&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function GetListItems (listName As String, viewName As String, ... etc)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;You'd think that like ListName you can provide either the 'friendly name' or the 'ListGUID'. In the case of ViewName it actually always means &lt;strong&gt;ViewGUID&lt;/strong&gt;. So if you have the 'friendly name' you need to make a call to &lt;em&gt;Views.asmx -&gt; GetViewCollection&lt;/em&gt; and then hunt for your GUID. I do this in the code for you.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;xpath and Sharepoint&lt;/strong&gt; - I spent a couple of days fighting with xpath queries and Sharepoint. After a number of frustrating hours I finally discovered a site which talked about needing to use &lt;a href="http://www.csharphelp.com/archives4/archive602.html"&gt;namespaces in SharePoint xpath&lt;/a&gt; queries.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim nodeListItems As System.Xml.XmlNode = Webservice.GetListCollection()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim xpq As String = "//Lists/List"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;For Each Node As System.Xml.XmlNode In nodeListItems.SelectNodes(xpq)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;while this does&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim nodeListItems As System.Xml.XmlNode = Webservice.GetListCollection()&lt;br /&gt;Dim xpq As String = "//sp:Lists/sp:List"&lt;br /&gt;For Each Node As System.Xml.XmlNode In RunSharePointXPathQuery(nodeListItems, xpq)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;* Download code for function RunSharePointXPathQuery&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Date Time in SharePoint web service&lt;/strong&gt; - It is truely amazing that different web methods in SharePoint return times in UTC or local timezone format. The most frustrating is that &lt;em&gt;Lists.asmx -&gt; GetListItems&lt;/em&gt; can return in UTC, while &lt;em&gt;Versions.asmx -&gt; GetVersions&lt;/em&gt; and &lt;em&gt;Lists.asmx -&gt; GetVersionCollection&lt;/em&gt; do not. There is a useful &lt;a href="http://www.sharepointblogs.com/pm4everyone/archive/2006/10/03/sharepoint-2003-querying-with-gmt-datetime.aspx"&gt;blog&lt;/a&gt; talking about UTC and SharePoint.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-6341090726569645075?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/6341090726569645075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=6341090726569645075&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6341090726569645075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6341090726569645075'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/11/freeware-logparserwss30-sharepoint.html' title='Freeware - Logparser.WSS30 (SharePoint)'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-4218019402438780790</id><published>2008-09-11T22:03:00.007+10:00</published><updated>2009-07-01T19:12:07.921+10:00</updated><title type='text'>Freeware - Logparser.ZIP</title><content type='html'>My last project was an OLEDB Log Parser COM input format plugin. One of the &lt;a href="http://forums.iis.net/p/1149010/1867927.aspx"&gt;comments &lt;/a&gt;was that ‘we’ (meaning I) should work on a solution to query within ZIP files. I read the comment at the time and thought the suggestion was very specific and technically very difficult. Several months have passed and I did some more research and found a few &lt;a href="http://forums.iis.net/t/1149963.aspx"&gt;more&lt;/a&gt; &lt;a href="http://forums.iis.net/t/1144572.aspx"&gt;comments&lt;/a&gt; on trying to do this.....&lt;br /&gt;&lt;br /&gt;Ta-da! Introducing a Log Parser COM input format ZIP plugin that will allow you to execute any Log Parser input query (e.g., –i:CSV, -i:IISW3C, -:TSV) against a single, or multiple Zip, GZip, Tar and BZip2 files. * For convenience I’ll refer to this set of files as ZIP files.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Freeware with VB.NET 2005 source code included&lt;/li&gt;&lt;li&gt;Can query Zip files (GZip, Tar and BZip2 files are supported via an extension written by &lt;a href="http://joelangley.blogspot.com/2009/06/logparser-unzip-and-parse.html"&gt;joelangley&lt;/a&gt;). To reduce disk requirements the LogParser.ZIP plugin extracts each file inside the zip, runs the Log Parser query, then deletes the unpacked file and repeats for each file.&lt;/li&gt;&lt;li&gt;Supports multiple zip files including wildcards, so you can query in the same Log Parser query across not only multiple files within a single ZIP, but multiple ZIP files either using comma separated list, or wildcards. E.g. ‘Select * From ‘2009*.zip’,’ 200812.zip’”&lt;/li&gt;&lt;li&gt;Supports all Log Parser Input Queries and their associated parameters. Note: Because the zip files are unpacked and then deleted the iCheckPoint parameter doesn’t work as it thinks the files have completely changed.&lt;/li&gt;&lt;li&gt;Implements iCheckPoint to support only showing the latest added files to the ZIP (not too sure if this will always work). This is supported across multiple ZIP files.&lt;/li&gt;&lt;li&gt;Implements 2 custom columns (as per standard LogParser). They are LogParserZIPFilename, LogParserRecordNumber in addition to returned columns. This is to provide extra querying features.&lt;/li&gt;&lt;li&gt;Logs any errors to console and to EventLog.Application&lt;/li&gt;&lt;li&gt;Supports all Log Parser data types except TIMESTAMP_TYPE, see challenges below.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;*************************************************&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/6bn09kg4xg"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB.NET source is included in download.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;em&gt;&lt;span style="color:#ff0000;"&gt;Note: I've given the code a good test, however there may be unexpected bugs. As this code has overwrite and delete file features please ensure that you test the software.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;To install:&lt;br /&gt;&lt;/em&gt;1. Copy the &lt;strong&gt;LogParser.ZIP&lt;/strong&gt; folder to a location on your harddrive&lt;br /&gt;2. Run the command &lt;strong&gt;.\LogParser.ZIP\InstalldotNETasCOM.bat&lt;/strong&gt; (need GACUTIL.EXE - part of the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec"&gt;.NET FW 2.0 SDK&lt;/a&gt; - &lt;a href="http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx"&gt;why&lt;/a&gt;?). This will install into the GAC the 3 components being &lt;em&gt;Gluegood.LogParser.ZIP&lt;/em&gt;, &lt;em&gt;Interop.MSUtil.dll&lt;/em&gt; (LogParser wrapper) and &lt;em&gt;ICSharpCode.SharpZipLib.dll.&lt;/em&gt;&lt;br /&gt;3. Change directory to the location where LogParser.ZIP can extract and then delete the unpacked zip files and directories. E.g. &lt;em&gt;cd c:\test&lt;br /&gt;&lt;/em&gt;4. Run your Log Parser query. e.g. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From 'C:\Test\Test.zip'" -iProgId:Gluegood.LogParser.ZIP -iCOMParams:iQuery="Select * From *.txt",iInputParameters="-i:CSV -HeaderRow:Off" -o:DataGrid&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Syntax&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From {ZIPFile(s)}'" -iProgId:Gluegood.LogParser.ZIP -iCOMParams:iQuery="{LogParserQuery}",iInputParameters="{LogParser InputParameters}" -o:DataGrid&lt;/span&gt;&lt;/p&gt;&lt;p&gt;*************************************************&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Challenges&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;1. Calling Log Parser APIs within VB.NET&lt;/strong&gt;&lt;br /&gt;The LogParser.ZIP COM Plugin is a VB.NET program that is COM interop enabled (to allow for LogParser to call it). Additionally it calls the LogParser COM API to execute LogParser queries thus making the whole interfacing rather technically challenging.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;a) GAC, assemblies and DLLs&lt;/em&gt;&lt;br /&gt;To enable LogParser to call LogParser.ZIP COM input plugin you need to give it a strong name, register and then publish it to the Global Assembly Cache (GAC). Due to the LogParser.ZIP residing in the GAC you need to create a dotNet wrapper for the Log Parser COM APIs (LogParser.dll), give it a strong name, and then place it too into the GAC. After a number of trials I found that the TLBIMP program did just this :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\tlbimp "C:\Program Files\Log Parser 2.2\LogParser.dll" /out:Interop.MSUtil.dll /keyfile:"GluegoodStrongKey.snk"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I then needed to Register the dotNet wrapper (Interop.MSUtil.dll) using REGASM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe .\Interop.MSUtil.dll&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I then needed to place Interop.MSUtil.dll into the GAC&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil" /i .\Interop.MSUtil.dll&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(The InstalldotNETasCOM.bat does all of the above for you)&lt;br /&gt;&lt;br /&gt;I then added a reference to the Interop.MSUtil.dll within my VB.Net project and can now call the LogParser COM API.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;b) Calling late bound a COM dll using VB.NET reflection&lt;br /&gt;&lt;/em&gt;To enable the greatest flexibility with the solution I needed to enable users to specify all Input types. E.g. –i:CSV, -i:TSV etc. Therefore I needed to dynamically call the COM Input Context Class. In my research this seems only achievable in using Reflection. Unfortunately there isn’t a lot of documentation on COM interop reflection using the GAC (bit unique I’d suggest). I found 2 &lt;a href="http://liquidboy.blogspot.com/search/label/Type.GetConstructor"&gt;useful&lt;/a&gt; &lt;a href="http://www.eggheadcafe.com/articles/20050717.asp"&gt;articles&lt;/a&gt; that helped provide guidance on what to do – I’d like the thank the authors for documenting this.&lt;br /&gt;&lt;br /&gt;Effectively I late bound to the COM input class using code exampled in this &lt;a href="http://www.eggheadcafe.com/articles/20050717.asp"&gt;site&lt;/a&gt;. One gotcha was the late bound GAC name I had to use for Interop.MSUtil.dll. Initially I used just Interop.MSUtil, however I found that the late bound function didn’t work, therefore I used the full GAC name for the assembly being&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Interop.MSUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=048dde0ba838787f, processorArchitecture=MSIL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I then had to set the Input Parameters and I used a function called CallByName, which allows you to set object properties by name, instead of early binding (very cool).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. Deciding on ZIP API&lt;/strong&gt;&lt;br /&gt;There are 2 major free ZIP APIs available for dotNET developers. The jslib ZIP methods, or the &lt;a href="http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx"&gt;#ZIPLib dotNET Library&lt;/a&gt;. I decided on the latter simply because it was open source like my solution, it had a smaller footprint (wasn’t an extra download) and the comments out in the community tended to favour it as a solution. Additionally it provided more than just ZIP extraction which I thought may be useful. For the sceptics it was really easy to implement within my code.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3. TIMESTAMP_TYPE datatype conversion issue&lt;/strong&gt;&lt;br /&gt;This remains unsolved, so if anyone has any ideas let me know. The LogParser.ZIP program extracts each value in the IRecordSet response and places into a DataTable. In my code I match the DataTable column data types to the LogParser column data types. When I then return to LogParser (via the GetFieldType method) the values I re-convert the DataTable column types to the appropriate LogParser FieldType. For some very strange reason the delivery of TIMESTAMP_TYPE on sample data I tried performed extremely poorly when compared to STRING_TYPE. E.g. 2 seconds compared to 5 minutes. I therefore decided not to convert TIMESTAMP_TYPE, but pass any TIMESTAMP columns back as STRING_TYPE.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-4218019402438780790?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/4218019402438780790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=4218019402438780790&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4218019402438780790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4218019402438780790'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/09/freeware-logparserzip.html' title='Freeware - Logparser.ZIP'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-3818681869677145753</id><published>2008-04-23T20:51:00.009+10:00</published><updated>2009-04-01T22:44:49.978+11:00</updated><title type='text'>Freeware - Logparser.OLEDB</title><content type='html'>&lt;p&gt;Log Parser has a native extension which allows developers to write their own custom input formats and for users to query using the i:COM input format. I decided to write the OLEDB Log Parser COM input format plugin so I could extend the data sources which LogParser could query. By using OLEDB and LogParser you have an extremely powerful tool which can provide complex querying solutions.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Using this DLL with LogParser you can query any OLEDB datasource which Log Parser doesn't support natively. e.g Excel, Access, DBF, MSSQL, Oracle, MS Project, FoxPro, AS/400, Index Server, HTML Tables, Text Files, and any other custom OLEDB providers. There are a number of &lt;a href="http://www.connectionstrings.com/"&gt;sites&lt;/a&gt; with OLEDB Connection Strings&lt;/li&gt;&lt;li&gt;Provide a query for the base OLEDB datasource and a query for Log Parser. e.g. get the data you want back from the data source and let Log Parser provide its SQL querying features (e.g. min, max, avg, etc and numerous functions) to format the data correctly.&lt;/li&gt;&lt;li&gt;Supports multiple datasources, so you can query in the same LogParser query across multiple Excel spreadsheets, Access databases, SQL databases etc. Extremely useful to query multiple data sources to discover the location of data.&lt;/li&gt;&lt;li&gt;Implements iCheckPoint to support only showing the latest records. This is supported across multiple data sources in a single query.&lt;/li&gt;&lt;li&gt;Implements 2 custom columns (as per standard LogParser). They are LogParserConnectionString, LogParserRecordNumber in addition to returned columns.&lt;/li&gt;&lt;li&gt;Logs any errors to console and to EventLog.Application &lt;/li&gt;&lt;li&gt;VB.NET 2005 source code included&lt;/li&gt;&lt;li&gt;Note: Doesn't currently support conversion of OLEDB datatypes to LogParser datatypes - everything is provided to LogParser engine as as string.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Below are some of the challenges :-&lt;/p&gt;&lt;p&gt;1. Add new columns to a DataSet, placing in the right order and setting their value. The trick is to add the columns and then to reverse transverse through the records updating them. &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;'oDataSet.Tables(0).Columns.Add("LogParserRecordNumber", 'System.Type.GetType("System.String"))&lt;br /&gt;'oDataSet.Tables(0).Columns("LogParserRecordNumber").SetOrdinal(1)&lt;br /&gt;'Dim lIndex As Long = lRowCount - 1&lt;br /&gt;'Do Until lIndex = -1&lt;br /&gt;' Dim oRow As DataRow = oDataSet.Tables(0).Rows(lIndex)&lt;br /&gt;' If (lIndex + 1) &lt;= lCheckPointOffset Then &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;' 'Can delete this row from in-memory datatable&lt;br /&gt;' &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oRow.Delete()&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;' oRow.AcceptChanges()&lt;br /&gt;' Else&lt;br /&gt;' ' Keep this row and add values to it.&lt;br /&gt;' lRecordNumber = lRecordNumber + 1&lt;br /&gt;' oRow.BeginEdit()&lt;br /&gt;' oRow.Item("LogParserRecordNumber") = lRecordNumber&lt;br /&gt;' oRow.EndEdit()&lt;br /&gt;' End If&lt;br /&gt;' lIndex = lIndex - 1&lt;br /&gt;'Loop&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2. Allowing Log Parser to escape quote (") in the command line request inside of the LogParser.exe query. The below query has quotes within quotes and to allow LogParser to accept this you must escape with slash (\). e.g. \"&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM &lt;span style="color:#000000;"&gt;"&lt;/span&gt;select * From &lt;em&gt;'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\SOLVSAMP.XLS;Extended Properties=&lt;strong&gt;\"Excel 8.0;HDR=Yes;IMEX=1;\"&lt;/strong&gt;'&lt;/em&gt;" -iProgId:Gluegood.LogParser.OLEDB -iCOMParams:iQuery="SELECT * FROM [Quick Tour$]" -o:DataGrid&lt;/span&gt;&lt;/p&gt;&lt;p&gt;*************************************************&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.box.net/shared/ovxv50cs97"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB.NET source is included in download.&lt;/p&gt;&lt;p&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy the LogParser.OLEDB folder to a location on your harddrive&lt;br /&gt;2. Run the command .\LogParser.OLEDB\InstalldotNETasCOM.bat (need GACUTIL.EXE - part of the&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec"&gt; .NET FW 2.0 SDK&lt;/a&gt; - &lt;a href="http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx"&gt;why&lt;/a&gt;?)&lt;br /&gt;3. Run your Log Parser query. e.g. &lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb;'" -iProgId:Gluegood.LogParser.OLEDB -iCOMParams:iQuery="SELECT * FROM [Employees]",iCheckPoint="C:\CheckPointTest.chk" -o:DataGrid&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:+0;"&gt;Syntax&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:COM "select * From '&amp;lt;&lt;em&gt;oledbConnectionString&amp;gt;&lt;strong&gt;&lt;oledbconnectionstring&gt;&lt;/strong&gt;&lt;/em&gt;'" -iProgId:&lt;strong&gt;Gluegood.LogParser.OLEDB&lt;/strong&gt; -iCOMParams:&lt;strong&gt;iQuery="&amp;lt;QueryString&amp;gt;&lt;oledbquery&gt;"&lt;/strong&gt;, ,&lt;strong&gt;iCheckPoint="&amp;lt;CheckPointFile&amp;gt;&lt;checkpointfile&gt;"&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:0;"&gt;*************************************************&lt;/span&gt; &lt;/p&gt;&lt;p&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/p&gt;&lt;em&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-3818681869677145753?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/3818681869677145753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=3818681869677145753&amp;isPopup=true' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/3818681869677145753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/3818681869677145753'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/04/freeware-logparseroledb.html' title='Freeware - Logparser.OLEDB'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-4835332381835261806</id><published>2008-03-16T16:29:00.004+11:00</published><updated>2009-04-01T22:45:49.139+11:00</updated><title type='text'>Freeware - Logparser.VSSJournal</title><content type='html'>Now that I understand the Log Parser COM input format &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;plugin&lt;/span&gt; I have migrated the &lt;a href="http://gluegood.blogspot.com/2007/11/freeware-vssmonitor.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;VSSMonitor&lt;/span&gt;&lt;/a&gt; code into a Log Parser input format &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;plugin&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Features :-&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Read &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;VSS&lt;/span&gt; 6.0 Journal files via Log Parser queries&lt;/li&gt;&lt;li&gt;Supports all fields and converts dates&lt;/li&gt;&lt;li&gt;Supports &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;iCheckPoint&lt;/span&gt; feature -custom implementation, but basically the same as the implementation that Log Parser &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;natively&lt;/span&gt; supports&lt;/li&gt;&lt;li&gt;Logs any errors to console and to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;EventLog&lt;/span&gt;.Application&lt;/li&gt;&lt;li&gt;VB.NET source code included&lt;/li&gt;&lt;li&gt;Supports only a single &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;VSS&lt;/span&gt; Journal file in a single call. e.g. * , ; are not supported.&lt;/li&gt;&lt;/ul&gt;Below are some of the challenges :-&lt;br /&gt;&lt;br /&gt;1. &lt;strong&gt;Implementing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;iCheckPoint&lt;/span&gt;&lt;/strong&gt; - Because I used &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;StreamReader&lt;/span&gt; there was a whole lot of hassle (i.e. research) in trying to record the position that I had streamed in the file. The biggest problem is &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;StreamReader&lt;/span&gt; position can be different from the stated StreamReader.BaseStream.Position, there are lots of articles &lt;a href="http://forums.devx.com/showthread.php?t=16523"&gt;out&lt;/a&gt; &lt;a href="http://www.xtremedotnettalk.com/showthread.php?t=87651&amp;amp;goto=nextoldest"&gt;there&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2387562&amp;amp;SiteID=1"&gt;about&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=6720&amp;amp;SiteID=1"&gt;this&lt;/a&gt;, however in my specific implementation I believe I'm safe. I first mark the StreamReader.BaseStream.Position from the last recorded file position before I even do a read. Then I &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;ReadLine&lt;/span&gt; the file contents and when I get to the end I record the StreamReader.BaseStream.Position. The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;StreamReader&lt;/span&gt; reads ahead and stores in a buffer, however at the end of the file there is nothing else to read so the StreamReader.BaseStream.Position is at the end.&lt;br /&gt;&lt;br /&gt;2. &lt;strong&gt;Storing the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;iCheckPoint&lt;/span&gt; values&lt;/strong&gt; - I wanted to create a flexible solution to store the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;iCheckPoint&lt;/span&gt; values. Now I could simply store only the offset of a single file, however I wanted to be as flexible as the Log Parser team have made theirs so I wanted to allow for multiple offsets based on the specified FROM fields. I decided to make a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;ArrayList&lt;/span&gt; with a Class per each file parsed using serialization. The standard Microsoft System.Xml.Serialization.XmlSerializer class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;doesn't&lt;/span&gt; support complex structures, so I couldn't use this. I found on the &lt;a href="http://www.codeproject.com/KB/vb/CustomXmlSerializer.aspx"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;CodeProject&lt;/span&gt; site a piece of code&lt;/a&gt; that supports serializing and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;de-serializing&lt;/span&gt; complex class structures which I had added to the code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/nosf0evn18"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB.NET source is included in download.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;LogParser&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;VSSJournal&lt;/span&gt; folder to a location on your &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;harddrive&lt;/span&gt;&lt;br /&gt;2. Run the command .\LogParser.VSSJournal\InstalldotNETasCOM.bat (need &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;GACUTIL&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;EXE&lt;/span&gt; - part of the&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec"&gt; .NET &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;FW&lt;/span&gt; 2.0 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;SDK&lt;/span&gt;&lt;/a&gt; - &lt;a href="http://blogs.msdn.com/astebner/archive/2006/11/04/why-to-not-use-gacutil-exe-in-an-application-setup.aspx"&gt;why&lt;/a&gt;?)&lt;br /&gt;3. Run your Log Parser query.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;LogParser&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;exe&lt;/span&gt; -i:COM "select * From 'journal.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;txt&lt;/span&gt;'" -iProgId:Gluegood.LogParser.VSSJournal -&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;iCOMParams&lt;/span&gt;:&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;iCheckPoint&lt;/span&gt;=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;VSSCheckpoint&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;chk&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-4835332381835261806?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/4835332381835261806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=4835332381835261806&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4835332381835261806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/4835332381835261806'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/03/freeware-logparservssjournal.html' title='Freeware - Logparser.VSSJournal'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-7748349716628329468</id><published>2008-03-09T21:01:00.030+11:00</published><updated>2009-05-02T16:35:42.332+10:00</updated><title type='text'>Freeware - LogParser.SampleQFE</title><content type='html'>I decided to have a go at writing a Log Parser COM Input Format Plugin using VB.NET. The COM Input Format Plugins allow you to write your own data custom parser of a data source. &lt;em&gt;Note: This is different from the Log Parser COM Interface where you can call Log Parser methods from code. &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I decided to look for some VB.NET examples, however couldn't see any out there so I thought that I'd convert the VBScript SampleQFE (which is available in the .\Log Parser 2.2\Samples\COM\QFE folder).&lt;br /&gt;&lt;br /&gt;Couple of points I found in my travels.&lt;br /&gt;1. Log Parser needs components that expose COM interfaces, therefore if you are using VB.NET you need to do the following :-&lt;br /&gt;a. Mark the Class you build as a 'COM Class' and 'COM visible'&lt;br /&gt;b. If you want it having a sensible COM name then use the code below :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;System.Runtime.InteropServices.ProgId("Gluegood.LogParser.SampleQFE") _&lt;br /&gt;, Microsoft.VisualBasic.ComClass()&amp;gt; _&lt;br /&gt;Public Class SampleQFE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;c. Bit of a gotcha for young players is that the AssemblyInfo.vb file of your project you must also have this line :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Assembly: ComVisible(True)&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;See this artcile for more information on COM in .NET&lt;br /&gt;&lt;a href="http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=113"&gt;&lt;em&gt;Calling .NET From COM&lt;/em&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;2. Additionally you must install it in the Global Assembly Cache (GAC). To install into the GAC you need to provide it with a Strong Key Name.&lt;br /&gt;a. Run this command to generate a new Strong Key Name&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sn" -k .\your folder\SampleQFE.snk&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;b. Add the SampleQFE.snk (which contains the Strong Key Name) to you project using the following line in code :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;Assembly: AssemblyDelaySign(False)&amp;gt;&lt;br /&gt;&amp;lt;Assembly: AssemblyKeyFile("C:\LogParser.SampleQFE\Code\SampleQFE\My Project\SampleQFE.snk")&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;See this &lt;a href="http://www.codeguru.com/columns/experts/article.php/c4643/"&gt;article&lt;/a&gt; for more info on this.&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;3. Compile&lt;br /&gt;4. Register the COM interfaces into the Registry using REGASM.EXE. e.g. the following command :-&lt;br /&gt;"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\LogParser.SampleQFE\Code\SampleQFE\bin\Release\SampleQFE.dll"&lt;br /&gt;&lt;br /&gt;5. Install the Compiled DLL into the GAC using GACUTIL so it can be universally accessed. e.g.&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil" /i .\Code\SampleQFE\bin\Release\SampleQFE.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;br /&gt;Hopefully this is enough to get someone else out there through the intial hurdles. Incidentally I've made the SampleQFE available here for download.&lt;br /&gt;&lt;br /&gt;Now to call from Log Parser run the following command :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"C:\Program Files\Log Parser 2.2\LogParser.exe" "Select * From ." -i:COM -o:DataGrid -iProgId:Gluegood.LogParser.SampleQFE -iCOMParams:ExtendedFields&amp;eq;ON -e:10&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/t0xz9v3yae"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB.NET source is included in download.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-7748349716628329468?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/7748349716628329468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=7748349716628329468&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/7748349716628329468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/7748349716628329468'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/03/freeware-logparsersampleqfe.html' title='Freeware - LogParser.SampleQFE'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-2688673777529177475</id><published>2008-01-31T23:16:00.001+11:00</published><updated>2008-02-01T00:23:26.545+11:00</updated><title type='text'>Advice - LogParser</title><content type='html'>I want to start this post by stating that I'm a huge fan of the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07"&gt;Microsoft LogParser&lt;/a&gt; tool. This tool is so useful and if you are dealing with log files, events, and/or file systems it is an absolute must have in your toolkit.&lt;br /&gt;&lt;br /&gt;A great extension to this tool is &lt;a href="http://www.codeplex.com/visuallogparser"&gt;Visual LogParser&lt;/a&gt;. If you like SQL Enterprise Manager (or SQL Query Analyser) then this interface to LogParser is extremely helpful.&lt;br /&gt;&lt;br /&gt;Below are some of my more advanced LogParser techniques that I've collected over time&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;IIS Performance&lt;/strong&gt; - The below query is perfect if you are trying to understand performance at a subfolder level. It will provide the Server, the URL stem, total pages and average time based on only pages that were successful.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set sDate=071107&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cd "C:\Program Files\Log Parser 2.2"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:IISW3C "select EXTRACT_TOKEN(LogFilename,2,'\\') as Server, TO_UPPERCASE(EXTRACT_PREFIX( cs-uri-stem, 1, '/')) AS URL, count(*) As PageTotal, avg(time-taken) as AvgTime From '\\server1\IISLogs\W3SVC1\ex%sDate%*.log', '\\server2\IISLogs\W3SVC1\ex%sDate%*.log' where sc-status = '200' group by EXTRACT_TOKEN(LogFilename,2,'\\'), TO_UPPERCASE(EXTRACT_PREFIX( cs-uri-stem, 1, '/')) order by TO_UPPERCASE(EXTRACT_PREFIX( cs-uri-stem, 1, '/')), EXTRACT_TOKEN(LogFilename,2,'\\')" -o:DATAGRID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;IIS User Usage&lt;/strong&gt; - Using the power of &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx"&gt;PSEXEC&lt;/a&gt; (psexec - I love this tool in that you can execute commands on remote servers without needing to copy and exe to that server) you can create a hosting server that schedules LogParser queries and unloads them to remote servers (the remote servers must have LogParser installed). Below are 2 batch files that allow you to run daily a LogParser query on a remote server and returning the results back to the scheduling server. This is perfect if you are running queries across the WAN.&lt;br /&gt;&lt;br /&gt;Additionally the below batch file uses a Date/Time routine - depending on your IIS Log Files it can be better to query a specific log file using a date (e.g. ex080120.log) than using the LogParser CheckPoint features.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;cd "C:\Program Files\BatchFiles"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;c:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;psexec \\server1 -c -u server1\username -p password&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;"C:\Program Files\BatchFiles\IISUsage\IISUsageDailyUsers.bat"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;Below is the &lt;strong&gt;IISUsageDailyUsers.bat&lt;/strong&gt; file&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REM Set the Date / Time elements&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;For /f "tokens=1-7 delims=:/-, " %%i in ('echo exit^cmd /q /k"prompt $D $T"') do ( &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    For /f "tokens=2-4 delims=/-,() skip=1" %%a in ('echo.^date')do ( &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set %%a=%%i &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set %%b=%%j &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set %%c=%%k &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set hh=%%l &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set min=%%m &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        set ss=%%n &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if %yy%==2008 Set %YearStr=08&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if %yy%==2009 Set %YearStr=09&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cd "C:\Program Files\Log Parser 2.2"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;C:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REM Page Statistics&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:IISW3C "select cs-username as Username, count(*) as ActivityCount INTO '\\ServerScheduling\IISUsage\Output%YearStr%%mm%%dd%.csv' from '\\server1\IISLogs\W3SVC1\ex%YearStr%%mm%%dd%*.log','\\server2\IISLogs\W3SVC1\ex%YearStr%%mm%%dd%*.log' where cs-username IS NOT NULL and c-ip like '10.1.0.%%' group by cs-username order by count(*) desc" -o:CSV&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;WLBS Status&lt;/strong&gt; - Want to know whether both servers are still in the farm? Use this tool to provide NLB Status - done in 2 parts. First a batch file to retrieve the status into a log file, next part is a LogParser query to check.&lt;br /&gt;&lt;br /&gt;Below is &lt;strong&gt;NLBStatus.cmd &lt;/strong&gt;batch file&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;date /t&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;time /t&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;@wlbs query SERVERCLST /passw &lt;password&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;It is called daily with a command like :-&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;call "C:\Program Files\BatchFiles\NLBStatus.cmd" &gt;&gt; "C:\Program Files\BatchFiles\Logs\NLB\NLBStatuslog_%yy%%mm%.log"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;LogParser query :-&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LogParser.exe -i:TEXTLINE "Select text FROM 'c:\Program Files\BatchFiles\Logs\NLB\*.log' WHERE Text LIKE '%converged%'" -o:DATAGRID -iCheckPoint:"C:\NLBCheckpoint.chk"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Get a response with less than the number of servers in the cluster then you know you have something wrong.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Fixed length files&lt;/strong&gt; - In something like Visual LogParser you can view nicely (in Excel style) Fixed Length formatted files. Apply a query against TEXTLINE using SUBSTR to format the fields :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT SUBSTR(Text,1,2) As [Id], SUBSTR(Text,3,10) As [Name] FROM C:\FixedLengthFile.txt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The [..] fieldname syntax allows you to have space in the column names.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;LogParser and Unicode files&lt;/strong&gt; - Something interesting I got caught with is how LogParser deals with CheckPoint files when parsing Unicode files. The solution around this is if using Unicode files to specify the &lt;span style="font-family:courier new;"&gt;iCodePage=-1&lt;/span&gt; paramater. e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;"c:\Program Files\Log Parser 2.2\LogParser.exe" "select EXTRACT_FILENAME(LogFileName), text FROM 'UnicodeFile.log' where text like '%%FINDSOMETHING%%'" -i:TextLine -o:DataGrid -iCheckPoint:"C:\checkpoint.chk" -iCodePage=-1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-2688673777529177475?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/2688673777529177475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=2688673777529177475&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/2688673777529177475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/2688673777529177475'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/01/advice-logparser.html' title='Advice - LogParser'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-1148586506684951313</id><published>2008-01-26T20:51:00.001+11:00</published><updated>2009-05-02T16:34:21.556+10:00</updated><title type='text'>Freeware - PerfCollector</title><content type='html'>PerfCollector is a command line freeware tool (with .NET source) that can monitor performance counters and log values to a text file. It can use either WMI or standard Performance Counters. See a previous &lt;a href="http://gluegood.blogspot.com/2008/01/advice-performance-counters-wmi-and.html"&gt;blog post&lt;/a&gt; on more information about why this tool was developed.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Freeware&lt;/em&gt; - with source included. &lt;/li&gt;&lt;li&gt;&lt;em&gt;Command line driven&lt;/em&gt; - This allows the tool to be scheduled. The PerfCollector tool has no UI. All activity is driven by a config.xml file with errors and logs to text files. Additionally it has a Debug entry in the Config.xml which allows you to see the actions being performed, additionally any errors are dumped into a \Trace\ folder. Program terminates on any exceptions.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Logs performance counter values to text file&lt;/em&gt; - Allows the configuration of Performance Counters and then dumps the values of those counters (only if they have changed) to a log file that can then be parsed using &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&amp;amp;displaylang=en"&gt;LogParser&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Different monitor settings&lt;/em&gt; - Monitors performance counters via either WMI Events or standard Performance Counters.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.box.net/shared/m1oemdjn0i"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB.NET source is included in download.&lt;/p&gt;&lt;p&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy the PerfCollector folder to a location on your harddrive&lt;br /&gt;2. Configure an XML file. See CONFIG.XML for an example&lt;br /&gt;3. Open a command prompt and type 'PerfCollector.exe &lt;xmlconfig.xml&gt;'&lt;br /&gt;4. Select 'E' (capital e) to stop.&lt;br /&gt;&lt;br /&gt;Additionally to run as a Windows Service see the .\InstallAsAService\InstallAsAService.bat batch file which has a script to allow you to install as a service using the SRVANY and INSTSRV resource kit tools (which can be downloaded for free from Microsoft)&lt;br /&gt;*************************************************&lt;/p&gt;&lt;p&gt;Config file structure&lt;/p&gt;&lt;p&gt;&lt;config&gt;config&lt;br /&gt;counters&lt;br /&gt;counter&lt;br /&gt;&lt;counters&gt;... many counter&lt;br /&gt;&lt;/counters&gt;&lt;br /&gt;Below are the attributes of &lt;em&gt;Counters&lt;/em&gt; element&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Timer -&lt;/em&gt; How often the tool should poll the performance counters, or how often WMI should check for changes. Lower values will impact CPU performance. Timer is in milliseconds. e.g. 5000&lt;/li&gt;&lt;li&gt;&lt;em&gt;MonitorType&lt;/em&gt; - Either 'WMI' for WMI monitoring or 'PerfMon' for PerfMon style montioring.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Debug&lt;/em&gt; - Sets level of verbose logging. True for verbose, false for no debugging.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Below are the attributes of the &lt;em&gt;Counter&lt;/em&gt; element&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;CategoryName&lt;/em&gt; - This is the PerfMon Category name of the Performance Counter. &lt;/li&gt;&lt;li&gt;&lt;em&gt;CounterCountName&lt;/em&gt; - This is the Performance Counter that contains a increasing total counter. e.g. TotalExecutedCalls&lt;/li&gt;&lt;li&gt;&lt;em&gt;CounterName&lt;/em&gt; - This is the Performance Counter that contains the value you are interested in. e.g. "Call Time Last"&lt;/li&gt;&lt;li&gt;&lt;em&gt;CategoryWMIName&lt;/em&gt; - This is the WMI Performance Counter Name. Find this using steps in the previous &lt;a href="http://gluegood.blogspot.com/2008/01/advice-performance-counters-wmi-and.html"&gt;post&lt;/a&gt;. e.g. "Win32_PerfRawData_CustomAppWindows_CustomAppWindows" &lt;/li&gt;&lt;li&gt;&lt;em&gt;ThresholdMinimum&lt;/em&gt; - This is the number at which the Counter must pass before it is logged to a text file. e.g. "1500"&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-1148586506684951313?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/1148586506684951313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=1148586506684951313&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1148586506684951313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1148586506684951313'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/01/freeware-perfcollector.html' title='Freeware - PerfCollector'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-7387293612621432535</id><published>2008-01-22T22:47:00.000+11:00</published><updated>2008-02-09T20:26:49.115+11:00</updated><title type='text'>Advice - Performance Counters, WMI and VB.NET</title><content type='html'>&lt;em&gt;Freeware &lt;/em&gt;&lt;em&gt;PerfCollector tool and code&lt;/em&gt;&lt;em&gt; that I wrote allows both Performance Counter and WMI query style querying is available in another &lt;a href="http://gluegood.blogspot.com/2008/01/freeware-perfcollector.html"&gt;post&lt;/a&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Recently I was working on a project that needed to find which business methods were taking the longest. As required in all enterprise handbooks the project had developed a whole bunch of custom performance counters on the business code. It all works perfectly. Dumping out values for the number of times a business method has been called, dumping out the time the last call took, average times, recent average times etc.&lt;br /&gt;&lt;br /&gt;Problem is that whenever I asked someone to help monitoring the business methods performance in a live environment they blindly waved at the performance counters and tell me to use them. How? Having performance counters in your code doesn’t mean anyone knows how to use them.&lt;br /&gt;&lt;br /&gt;Fairly quickly I noticed that Windows PerfMon isn’t going to help. PerfMon logging allows you to choose the counter and then choose the instances (in our case instances are each of the business method names). Two major problems with this approach are a) PerfMon doesn’t dynamically add instances once you have setup logging, so in my case I’m stuffed as new business methods that didn’t exist when I first setup the counter log would never be logged and b) sampling every 1 second collects a huge amount of data and I don’t really want to parse files that have the same performance counter details repeated even though the values are changing – nor the room to store all this data.&lt;br /&gt;&lt;br /&gt;Ideally what I’m looking for is IIS style log files for long running business calls. 1 line per long running business method identifying; method name, time and the length of call. I really wanted to catch long running business code and know which method to attack.&lt;br /&gt;&lt;br /&gt;To solve this I knew I’d need to write code (couldn’t find much on the Internet). I looked at using VB.NET to access the System.Diagnostics.PerformanceCounter objects. I wrote code to log out the value of counters that changed (that met a threshold I set) and to re-enumerate all the instances to look for new counters. This gave me a trace on the business methods. Logging out performance counters in Visual Baisc dotNet looks like :-&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim myCounter As System.Diagnostics.PerformanceCounter = New System.Diagnostics.PerformanceCounter&lt;br /&gt;myCounter.CategoryName = “Process”&lt;br /&gt;myCounter.InstanceName = “lsass”&lt;br /&gt;myCounter.CounterName = “% User Time”&lt;br /&gt;Dim lValue As Long = CLng(myCounter.RawValue)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I then realised that as the number of instances (business methods in my case) increased then the load on the server will increase (from my tool enumerating), tool thus defeating its purpose of finding long running queries. Maybe there is a simple way to capture performance counters that are changing? I remembered that WMI exposed performance counters. With further research I conducted I found that WMI can provide callbacks to code when a query you register in WMI finds a record(s).&lt;br /&gt;&lt;br /&gt;WMI must be one of the most complex pieces of Microsoft technology I’ve worked with. E.g. root\cimv2 – huh? Why cim? why v2? Then if you want to look at instances you need to run wbemtest. Not wmitest? I’d love to write a dummies guide to WMI, but I suspect it just wouldn’t fly as fairly quickly it would turn into complex reference material. Below is a brain dump of what I’ve found in my 3 days of research – starting point only and I’m sure I’ve made some silly assumptions, but if it can help any of you let me know.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What can I do with WMI&lt;/strong&gt; - WMI is available on newer Microsoft operating systems (W2K, WXP, W2K3 etc) and it allows you to a) interrogate a system configuration e.g. Disk, Processor, Memory etc b) interrogate all performance counters c) files on a file system and d) has differencing facilities so you can know when something is added, modified or deleted (and I’m sure many more if you can delve its depths)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How can I look at WMI stuff, specifically Performance Counters&lt;/strong&gt; – Simple, follow these 9 simple steps ;-). Goto &lt;strong&gt;Start&lt;/strong&gt;-&gt;&lt;strong&gt;Run&lt;/strong&gt; and then type &lt;strong&gt;wbemtest&lt;/strong&gt;. Next select &lt;strong&gt;Connect…&lt;/strong&gt; and type in the top textbox (un-labled) &lt;strong&gt;root\cimv2&lt;/strong&gt;. Select &lt;strong&gt;Connect&lt;/strong&gt;. Now select &lt;strong&gt;Enum Classes…&lt;/strong&gt; type &lt;strong&gt;win32_perfrawdata&lt;/strong&gt; then select &lt;strong&gt;Ok&lt;/strong&gt;. Now select the specific object (aka Performance Object), we’ll select &lt;strong&gt;Win32_PerfRawData_PerfProc_Process&lt;/strong&gt;. From here you have 2 choices.&lt;br /&gt;a) If you want to look at counters then in the properties list (the 2nd listbox) scroll down to the actual counters.&lt;br /&gt;b) Or to view a value of a counter select &lt;strong&gt;Instances&lt;/strong&gt; to view instances and then double click on an instance to view what counters are available and then select the counter to view the value.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My custom performance counter doesn’t exist&lt;/strong&gt; – I’m sure there is a more technical reason, but use &lt;strong&gt;Start&lt;/strong&gt;-&gt;&lt;strong&gt;Run&lt;/strong&gt; and then type &lt;strong&gt;wmiadap.exe /f&lt;/strong&gt;. Reboot and hopefully all is good. Reboot is definitely required as before a reboot you may be able to see the performance counters in wbemtest, but you won’t get instances created and thus no values.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How can I read performance counters in code&lt;/strong&gt; – Few ways, but for my purpose I want to know when a counter changes. Firstly you need a decent WMI query like the one below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT&lt;br /&gt;*&lt;br /&gt;FROM __InstanceModificationEvent&lt;br /&gt;WITHIN 1&lt;br /&gt;WHERE&lt;br /&gt;TargetInstance ISA 'Win32_PerfRawData_CustomCounter_CustomCounter'&lt;br /&gt;AND TargetInstance.Count &gt; PreviousInstance.Count&lt;br /&gt;AND NOT TargetInstance.Name = '_Total'&lt;br /&gt;AND TargetInstance.LastTime &gt; 1500&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;strong&gt;__InstanceModificationEvent&lt;/strong&gt; part of this query is a special in-memory table that stores changes from all WMI events. The Performance Counters luckily are part of this differencing. The &lt;strong&gt;WHERE&lt;/strong&gt; clause allow you to narrow down exactly what change you want to know about. The &lt;strong&gt;WITHIN&lt;/strong&gt; clause is how often sampling occurs (1 second in this case). So what happens if 2 or more ‘changes’ happen in the WITHIN time. Well you get only 1 – I suspect the last one. Either poll more frequently (e.g 0.5. The lower this number the more stress you place on your PC), or ask Microsoft to support ‘&lt;strong&gt;GROUP WITHIN’&lt;/strong&gt; and aggregate Events – this isn’t supported. You also need to use code like this in VB.NET&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim wqlQuery As String = GenerateWMIQuery()&lt;br /&gt;' Setup WMI Query and Watcher&lt;br /&gt;Dim query As System.Management.WqlEventQuery = New System.Management.WqlEventQuery(wqlQuery)&lt;br /&gt;Dim mWatcher As System.Management.ManagementEventWatcher = New System.Management.ManagementEventWatcher&lt;br /&gt;mWatcher.Query = query&lt;br /&gt;&lt;br /&gt;' Set up a listener for events&lt;br /&gt;AddHandler mWatcher.EventArrived, AddressOf WMIEventRaised&lt;br /&gt;' Start listening&lt;br /&gt;mWatcher.Start()&lt;br /&gt;Do&lt;br /&gt;' Loop every 10 seconds.&lt;br /&gt;System.Threading.Thread.Sleep(10000)&lt;br /&gt;Loop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then catch via&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Shared Sub WMIEventRaised(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs)&lt;br /&gt;&lt;br /&gt;Dim ev As System.Management.ManagementBaseObject = e.NewEvent&lt;br /&gt;Dim lValue As Long = CType(ev("TargetInstance"), System.Management.ManagementBaseObject)("PercentUserTime")&lt;br /&gt;Dim sInstance As String = CType(ev("TargetInstance"), System.Management.ManagementBaseObject)("Name")&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;How often should I sample and what is the effect on performance&lt;/strong&gt; – No idea. Seriously depends on your hardware. My suggestion is make the WMI query work for you. Ensure that you are only querying for exactly what you need, then you should be able to query every 5 seconds to pick up the event you need. Sure you might miss something, but if performance is so bad you’ll catch it again. I’m querying every 5 seconds and the WMI performance looks fine as does the .NET code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://gluegood.blogspot.com/2008/01/freeware-perfcollector.html"&gt;PerfCollector tool and code&lt;/a&gt; that I wrote allows both Performance Counter and WMI query style querying.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-7387293612621432535?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/7387293612621432535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=7387293612621432535&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/7387293612621432535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/7387293612621432535'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2008/01/advice-performance-counters-wmi-and.html' title='Advice - Performance Counters, WMI and VB.NET'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-6247603086494364404</id><published>2007-11-18T16:16:00.001+11:00</published><updated>2009-05-02T16:36:16.461+10:00</updated><title type='text'>Freeware - SharePointUpload</title><content type='html'>SharePoint Upload is a command line freeware tool (with .NET source) that can extract e-mails from PST, Public Folders, and Exchange Mailboxes and place on a file system in MSG format (using Redemption). Additionally it can extract Visual Source Safe (VSS) documents, SharePoint Lists (extracted to HTML) and QualityCentre Test Cases (Extracted to HTML), The extracted files are compatible to SharePoint naming conventions. Used with SharePoint this tool can create a &lt;a href="http://gluegood.blogspot.com/2007/11/advice-sdlc-content-search.html"&gt;SDLC Search tool&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note: Although the tool was designed for SharePoint's naming restrictions, the tool can be used to extract all the above to a normal folder (e.g. C:\Temp).&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Windows Sharepoint Server (WSS) v3.0 has a feature in that you can copy files directly to it using standard UNC paths. e.g. if your SharePoint document library path is http://sharepoint.mydomain/SDLCSearch/ documents/RequirementDocuments/AllItems.aspx then you can upload documents directly by copying them into &lt;span style="font-family:courier new;"&gt;\\sharepoint.mydomain\SDLCSearch\ documents\RequirementDocuments&lt;/span&gt;. To do this you must have the 'WebClient' service started from the PC which you are initiating the request.&lt;br /&gt;&lt;br /&gt;Below are some examples of SDLC data you want to index and how this could be copied to a Sharepoint site for indexing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Visual Source Safe&lt;/strong&gt; - Using VSS automation you can conduct a 'GetLatest' direct into the WSS Document Library UNC path. An advantage of this technique is that VSS only copies over files that have changed.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;E-mails&lt;/strong&gt; - Using the &lt;a href="http://www.dimastr.com/redemption/"&gt;Redemption&lt;/a&gt; Data Objects (RDO) you can extract e-mails from PST, Public Folders and Exchange Mailboxes into MSG, RTF or HTML format, these can be copied directly into the WSS Document Library.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Quality Centre&lt;/strong&gt; -&lt;strong&gt; &lt;/strong&gt;Test Cases can be extracted as a single HTML document via a report, however for indexing purposes it is much more useful to have each test case as its own document. Using HTML parsing over the single Test Case HTML extract you can split the single HTML report into each Test Case.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Windows Sharepoint Lists /Wikis&lt;/strong&gt; - Lists and Wikis on other sites that need to be included in indexing need to be pulled into the SDLC Searching site. Using WSS List Web Services you can run a query and extract each list item into seperate documents HTML documents.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The SharepointUpload tool that is available from Gluegood can effectively do all of the above and has the following features :-&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;&lt;strong&gt;Freeware - with source included.&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Command line driven -&lt;/em&gt; This allows the tool to be scheduled. The SharepointUpload tool has no UI. All activity is driven by a config.xml file with errors and logs to text files. Additionall has a Debug entry in the Config.xml which allows you to see the actions being performed, additionally any errors are dumped into a \Trace\ folder. Program terminates on any exceptions.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Honours WSS invalid file and path name conventions&lt;/em&gt; - See &lt;a href="http://blogs.msdn.com/joelo/archive/2007/06/27/file-name-length-size-and-invalid-character-restrictions-and-recommendations.aspx"&gt;here&lt;/a&gt; for a more detailed list. Anything it doesn't like it replaces with '_' underscore, or trims to required length.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Supports full reloads -&lt;/em&gt; sometimes you want to wipe all the content you previously uploaded. Setting a flag in the config.xml will do this by running the command cmd /c del /q /f /s "&amp;lt;SharepointUploadPath&amp;gt;"&lt;/li&gt;&lt;li&gt;&lt;em&gt;Has a 'High Water Mark' concept&lt;/em&gt; - so that if you have already extracted a file it doesn't re-extract. Used in EMAIL by only extracting those e-mails that have a 'SentOn' date greater than or equal to the 'High Water Mark' date. Used in WSSList extract by only extracting those list items that have a 'Modified By' date greater than or equal to the 'High Water Mark' date. This is reset after a successful run in the Config.xml file(except if you manually set this date to '2000-Jan-01' - this allows for re-runs, but not removing old content using the Full Reload feature) &lt;/li&gt;&lt;li&gt;&lt;em&gt;Has matching for e-mails&lt;/em&gt; - E-mail is a bit of a monster if extracting to file names. Not only do you have to worry about the filename, but you need to work out if you have a new e-mail, or an e-mail you have already extracted. e.g. in SharepointUpload it appends _1 for the 1st duplicate found and _2 for the 2nd duplicate, and so on. If you are re-running the program and it tries to write to the same filename, before it overwrites it looks at the Subject and the SentOn Date/Time to check if they are the same - If they are then overwrite existing, else create a new filename looking for the next one available.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Regular Expression filtering&lt;/em&gt; - Available on VSS (file and folder paths), and E-mails (folder restriction only)&lt;/li&gt;&lt;li&gt;&lt;em&gt;Automatic subfolder generation -&lt;/em&gt; To ensure that folders don't become full of content and become unusable in WSS each extract will create subfolders (except VSS) based on hard-coded settings. e.g. E-mail will great a subfolder based on the month and year (e.g. YYYYMM), WSSLIST and QC will create based on every 10,000 Ids. e.g. folder for 10000 and a folder for 20000.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.box.net/shared/dq4aeeah7y"&gt;Download&lt;/a&gt;&lt;/strong&gt;&lt;strong&gt;.&lt;/strong&gt; VB.NET source is included in download.&lt;/p&gt;&lt;p&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy and Unzip the SharepointUpload.zip archive to a folder on your harddrive. Keep both \Trace and \Log folders.&lt;br /&gt;2. For Visual Source Safe (VSS) functionality if VSS 6.0 isn’t installed on the PC that you’ll be running SharePointUpload then copy the Visual Source Safe automation dlls SSUS.dll and SSAPI.DLL to your VSSMonitor folder. Register SSAPI.DLL.&lt;br /&gt;3. For e-mail (EMAIL) functionality install the Developer Version of Redemption (tested against v4.4) - &lt;a href="http://www.dimastr.com/redemption/download.htm"&gt;download and install&lt;/a&gt; as per directions from the site. Note: Ensure that if Outlook isn't installed on the PC that you either install Outlook or install the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e17e7f31-079a-43a9-bff2-0a110307611e&amp;amp;DisplayLang=en"&gt;ExchangeMapiCdo.exe&lt;/a&gt; which is a dependency of the Redemption component.&lt;br /&gt;4. Configure the config.xml file which your VSS, EMAIL, WSSLIST, WSSWIKI, QC, and DB settings. Samples are provided in the config.xml file.&lt;br /&gt;5. Launch SharepointUpload with the command line parameter of the config.xml file path. e.g. &lt;span style="font-family:courier new;"&gt;SharepointUpload.exe config.xml&lt;/span&gt; or use the SharepointUpload.bat file which logs the output to a file based on current month and year.&lt;br /&gt;*************************************************&lt;/p&gt;&lt;p&gt;Config file overview&lt;br /&gt;&amp;lt;config&amp;gt;&lt;br /&gt;&amp;lt;patterns&amp;gt;&lt;br /&gt;&amp;lt;pattern&amp;gt;settings&amp;lt;/pattern&amp;gt;&lt;br /&gt;... many patterns&lt;br /&gt;&amp;lt;/patterns&amp;gt;&lt;br /&gt;&amp;lt;/config&amp;gt;&lt;/p&gt;&lt;p&gt;Below are attributes common to all Patterns :-&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Name&lt;/em&gt; - Name of the pattern. e.g. "All Documents from VSS"&lt;/li&gt;&lt;li&gt;&lt;em&gt;SharepointDestination&lt;/em&gt; - Destination UNC path. The SharePoint path where documents should be uploaded. &lt;/li&gt;&lt;li&gt;&lt;em&gt;HighWaterMark -&lt;/em&gt; Sets the last date that the Pattern was run and provides filtering for next run against EMAIL and WSSLIST types.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Debug -&lt;/em&gt; Sets level of verbose logging. True for verbose, false for totals only&lt;/li&gt;&lt;li&gt;&lt;em&gt;PatternType&lt;/em&gt; - Type of the pattern. See below list and additional parameters per type.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Each Pattern is based on PatternType&lt;/p&gt;&lt;p&gt;&lt;em&gt;VSS&lt;br /&gt;Visual Source Safe extract using Get Latest automation.&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;SourcePath&lt;/em&gt; - location of VSS INI file&lt;/li&gt;&lt;li&gt;&lt;em&gt;Username&lt;/em&gt; - Username for VSS&lt;/li&gt;&lt;li&gt;&lt;em&gt;Password&lt;/em&gt; - Password for VSS&lt;/li&gt;&lt;li&gt;&lt;em&gt;PathTopLevel&lt;/em&gt; - Location to commence searching in the tree.&lt;/li&gt;&lt;li&gt;&lt;em&gt;RegExFilter&lt;/em&gt; - Restriction on what to extract based on folder and filename. Blank is all.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;WSSLIST&lt;/em&gt; (Windows SharePoint Server List)&lt;br /&gt;&lt;em&gt;Extracts each list item to a simple HTML document. The name of the document is in the format of &amp;lt;ID&amp;gt; - &amp;lt;Title&amp;gt;.htm. Special OWS fields are excluded.&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;SourcePath&lt;/em&gt; - location of URL to list. e.g. http://sharepoint.mydomain/site/Lists/NewReq/MyView.aspx.&lt;/li&gt;&lt;li&gt;&lt;em&gt;ListName&lt;/em&gt; - Name of the List. Use either name - "New Requirements" or GUID. See &lt;a href="http://cisa.ca/blogs/medhat/Lists/Posts/Post.aspx?ID=8"&gt;here&lt;/a&gt; to find the GUID of the list. &lt;/li&gt;&lt;li&gt;&lt;em&gt;ViewGUID&lt;/em&gt; - GUID of the view to use. See &lt;a href="http://cisa.ca/blogs/medhat/Lists/Posts/Post.aspx?ID=8"&gt;here&lt;/a&gt; to find the View GUID. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;WSSWIKI (Windows SharePoint Server List)&lt;br /&gt;Extracts each Wiki item to a simple HTML document. The name of the document is in the format of &amp;lt;ID&amp;gt; - &amp;lt;Title&amp;gt;.htm. Special OWS fields are excluded.&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;SourcePath&lt;/em&gt; - location of URL to AllPages view of the Wiki. e.g. &lt;a href="http://sharepoint.mydomain/site/Wiki/Forms/AllPages.aspx"&gt;http://sharepoint.mydomain/site/Wiki/Forms/AllPages.aspx&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;em&gt;ListName&lt;/em&gt; - Name of the List. Use either name - "Wiki Pages" or GUID. See &lt;a href="http://cisa.ca/blogs/medhat/Lists/Posts/Post.aspx?ID=8"&gt;here&lt;/a&gt; to find the GUID of the list.&lt;/li&gt;&lt;li&gt;&lt;em&gt;ViewGUID&lt;/em&gt; - GUID of the view to use. See &lt;a href="http://cisa.ca/blogs/medhat/Lists/Posts/Post.aspx?ID=8"&gt;here&lt;/a&gt; to find the View GUID. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;EMAIL&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Extracts each e-mail (PST, Public Folder, or Exchange Mailbox) as MSG. The name of the e-mail is in the format of &amp;lt;subject&amp;gt;_&amp;lt;version&amp;gt;.msg.&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;SourcePath&lt;/em&gt; - PST file path or Public Folder path (must start with \\Public Folders\..), or Exchange Mailbox Name&lt;/li&gt;&lt;li&gt;&lt;em&gt;Username&lt;/em&gt; - ExchangeMailboxName, need a base name&lt;/li&gt;&lt;li&gt;&lt;em&gt;RegExFilter&lt;/em&gt; - Matching of folder names. e.g. 2007 will extract for e-mails in the 2007 folder and subfolders. Blank is all.&lt;/li&gt;&lt;li&gt;&lt;em&gt;ExchangeServer&lt;/em&gt; - Location of the ExchangeServer&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;QC&lt;br /&gt;Extracts each QualityCentre test case as HTML. The name of the QC Test case is in the format of TestCase &amp;lt;TestCaseIdt&amp;gt; - &amp;lt;TestCaseTitle&amp;gt;.htm. Note: This should work for QualityCentre v9.0, however the extract isn't that intelligent and the HTML parsing may not work for your instance of QualityCentre.&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SourcePath - Path to QualityCentre TestCase report.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;DB&lt;br /&gt;&lt;em&gt;I'm not even going to attempt to document this, read the code and suit it to your own purpose. Uses DataSets, not DataReaders to improve locking contention.&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.&lt;br /&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-6247603086494364404?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/6247603086494364404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=6247603086494364404&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6247603086494364404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6247603086494364404'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/freeware-sharepointupload.html' title='Freeware - SharePointUpload'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-1346737998255231062</id><published>2007-11-10T16:14:00.001+11:00</published><updated>2008-06-17T20:41:41.274+10:00</updated><title type='text'>Advice - SDLC content search</title><content type='html'>&lt;em&gt;A freeware tool (with VB.NET source) that I wrote is available that can upload the artifacts discussed below. It is available in another &lt;/em&gt;&lt;a href="http://gluegood.blogspot.com/2007/11/freeware-sharepointupload.html"&gt;&lt;em&gt;post&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. e.g. It can upload e-mails from PST, Public Folders, and Exchange Mailboxes and place on a file system in MSG format (using Redemption). Additionally it can extract Visual Source Safe (VSS) documents, SharePoint Lists and Wikis (extracted to HTML) and QualityCentre Test Cases (Extracted to HTML), The extracted files are compatible to SharePoint naming conventions.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I've found that a wide variety of tools get used for Software Development and they are often not searchable as a whole, examples of tools in a single Microsoft Development Enterprise are :-&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Visual Source Safe and/or Team Foundation Server &lt;/em&gt;- Code and document repository and versioning. &lt;/li&gt;&lt;li&gt;&lt;em&gt;SharePoint (WSS 3.0)&lt;/em&gt; - User issues and new requirements log, Wiki for tips and tricks, and document repository for sharing with users. &lt;/li&gt;&lt;li&gt;&lt;em&gt;HP Quality Centre&lt;/em&gt; - Test Cases and Test Plans &lt;/li&gt;&lt;li&gt;&lt;em&gt;E-mails&lt;/em&gt; - for Support communication, project management etc &lt;/li&gt;&lt;li&gt;&lt;em&gt;Development Bug Tracking system&lt;/em&gt; - Often implemented as a custom built database solution, or using TFS. &lt;/li&gt;&lt;li&gt;&lt;em&gt;Online Help&lt;/em&gt; - Where your users are told about everything in the software (sigh...which they demand, but never use!)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I've seen a lot of teams struggle to find anything historical as there are just too many places to look. The dream of bringing all these items together in a single tool isn't that realistic seeing that a single tool which does everything above (and do it well) will cost a fortune - documents, e-mail etc are always going to be outside of most SDLC tools.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Example&lt;/em&gt; - An ongoing Enterprise Development team is still developing several years after the first release. Years have passed and a lot of the original team have moved on and unfortunately with them all previous decisions. Being a professional team everything is well documented, however they have left behind 50,000 artifacts across e-mails, documents, bug tasks, test cases, user issues etc. The team decides that a field needs to be altered, but have no idea when it was introduced or more importantly why. Team members start searching across all repositories, but each tool has its own searching syntax and some systems like e-mail, online help and even source control have either no, or extremely poor quick content searching capabilities out of the box.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br /&gt;Wouldn't it be great, and much simpler if all content could be searched and additionally the search facility provided was quick and powerful enough to choose which areas to search across. Obviously you can go and purchase an Enterprise searching solution with plug-ins to the many systems, but this creates an administrative mess in having to divide up the content for different purposes. &lt;a href="http://files.openomy.com/public/gluegood/SDLCPreview.JPG"&gt;&lt;/p&gt;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;&lt;a href="http://files.openomy.com/public/gluegood/SDLCPreview.JPG"&gt;&lt;p align="center"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 164px; TEXT-ALIGN: center" height="194" alt="" src="http://files.openomy.com/public/gluegood/SDLCPreview.JPG" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;br /&gt;Click picture to view in better detail&lt;/div&gt;&lt;br /&gt;I believe there is a much simplier solution by using the native features in Windows Sharepoint Services (WSS 3.0) which comes standard on Windows 2003. You can create an SDLC content searching facility by exporting the content from the above systems in a HTML, DOC, or MSG format and using SharePoint's indexing facilities to search across the content. Obviously data will be duplicated, but the SharePoint content can be seen as read-only and thus synchronised daily/weekly from the source systems. Disk is relatively cheap and most of the content here is small, however numerous.&lt;br /&gt;&lt;br /&gt;There are 2 parts to this solution 1) the Searching Portal which the SharePoint site with a SharePoint Web Part and 2) a &lt;a href="http://gluegood.blogspot.com/2007/11/freeware-sharepointupload.html"&gt;tool to extract and load the content into SharePoint&lt;/a&gt;. Point 2 will be explained in a &lt;a href="http://gluegood.blogspot.com/2007/11/freeware-sharepointupload.html"&gt;future post &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;How the SDLC Content searching portal works&lt;br /&gt;&lt;/strong&gt;WSS 3.0 provides a search page to conduct searching over content. It is in the format of http://&amp;lt;siteurl&amp;gt;/_layouts/searchresults.aspx?k=&amp;lt;KEYWORDS&amp;gt;&amp;amp;u=&amp;lt;SEARCHSUBSITE&amp;gt;&lt;br /&gt;The query string allows for standard search test and additionally the entry of search properties. e.g. instead of just '&lt;em&gt;k=Functional Specification&lt;/em&gt;' you can add the syntax '&lt;em&gt;k=FileExtension:"DOC" Functional Specification&lt;/em&gt;'. Some useful search properties I've found in my travels for WSS 3.0&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Title - This is the document title, extracted from the document meta data in Office documents, or from the &amp;lt;title&amp;gt; tag in HTML documents. &lt;/li&gt;&lt;li&gt;FileName - This is the document filename. &lt;/li&gt;&lt;li&gt;Size - This is the document size &lt;/li&gt;&lt;li&gt;Write - This is the date the file was last written to. &lt;/li&gt;&lt;li&gt;Author - This is the document author &lt;/li&gt;&lt;li&gt;FileExtension - This is extension of the documents. e.g. FileExtension:xls &lt;/li&gt;&lt;li&gt;VPath - The virtual path to the item. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The last Property is the one that allows us to restrict to certain content areas. These properties get used by entering +&amp;lt;property&amp;gt;:&amp;lt;value&amp;gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Steps&lt;/strong&gt;&lt;br /&gt;1. IFilters need to be installed on the Sharepoint server to scan the content uploaded from the various systems. e.g. if you have PDFs you'll need to install a PDF IFilter. For a long time a Microsoft MSG IFilter was missing for some time, however this is now available (&lt;a href="http://blog.gavin-adams.com/2007/10/09/enabling-the-inbuilt-msg-ifilter-on-sharepoint-even-64bit/"&gt;http://blog.gavin-adams.com/2007/10/09/enabling-the-inbuilt-msg-ifilter-on-sharepoint-even-64bit/&lt;/a&gt;)&lt;br /&gt;2. On a SharePoint site create a Document Libraries for each of the content you plan to extract. These provide a container for content and using 'VPATH' property field provide a way to differentiate content.&lt;br /&gt;3. Add to the SharePoint site a 'Form Web Part' and select Source Editor.&lt;br /&gt;4. Download the &lt;a href="http://files.openomy.com/public/gluegood/WebPartSource.txt"&gt;&lt;strong&gt;code&lt;/strong&gt;&lt;/a&gt; and insert into the Source Editor.&lt;br /&gt;&lt;br /&gt;This code is using check boxes to create vpath entries that are fed into the SharePoint search. Sections have been re-produced below - you need to replace the red code below with your own Sharepoint URL and the green code with your own document libraries, descriptions and code.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;a href="http://files.openomy.com/public/gluegood/SDLCSearchCode.JPG"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://files.openomy.com/public/gluegood/SDLCSearchCode.JPG" border="0" /&gt;&lt;/a&gt;Click picture to view in better detail&lt;/p&gt;&lt;p&gt;&lt;br /&gt;5. Optionally I suggest adding a Content Editor Web Part with the following Content to help users :-&lt;/p&gt;&lt;p&gt;&lt;em&gt;Use the Search facility above to search for documents and/or e-mails and/or SDLC artifacts. Enter search text and restrict by specific areas. Selecting no areas will search all areas. Additionally search via document properties. Syntax : e.g. Title:"Load Balancing"Properties available :&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Title - This is the document title, extracted from the document meta data in Office documents, or from the &amp;lt;title&amp;gt; tag in markup documents.&lt;br /&gt;FileName - This is the document filename.&lt;br /&gt;Size - This is the document size&lt;br /&gt;Write - This is the date the file was last written to.&lt;br /&gt;Author - This is the document author&lt;br /&gt;FileExtension - This is extension of the documents. e.g. FileExtension:xls&lt;/em&gt;&lt;/p&gt;&lt;p&gt;That's it!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-1346737998255231062?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/1346737998255231062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=1346737998255231062&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1346737998255231062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1346737998255231062'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/advice-sdlc-content-search.html' title='Advice - SDLC content search'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-5935460837698562964</id><published>2007-11-05T13:35:00.002+11:00</published><updated>2009-05-02T16:45:31.533+10:00</updated><title type='text'>Freeware - VSSMonitor</title><content type='html'>A VBScript utility that continually monitors a VSS database and sends emails when certain patterns are detected.&lt;br /&gt;&lt;br /&gt;This is an extension on the free utility written by Doug Schmidt called SSMonitor. You can view the original functionality at the CodeProject web site:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeproject.com/vbscript/ssmonitor.asp"&gt;http://www.codeproject.com/vbscript/ssmonitor.asp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thanks Doug for a great utility.&lt;br /&gt;&lt;br /&gt;From the original functionality it has been extended to provide the following :-&lt;br /&gt;1. Highwater marker (basically a file offset) to ensure that if the PC is rebooted the ‘cached’ events aren’t lost. This is only moved along when there are no events cached.&lt;br /&gt;2. Checked-out status – using VSS automation conducting a check of files that have been Checked Out for an configurable number of days.&lt;br /&gt;3. Supporting day or the week notifications – e.g. not just every 15 mins, or daily at 5:00pm, but Friday 5:00pm.&lt;br /&gt;4. Regular Expression check on username – same as the filename expression check, but on usernames.&lt;br /&gt;&lt;br /&gt;I’ve used the new features above for the following checks&lt;br /&gt;- before the weekend notifying all developers of code checked out.&lt;br /&gt;- notified when a particular person checks in code. Perfect for checking what new starters or recently terminated staff may be up to.&lt;br /&gt;- tracking for interested parties when only a particular person makes a change.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://www.box.net/shared/v460pva9cj"&gt;Download&lt;/a&gt;&lt;/strong&gt;. VBScript source is included in download.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy and Unzip the VSSMonitor.zip archive to a folder on your harddrive&lt;br /&gt;2. As per SSMonitor installation obtain a copy of SMTP.ocx and copy to your harddrive - http://www.ostrosoft.com/smtp_component.asp. Additionally register the component.&lt;br /&gt;3. For ‘Check Out’ functionality if VSS 6.0 isn’t installed on the PC that you’ll be running VSSMonitor then copy the Visual Source Safe automation dlls SSUS.dll and SSAPI.DLL to your VSSMonitor folder. Register SSAPI.DLL.&lt;br /&gt;4. Configure the config.xml file which your SMTP, VSS and Pattern events. A sample file is included in the zip.&lt;br /&gt;5. Run the batch file VSSMonitor.cmd which will commence the monitoring - a trace file produced in the Log folder.&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;Additional Config.xml values beyond the SSMonitor standard :-&lt;br /&gt;** Database **&lt;br /&gt;&lt;em&gt;VSSINIPath&lt;/em&gt; - location to the srcsafe.ini file&lt;br /&gt;&lt;em&gt;VSSUsername&lt;/em&gt; - VSS Username&lt;br /&gt;&lt;em&gt;VSSPassword&lt;/em&gt; - VSS Password&lt;br /&gt;&lt;br /&gt;** Pattern **&lt;br /&gt;&lt;em&gt;fixedReportTime&lt;/em&gt; – supports ‘ddd hh:mm’ format. E.g. ‘Fri 8:00 AM’ or ‘8:00 AM’&lt;br /&gt;&lt;br /&gt;&lt;em&gt;userFilter&lt;/em&gt; – Regular Expression of usernames for filtering&lt;br /&gt;&lt;br /&gt;&lt;em&gt;eventFilter&lt;/em&gt; – new type being ‘Checked Out’&lt;br /&gt;&lt;em&gt;checkedOutDays&lt;/em&gt; – Number of days which a file must be checked out for to trigger being included in the Checked Out notification&lt;br /&gt;&lt;em&gt;pathTopLevel&lt;/em&gt; - Top level(s) of VSS that the CheckOut pattern should commence searching from, reduces query time if more specific, comma seperated for more than 1 path&lt;br /&gt;&lt;br /&gt;&lt;em&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it.&lt;br /&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-5935460837698562964?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/5935460837698562964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=5935460837698562964&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/5935460837698562964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/5935460837698562964'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/freeware-vssmonitor.html' title='Freeware - VSSMonitor'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-3958524961396029915</id><published>2007-11-05T08:26:00.002+11:00</published><updated>2009-05-02T16:35:14.533+10:00</updated><title type='text'>Freeware - Nockylock</title><content type='html'>Nockylock is a freeware program that stops a 2 year old from harming the computer by locking the keyboard and locking the mouse. This software was inspired by my 2 year old who enjoys watching 'The Wiggles'. Unfortunately she also enjoys banging the keyboard and clicking the mouse in the process. This simple utility allows the parent to lock the computer from all input (BlockInput API) and then using ALT-CTRL-DEL select Cancel and then stop the utility&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/l0nfe68zbv"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB6 Source is included in download.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy the Nockylock folder to a location on your harddrive&lt;br /&gt;2. Run the program Nockylock.exe&lt;br /&gt;3. Select 'Start' to commence the countdown to the locking of the PC input. Note: Nockylock will continue to lock the input even if it has lost focus on the desktop. e.g. you can full screen a media player.&lt;br /&gt;4. Once locked select ALT-CTRL-DEL and then select Cancel from the dialog&lt;br /&gt;5. Navigate to the Nockylock window and select 'Stop'&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;This application has been tested under various Windows versions - tested under Windows XP, Windows 2000 and Windows 2003.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.&lt;br /&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-3958524961396029915?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/3958524961396029915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=3958524961396029915&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/3958524961396029915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/3958524961396029915'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/software-nockylock.html' title='Freeware - Nockylock'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-6448551404404076546</id><published>2007-11-05T08:19:00.002+11:00</published><updated>2009-05-02T16:34:50.363+10:00</updated><title type='text'>Freeware - Firstlines</title><content type='html'>FirstLines is a freeware program inspired by a Penguin Classics screensaver that was released in 2005. Unfortunately it only showed 3 quotes, so I decided to write my own.&lt;br /&gt;&lt;br /&gt;Using this application you can configure the quote file to use, font details, and the colour. Follow the format in the sample quote file (FirstLines.txt) to add new quotes. There is also provided an extended quotes file (FirstLinesExtended.txt) that provides a lot more quotes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.box.net/shared/yyv5gx08oe"&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/a&gt;. VB6 source is included in download.&lt;br /&gt;&lt;br /&gt;*************************************************&lt;br /&gt;To install:&lt;br /&gt;1. Copy the FirstLines. folder to a location on your harddrive&lt;br /&gt;2. Right-Click on the FirstLines.scr after the copy and select Install&lt;br /&gt;3. Configure the settings and then preview.&lt;br /&gt;*************************************************&lt;br /&gt;&lt;br /&gt;Quotes obtained from http://www.people.cornell.edu/pages/jad22/index.html#Categories&lt;br /&gt;&lt;br /&gt;This application has been tested under various Windows versions - tested under Windows XP, Windows 2000 and Windows 2003.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;** Legal **&lt;br /&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.&lt;br /&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-6448551404404076546?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/6448551404404076546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=6448551404404076546&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6448551404404076546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/6448551404404076546'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/software-firstlines.html' title='Freeware - Firstlines'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354979324932603051.post-1906384619953794627</id><published>2007-11-05T07:43:00.002+11:00</published><updated>2010-09-26T22:14:27.545+10:00</updated><title type='text'>About Gluegood</title><content type='html'>Welcome to Gluegood Software&lt;br /&gt;&lt;br /&gt;I specialise in providing advice and building tools that are useful for Enterprises that utilise Microsoft applications.&lt;br /&gt;&lt;br /&gt;My philosophy is that all utilities available on this site should be Licensed under GNU (e.g. Freeware). Having other things in my life I'm unable to offer extensive support.&lt;br /&gt;&lt;br /&gt;By day I'm a Software Development Manager with a passion for functional software.&lt;br /&gt;&lt;br /&gt;Hope you enjoy your time in the site. If you have any comments please e-mail me using the e-mail address – gluegood at gmail dot com&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6354979324932603051-1906384619953794627?l=gluegood.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gluegood.blogspot.com/feeds/1906384619953794627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6354979324932603051&amp;postID=1906384619953794627&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1906384619953794627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354979324932603051/posts/default/1906384619953794627'/><link rel='alternate' type='text/html' href='http://gluegood.blogspot.com/2007/11/about-gluegood.html' title='About Gluegood'/><author><name>Gluegood Software</name><uri>http://www.blogger.com/profile/18165239762995945438</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
