Jan Schreuder on .Net

.Net code samples, experiences, observations

View my professional profile on LinkedIn

Recent Posts

Tags

News

  • Inappropriate comments will be deleted at my discretion.

    The information and code samples in this weblog is provided "AS IS" without warranty of any kind, either expressed or implied, including but not limited to the merchantability and/or fitness for a particular purpose.

Community

Email Notifications

Tool suppliers

Tools

General

Microsoft

Favorite blogs

Archives

March 2007 - Posts

MSXML 4.0 to be kill bit-ed

While on the subject of XML. I noticed an announcement on the Microsoft XML Team blog that MSXML4 is going to disappear within the next 12 months. It will mean that applications will no longer be able to create MSXML4 documents in the Internet Explorer browser. The team urges everyone to switch to MSXML6 as soon as possible.

The differences between MSXML4 and MSXML6, as well as migration issues, can be viewed here. A summary of the supported versions:

  • MSXML6 – Should be your first choice. This is the MSXML version that will be carried forward. MSXML6 is shipped with Vista and Microsoft is working on getting this in downlevel OS Service Packs.
  • MSXML3 – This has the advantage of having shipped with every supported OS. Microsoft is committed to keeping MSXML3 robust and stable but won’t be adding any functional improvements.
  • MSXML4 – This is in maintenance mode with a very high bar for fixes approaching End of Life.
  • MSXML5 – Exclusively meant for Office. Do not take any dependencies on it.

More information can be found in this post at the Microsoft XML team blog.

Posted: Mar 23 2007, 03:00 PM by Jan Schreuder | with no comments
Filed under: ,
XML Notepad 2007 Update

Exactly one month ago, I blogged about XML Notepad 2007. XML Notepad 2007 is the replacement for the original XML Notepad that was written back in 1998! The XML team released an update to the tool yesterday, which you can download here. A full list of new features and bug fixes can be viewed here.

Try it. Especially the option to view the differrences between two XML documents is really good!

Posted: Mar 23 2007, 02:50 PM by Jan Schreuder | with no comments
Filed under: , ,
How to: Generate source documentation using Sandcastle

I've blogged about Sandcastle a few times already (see these links) in the past year. Sandcastle is the Microsoft solution for generating Help files using the XMl documentation tags in your .Net code. I've decided I needed to post an update on the current status of Sandcastle, because I feel the tool is getting more mature. At present, the March CTP has just been released.

The reason for this new post was the new CTP and the improved Sandcastle Helper by Eric Woodruff. The new CTP contains numerous fixes. A large number of these fixes are related to the Orcas Beta 1 release. Sandcastle now supports building help files based on Orcas projects and correctly references Orcas assemblies.

The Sandcastle Helper is, by my opinion, still one of the better options to create a help file using Sandcastle. At first, the application featured only a Winforms GUI application which strongly resembles the infamous (but now deceased) NDoc application. There is now also a console application which uses the project files that you create using the GUI application. This gives you the option of including it in a postbuild event in your Visual Studio project. The application also helps you add references to GAC assemblies you use in your solution. Sandcastle needs these references so that reflection will help extract information about objects used from these GAC assemblies.

In this post I will try to give you a short introduction for when you want to use Sandcastle and the Sandcastle Helper.

Quickstart

So let's have a quick look in how you can use Sandcastle for generating your documentation. You must first install the CTP and the Sandcastle Helper:

Step 1 - Make sure the project creates an XML document

Now let's assume you have a .Net assembly called ClassLibrary1 which contains the following sample class:

using System;
using System.Collections.Generic;
using System.Text;
 
namespace ClassLibrary1
{
    /// <summary>
    /// A sample class to show something using Sandcastle
    /// </summary>
    public class SampleClass
    {
        private string _propertyValue;
 
        /// <summary>
        /// Gets or sets the property value.
        /// </summary>
        /// <value>The property value.</value>
        public string Property
        {
            get
            {
                return _propertyValue;
            }
            set
            {
                _propertyValue = value;
            }
        }
 
        /// <summary>
        /// Determines whether the property is null.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if property is null; otherwise, <c>false</c>.
        /// </returns>
        public bool IsPropertyNull()
        {
            bool result = false;
 
            if (this.Property == null)
            {
                result = true;
            }
            return result;
        }
 
        /// <summary>
        /// Determines whether the property is null.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if property is empty; otherwise, <c>false</c>.
        /// </returns>
        /// <example>
        /// This example shows how you might use this method:
        /// 
        /// <code>
        /// SampleClass sample = new SampleClass();
        /// 
        /// if (sample.IsPropertyEmpty())
        /// {
        ///        Console.WriteLine("The property is empty");
        /// }
        /// else
        /// {
        ///        Console.WriteLine("The property contains value " + sample.Property);
        /// }
        /// </code>
        /// </example>
        public bool IsPropertyEmpty()
        {
 
            bool result = this.IsPropertyNull();
 
            if (!result)
            {
                result = (Property.Trim().Length == 0);
            }
            return result;
        }
    }
}

