Archives

Archives / 2007 / February
  • VB.NET Version of Web Service Software Factory now available

    In addition to the 800,000 RSS feeds I subscribe to I also keep an eye on downloads from Microsoft. This is so I don't miss anything that happens to come out and become the new SharePoint or something. However monitoring downloads from Microsoft is like herding cats. They come in spurts and don't make much sense to me.

    For example recently the following downloadables got updates: Guidance Automation Toolkit, Guidance Automation Extensions, and the Web Service Software Factory. What's odd about it is that they were updated in the last day or so, but are still versions from back in June 2006. So what? I'm getting updates because someone edited an entry on a site somewhere. Or is there a real update here or not.

    You think something like this was easy. Notify people when a "new" version is available, not just an update to the page that contains the old version. But then I'm prolly asking too much.

    BTW, the Visual Basic.NET flavor of the Web Service Software Factory (the title of this blog post) is new and available here.

  • A few good men (or women)

    I'm looking for a few good men (or women, but no lizards unless you're that cool one from that Geico commercial). I need a few good experienced intermediate to senior .NET developers in the Calgary area for projects. Short term, long term, or full time, it's flexible but availability needs to be immediate.

    As for qualifications a good, solid working base of .NET 2.0 is required along with good development practices (layered applications, separation of concern, thin UI, that kind of stuff). We use the following tools, technologies, patterns and practices so you need a good knowledge of some (or all) of these:

    • Scrum
    • .NET 2.0
    • Composite Application UI Block (CAB)
    • Enterprise Libraries
    • Smart Client Software Factories (SCSF)
    • Test Driven Development (TDD)
    • Visual Studio Team System
    • Design Patterns/Software Factories
    • Domain Driven Design (DDD)

    If you're qualified, interested, and avaialble and in the Calgary area feel free to email me with a note about yourself (attaching your CV is optional) and we can chat. Thanks!

    This blog entry was brought to you by the letter N, H, L and the number 7.

  • SharePoint Code Camp this Saturday

    Please join Robert Holmes and other presenters at an all day event in Waltham, MA on Saturday, February 24th, from 8:30 to 6:00 PM presenting all aspects of the new SharePoint products, WSS 3.0 and MOSS 2007. The main focus will be on the new aspects of the product line, however we will start with an introduction to Team Services (WSS), and work up from there, and our goal is for anyone present for the whole day will leave with the knowledge of what is possible with the product, and the ability to sit down and get started on a new implementation of a SharePoint solution, or extend an existing one. You can review the schedule to see what specific areas are of interest to you, or else spend the whole day and learn all there is to learn.

    You can find the code and slides here: http://www.sharepointguy.com/SharePointCodeCamp07/default.aspx.

    You can see the content only site, no registration, at: http://www.sharepointguy.com/SharePointCodeCamp07/default.aspx.

    Enjoy!

  • ASP.NET 2.0:1, Bil:0

    I just spent the better part of the evening chasing down the dumbest error I've ever seen. ASP.NET decided to litter my web.config file in a web app I'm setting up with a reference to stdole.dll (not a web dll nor is it anything I reference directly or even need). I finally tracked down someone who came up with a resolution and explanation here.

    Of course I couldn't figure out which assembly that was causing the problem, so I just threw my GAC'd version of stdole.dll into the bin folder of the website. I'm using a few dlls including Enterprise Libraries, but nothing fancy. In any case, if you ever see this crazy message when deploying a website:

    Parser Error Message: Could not load file or assembly 'stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

    You might want to check out the link above. Either a) manually edit the web.config file [which I'm sure I'll forget one of these days during deployment] or b) toss the file into your bin directory or c) hunt down the culprit and set "Specific Version" to false.

    Man, what a @!#!!!%!&! PITA this stupid, stupid, stupid thing is. I'm not sure if I'm peeved at MS for coming up with such a wonderful design, or for me for killing my brain all night over it. Now I feel as foolish as this and this.

    Sigh, I need a hug (or a beer, not sure which).

  • Versioning the Microsoft way... with NAnt

    I was inspired by a recent blog entry by Jeff Atwood here about how Microsoft versions their products and how the build number is significant. I thought it would be good to post a walkthrough of how to build your own versioning system ala Microsoft but using NAnt. I'm sure some budding geek out there could convert this to MSBuild, but you know my love of that tool so NAnt it is.

    First off, NAnt has a great facility for generating that AssemblyInfo.cs file that every project has. It's the asminfo task and basically looks like this:

    <?xml version="1.0"?>
    <project name="Test" default="UpdateAssemblyInfo">
        <target name="UpdateAssemblyInfo">
            <asminfo output="AssemblyInfo.cs" language="CSharp">
                <imports>
                    <import namespace="System.Reflection" />
                    <import namespace="System.Runtime.InteropServices" />
                </imports>
                <attributes>
                    <attribute type="AssemblyTitleAttribute" value="ClassLibrary1" />
                    <attribute type="AssemblyDescriptionAttribute" value="" />
                    <attribute type="AssemblyConfigurationAttribute" value="" />
                    <attribute type="AssemblyCompanyAttribute" value="" />
                    <attribute type="AssemblyProductAttribute" value="ClassLibrary1" />
                    <attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2007" />
                    <attribute type="AssemblyTrademarkAttribute" value="" />
                    <attribute type="AssemblyCultureAttribute" value="" />
     
                    <attribute type="ComVisibleAttribute" value="false" />
     
                    <attribute type="GuidAttribute" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />
     
                    <attribute type="AssemblyVersionAttribute" value="1.0.0.0" />
                    <attribute type="AssemblyFileVersionAttribute" value="1.0.0.0" />
                </attributes>
            </asminfo>
        </target>
    </project>

    This will product a default AssemblyInfo.cs file that looks like this:

    using System.Reflection;
    using System.Runtime.InteropServices;
     
    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated by a tool.
    //     Runtime Version:2.0.50727.42
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
     
    [assembly: AssemblyTitleAttribute("ClassLibrary1")]
    [assembly: AssemblyDescriptionAttribute("")]
    [assembly: AssemblyConfigurationAttribute("")]
    [assembly: AssemblyCompanyAttribute("")]
    [assembly: AssemblyProductAttribute("ClassLibrary1")]
    [assembly: AssemblyCopyrightAttribute("Copyright (c) 2007")]
    [assembly: AssemblyTrademarkAttribute("")]
    [assembly: AssemblyCultureAttribute("")]
    [assembly: ComVisibleAttribute(false)]
    [assembly: GuidAttribute("f98c8021-fbf1-44ff-a484-946152cefdb8")]
    [assembly: AssemblyVersionAttribute("1.0.0.0")]
    [assembly: AssemblyFileVersionAttribute("1.0.0.0")]

    Notice however a few things. First is the Guid. We had to hard code that which might be okay, but lets dig into NAnt scripting by replacing it with a real Guid. NAnt also has the ability to let you write embedded code (C#, VB.NET, etc.) via the <script> task, so let's write a small task to do that. We'll just have it generate a new Guid and set a new custom property in the NAnt script that we'll use in our asminfo task. Create a property in the NAnt script to hold our Guid:

    <property name="project.guid" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />

    Then use that property in our GuidAttribute:

    <attribute type="GuidAttribute" value="${project.guid}" />

    Finally here's the task to generate a Guid via NAnt (make the default UpdateAssemblyInfo task dependent on this one):

    <target name="CreateUniqueGuid">
        <script language="C#">
            <code>
                <![CDATA[
                    public static void ScriptMain(Project project) {
                        project.Properties["project.guid"] = Guid.NewGuid().ToString();
                    }
                ]]>
            </code>
        </script>
    </target>

    Great. We now have a NAnt script that will generate a new version file with a unique Guid everytime. Next we want to tackle the versioning issue.

    As described by Jensen Harris here, the Microsoft Office scheme is pretty simple:

    • Take the year in which a project started. For Office "12", that was 2003.
    • Call January of that year "Month 1."
    • The first two digits of the build number are the number of months since "Month 1."
    • The last two digits are the day of that month.

    Using this we'll need to setup a couple of properties. One is to hold the year the project starts, the other is the build version we want to set:

    <property name="project.year" value="2003" />
    <property name="build.version" value="1.0.0.0" />

    Now we could write a lot of NAnt code as there are functions to manipulate dates, but it's much easier using the <script> task and some C#. Here's the NAnt task to generate the build number using the Microsoft Office approach:

    <target name="GenerateBuildNumber">
        <script language="C#">
            <imports>
                <import name="System.Globalization" />
                <import name="System.Threading" />
            </imports>
            <code>
                <![CDATA[
                    public static void ScriptMain(Project project) {
                        Version version = new Version(project.Properties["build.version"]);
                        int major = version.Major;
                        int minor = version.Minor;
                        int build = version.Build;
                        int revision = version.Revision;
     
                        int startYear = Convert.ToInt32(project.Properties["project.year"]);
                        DateTime start = new DateTime(startYear, 1, 1);
                        Calendar calendar = Thread.CurrentThread.CurrentCulture.Calendar;
                        int months = ((calendar.GetYear(DateTime.Today)
                            - calendar.GetYear(start)) * 12)
                            + calendar.GetMonth(DateTime.Today)
                            - calendar.GetMonth(start);
                        int day = DateTime.Now.Day;
                        build = (months * 100) + day;
     
                        version = new Version(major, minor, build, revision);
                        project.Properties["build.version"] = version.ToString();
                    }
                ]]>
            </code>
        </script>

    We get the version in the NAnt script as a starter (since we're only replacing the build number) and then assign values to it (they're read-only in .NET). Then this is written back out to the property as a string.

    If this is run today (February 17, 2007) it's been 49 months since the start of 2003 and today is the 17th day. So the build number is 4917. 

    Here's the finaly output from this NAnt script:

    using System.Reflection;
    using System.Runtime.InteropServices;
     
    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated by a tool.
    //     Runtime Version:2.0.50727.42
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
     
    [assembly: AssemblyTitleAttribute("ClassLibrary1")]
    [assembly: AssemblyDescriptionAttribute("")]
    [assembly: AssemblyConfigurationAttribute("")]
    [assembly: AssemblyCompanyAttribute("")]
    [assembly: AssemblyProductAttribute("ClassLibrary1")]
    [assembly: AssemblyCopyrightAttribute("Copyright (c) 2007")]
    [assembly: AssemblyTrademarkAttribute("")]
    [assembly: AssemblyCultureAttribute("")]
    [assembly: ComVisibleAttribute(false)]
    [assembly: GuidAttribute("a6e7ff79-63ba-443f-8bc3-0c4b43f43ffe")]
    [assembly: AssemblyVersionAttribute("1.0.4917.0")]
    [assembly: AssemblyFileVersionAttribute("1.0.4917.0")]
     

    And here's the full NAnt script:

        1 <?xml version="1.0"?>
        2 <project name="Test" default="UpdateAssemblyInfo">
        3 
        4     <property name="project.guid" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />
        5     <property name="project.year" value="2003" />
        6     <property name="build.version" value="1.0.0.0" />
        7 
        8     <target name="UpdateAssemblyInfo" depends="CreateUniqueGuid, GenerateBuildNumber">
        9         <asminfo output="AssemblyInfo.cs" language="CSharp">
       10             <imports>
       11                 <import namespace="System.Reflection" />
       12                 <import namespace="System.Runtime.InteropServices" />
       13             </imports>
       14             <attributes>
       15                 <attribute type="AssemblyTitleAttribute" value="ClassLibrary1" />
       16                 <attribute type="AssemblyDescriptionAttribute" value="" />
       17                 <attribute type="AssemblyConfigurationAttribute" value="" />
       18                 <attribute type="AssemblyCompanyAttribute" value="" />
       19                 <attribute type="AssemblyProductAttribute" value="ClassLibrary1" />
       20                 <attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2007" />
       21                 <attribute type="AssemblyTrademarkAttribute" value="" />
       22                 <attribute type="AssemblyCultureAttribute" value="" />
       23 
       24                 <attribute type="ComVisibleAttribute" value="false" />
       25 
       26                 <attribute type="GuidAttribute" value="${project.guid}" />
       27 
       28                 <attribute type="AssemblyVersionAttribute" value="${build.version}" />
       29                 <attribute type="AssemblyFileVersionAttribute" value="${build.version}" />
       30             </attributes>
       31         </asminfo>
       32     </target>
       33 
       34     <target name="CreateUniqueGuid">
       35         <script language="C#">
       36             <code>
       37                 <![CDATA[
       38                     public static void ScriptMain(Project project) {
       39                         project.Properties["project.guid"] = Guid.NewGuid().ToString();
       40                     }
       41                 ]]>
       42             </code>
       43         </script>
       44     </target>
       45 
       46     <target name="GenerateBuildNumber">
       47         <script language="C#">
       48             <imports>
       49                 <import name="System.Globalization" />
       50                 <import name="System.Threading" />
       51             </imports>
       52             <code>
       53                 <![CDATA[
       54                     public static void ScriptMain(Project project) {
       55                         Version version = new Version(project.Properties["build.version"]);
       56                         int major = version.Major;
       57                         int minor = version.Minor;
       58                         int build = version.Build;
       59                         int revision = version.Revision;
       60 
       61                         int startYear = Convert.ToInt32(project.Properties["project.year"]);
       62                         DateTime start = new DateTime(startYear, 1, 1);
       63                         Calendar calendar = Thread.CurrentThread.CurrentCulture.Calendar;
       64                         int months = ((calendar.GetYear(DateTime.Today)
       65                             - calendar.GetYear(start)) * 12)
       66                             + calendar.GetMonth(DateTime.Today)
       67                             - calendar.GetMonth(start);
       68                         int day = DateTime.Now.Day;
       69                         build = (months * 100) + day;
       70 
       71                         version = new Version(major, minor, build, revision);
       72                         project.Properties["build.version"] = version.ToString();
       73                     }
       74                 ]]>
       75             </code>
       76         </script>
       77     </target>
       78 
       79 </project>

    Enjoy!

  • How to drive a developer insane

    Further to my post about the two dozen add-ins I have loading into Visual Studio (wonder what Scott's startup looks like) I have no less than 3 Refactor menus available to me.

    First there's the built-in refactorings from Visual Studio (including an additional one, refactor to resource that I added via the VS PowerToys):

    Refactor menu from Visual Studio

    Next there's ReSharpers Refactor menu that has a million options:

    Refactor menu from ReSharper

    Finally there's Developer Express' Refactor! Pro menu which is context sensitive so the options change based on what element you pick in the Editor (but I'm sure it's got as many as ReSharper or more):

    Refactor menu from Refactor! Pro

    Round that out with GhostDoc (Document This), the test options (TestDriven), a bunch of other options ReSharper and who knows what else threw in there, plus an addin that let's me jump to a method in Reflector, and all those silly "Create Unit Tests..." options that Team Suite added for which I swore I would never use.

    It's enough to drive a guy batty (which really does explain my state of mind after a day working in this environment). Never really noticed it before but Holy Options Batman, that's a crapload of stuff to deal with.

    Excuse me while I reboot my brain.

    P.S. there is an answer to this madness which makes complete sense. Collapse all "Refactor" menu options into a single menu and filter the refactorings to only show what I can do (like how DevExpress does it, good job guys!). Don't show me stuff that I can't do (even if it is grayed out). It's useless to me if I can't click on it. 

    In fact, do that to the entire context menu system in Visual Studio.

    Orcas anyone? Can you hear me guys!

    Wake up and give us code monkeys some screen real estate back please!

  • What's in your Visual Studio?

    I noticed tonight my splash screen for Visual Studio was getting a little out of control (in addition to taking some time to load):

    Visual Studio Team Suite Splash Screen

    I run Team Suite (just because I can) and I've got a lot loaded (including a new experiment, running ReSharper and CodeRush/Refactor Pro together) but I think I'm at the limit of my splash screen length and the add-ins it can display.

    Actually some add-ins (like GhostDoc and TestDriven.NET) don't show up on the splash screen so here's a complete list of what's in my Visual Studio:

    • Microsoft Visual Studio 2005
    • Microsoft .NET Framework
    • Microsoft Visual Basic 2005
    • Microsoft Visual C# 2005
    • Microsoft Visual C++ 2005
    • Microsoft Visual J# 2005
    • Microsoft Visual Studio 2005 Tools for Applications
    • Microsoft Visual Studio Tools for the Microsoft Office System
    • Microsoft Visual Web Developer 2005
    • Microsoft Web Application Projects 2005
    • Microsoft Visual Studio 2005 Team Edition for Software Architects
    • Microsoft Visual Studio Team Edition for Database Professionals Version 2.0.50727.251
    • Microsoft Visual Studio 2005 Team Edition for Software Developers
    • Microsoft Visual Studio 2005 Team Edition for Software Testers
    • Microsoft Visual Studio 2005 Team Explorer
    • CodeSmith 4.0
    • Crystal Reports for Visual Studio 2005
    • DXCore for Visual Studio 2.0
    • Enterprise Library Configuration Editor 3.0 Jan 2007 CTP
    • Extensions for Windows WF
    • Microsoft Recipe Framework Package 8.0
    • Microsoft Visual Studio 2005 Team Explorer - ENU Service Pack 1 (KB926601)
    • Refactor! for Visual Studio 1.0
    • ReSharper 2.5 (build #326)
    • SQL Server Analysis Services
    • SQL Server Integration Services
    • SQL Server Reporting Services
    • DevExpress Tools
    • GhostDoc
    • TestDriven.NET 2.0.1948 Professional

    Anyone else have this problem? Wonder what will happen if I install more add-ons? Maybe the makers of laptops need to focus more on vertical space rather than horizontal (or I could turn it on its side, but makes it hard to type that way).

  • Being a responsible aggregate blogger

    Sometimes things make my blood boil. Other times I just let it pass and move on. As I was trying to catch up on my feeds tonight (only 6182 to go for this month) I stumbled across this post by Andrew Stopford:

    Commercial UI components in OSS

    The use of commerical UI components in a OSS project is a topic of debate and contention. The standard winforms/webforms components are limited and using commerical UI components allows for a far greater degree of UI functionality and in an eighth of the time. It's such a mine field that certainly in the .NET space they are not used. You run the risk of a ever changing UI, a quote from this post on the use of commerical UI components in RSS Bandit.

    I read the quote and it seemed to be very familiar. Wait a minute, it was mine from this post on being a responsible open source developer I wrote back in December.

    The problem I have with the post that Andrew links to is it goes to some aggregate site (the World of ASP.NET) but if you visit the page from the link above, you have no idea who wrote it. In fact there's no link back to my original content.

    My blog content is licensed under the Creative Commons license and you're free to use it, but there needs to be some professionalism about "borrowing" someone elses content. I mean, at least have a link, credit, or at least a mention of where it came from if it's not your own thoughts.

    I've come across other sites where people just downright steal content and even claim it their own which is a whole 'nuther problem. Just as a friendly reminder for anyone who wants to link or quote my content (and you're quite welcome to) please direct people back to the source. It helps me understand if anyone is interested in my message and provides me with a conduit to the outside world in case I'm mistaken (hey, it can happen) or someone wants to leave me for dead in a dumpster.

    Just be a little responsible when you blog, that's all I ask.

  • Shane Perran is a wiener!

    Congrats to Shane Perran with his splash screen entry for SharePoint Builder as it was the fav (both mine and people who emailed me about the entries).

    spbuilder_contest_0

    Shane will recieve a special package from me at this years MVP Summit, including the fabulous home version of SharePoint Builder along with Rice-A-Roni, the San Francisco Treat.

    Thanks to everyone who entered!

  • Stuck between a Ribbon and a hard place

    I'm stuck. While some people will disagree with me, I like the Ribbon. It's a cool idea and looks sharp. As a side note, I convinced a customer we would incorporate it into their business app as the corporatation was moving to Office 2007 this year anyways, and they would be stuck with it. We'll be the first app using it and the customer is quite happy after seeing what it does and how they can use it. Anyways, back to my problem.

    SharePoint Builder is a free, Smart Client app that is coming out shortly (I think the alpha release is a couple of days away). The Ribbon concept kind of works with it as I can envision Ribbon buttons for different types of site definitions the editor handles (sites, lists, features, etc.) with Ribbon groups inside for items in those files, and the ability to add, edit, and delete them. This paradigm works with the Ribbon with the alternative option using traditional menus and toolbars (which works as well but isn't as sexy looking or functional).

    The trouble is finding a library out there to implement the Ribbon control. There are tons of libraries available now that provide the Ribbon control (DotNetBar, DevExpress, etc.) and they all work equally well. If I did have a choice of a commercial package I would probably go with DevExpress. I have a copy of it, it follows the Microsoft Guidelines for the Ribbon pretty closely, works well and is easy to implement. Therein lies my trouble. SharePoint Builder is a free project, and open source to boot. I'm not about to offer up a free, open source tool that relies on an expensive (or inexpensive for that matter), closed, commercial control. I simply won't do it.

    The only free, open source Ribbon I found out there was a GotDotNet project however it was pretty far off from the MS guidelines for Ribbon apps. This might spark a debate as most people don't agree that control authors should follow the guidelines put out my Microsoft however they're published and out there and if I'm going to use a Ribbon control in an app of mine, I'm going to do so with one that's as close to the guidelines as possible. The GDN project is too far off from being compatible and while it sort of looks like the Ribbon, it certainly doesn't behave like it (which I think is the main point of the Ribbon control concept anyways).

    So it doesn't look like a Ribbon is going to work here unless someone else has some thoughts. I'm already swamped in work so really don't have time to build my own open source Ribbon to offer this project (and everyone else once it was built) and the ones out there don't measure up to the guidelines. A free copy of a commercial package isn't the issue as I don't want others to not be able to build the application, and a trimmed down "donation" copy of a commercial package isn't going to work either as it's only as good as long as the company is out there (and there's the problem of what happens if/when it breaks or needs an update). I guess menus and toolbars it is for this project.

  • Crash Recovery

    A couple of weeks ago I had my first car accident in 24 years of driving. The car was a write-off and we've gone out and bought a replacement, as one does in this situation.

    Here's what the old car (a 2004 Suzuki XL7) looks like (not mine but an incredible simulation):

    suzuki_before

    Here's what I did to it:

    Rear end smash up

    What's left of the front of my car

    And here's what replaced it:

    Pacifica_1_big

    A 2006 Pacifica. Leather interior, heated seats, dual climate control, lotsa buttons. Works for me.