Never mind rather silly looking code, it's just to demonstrate Sandcastle ;-). I'm assuming everybody knows this, but make sure you check the XML documentation file check box on the Build tab in your project properties window:

Step 2 - Compile the assembly 

Now compile the class library. You should see the ClassLibrary1.XML in the Debug directory.

Step 3 - Run the Sandcastle Help File Builder

Next thing to do is start the Sandcastle Help File Builder. You should see the following window:

Step 4 - Add assemblies to the Sandcastle Help File Builder project 

To create a help file, all you need to do now is click the Add button and select the compiled assembly for the class library. The Assemblies to Document list box should then show the assembly you compiled, and the XML file containing the documentation information that the .Net compiler extracted from your code.

Step 5 - Set additional properties

In the Project properties panel of the application you should change the following properties:

  • Presentation Style. Set this to VS2005
  • SDK Link type. Set this to Index
Step 6 - Generate the help file

Last step is to click on the generate button in the toolbar:

The application will then run all Sandcastle tools in the correct order to generate a help file.

Step 7 - View generated help file

When the help file is compiled, you can view the result by selecting View Help File from the Documentation menu. The documentation for the method IsPropertyEmpty in the above sample class will look like this:

Useful T-SQL Date functions

I was looking for a quick way to calculate the last day of the month in T-SQL and bumped into an article written by Gregory A. Larsen on DatabaseJournal.com. The article describes a number of T-SQL methods to calculate different date and time values.

I used information from that article to create a few user defined functions which I now use in my stored procedures. You can find the code for these functions in this post. Please link to the full article by Gregory A. Larsen for a full explanation and more date/time calculations.

Midnight for the Current Day

Using the code in the above article, I created a small user defined function that will give me a datetime value with the time set to 00:00:00. It makes it easier to check if a given datetime is on a specific date.

CREATE FUNCTION [dbo].[StripTimeFromDate] (@inputDate DATETIME)
RETURNS DATETIME
BEGIN
 
    RETURN DATEADD(d, DATEDIFF(d, 0, @inputDate), 0)
 
END

First Monday of the Month

I have a stored procedure that checks a number of things in the database. Please forgive me for not going into details here, but some data in these tables needs to be reset on the first Monday of the month. As I'm not allowed to create jobs on the server, I simply added the code to reset the information to the stored procedure. To calculate the first Monday of a month, I use the following user defined function.

CREATE FUNCTION [dbo].[FirstMondayOfMonth] (@inputDate DATETIME)
RETURNS DATETIME
BEGIN
 
    RETURN DATEADD(wk, DATEDIFF(wk, 0, dateadd(dd, 6 - datepart(day, @inputDate), @inputDate)), 0) 
 
END

Last Day of the Month

Another one I now use is a user defined function to calculate the last day of the month. The application I now work on assigns tasks to users that need to be done on the first Monday of the month. When they complete the task, another task is assigned to take place on the last day of the month. The stored procedure that completes the task uses the following user defined function to calculate that date.

CREATE FUNCTION [dbo].[LastDayOfMonth] (@inputDate DATETIME )
RETURNS DATETIME
BEGIN
 
    RETURN dateadd(ms, -3, DATEADD(mm, DATEDIFF(m, 0, @inputDate) + 1, 0))
 
END

 

This weeks embarrasing moment

We all have those, I'm sure of it. Today it was my time to walk away from my computer and hide my face. So what happenend?

I built a windows service for my current assigment. I tested it and it worked so it was time to deploy it to the test server. The solution included a setup project, so I simply compiled the setup and sent it off. To my surprise, I was called to tell me the setup didn't work properly. According to the tester, the files had been installed, but the service did not show in the services window.

I couldn't believe it, so I ran the setup again on my system and checked my services window. Weird, it's there. I uninstalled it and checked it again. It was still there! WTF?!?!?! Time to open the good old dos-prompt and run InstallUtil /u on the service application in my debug folder. And yes, the service was gone. I proceeded in running the setup again, and it didn't appear in my services window.

I then checked the installer class in my service project and found that my installer class was tagged with the [RunInstaller(true)] attribute. I then checked a service class that I knew was installing properly and that class turned out to be tagged with [RunInstallerAttribute(true)]. You'll notice the small but significant difference. And the reason for my shame. Still trying to figure out why the [RunInstaller(true)] didn't raise a compiler error, though.

Lessons learned

  1. Be humble, you can't even trust your own work. Or the compiler...
  2. Make sure the service is uninstalled and doesn't show in the services window before testing the setup.
  3. Run the setup to make sure it installs all necessary files.
  4. Check if the service shows up in the services window.

 

Posted: Mar 02 2007, 04:19 PM by Jan Schreuder | with 1 comment(s)
Filed under: