Microsoft Certification Exam Voucher Giveaway

I’ve recently come into several Certification Exam Vouchers and have decided to host a giveaway.  Just post a comment to the blog, and I’ll randomly select a winner.  All entries must be in by June 30th, 2008.

You can also post a comment to my cross posting site on MySoftwareStartup to gain an additional entry.  Due to the amount of comments, I will wait to display them all until after the contest.

read more

Growing your software business, stuck in a rut

The following is a response to the forum question posted here.

I had the opportunity to meet Scott while at the Little Rock .Net User Group, and we talked briefly about my thoughts on how to take advantage of the programs available to software startups.  In particular Scott owns a consulting business and he’s having growing pains.

Scott’s problems is very typical of thousands of small business consultant shops.  He’s busy being the business owner, full time consultant/programmer, bookkeeper, marketing, sales guy, etc.  So how do you start growing this small shop?

When doing consulting my first rule is to set the customer’s expectations.  Since you are my customer, here’s the good and the bad of growing your business.  You will have to relinquish power.  You will have to accept things that isn’t “your way”.  You will think quality isn’t as good as what you can do, but that is typically because they aren’t doing it “your way”.  When in actuality, your customers will be fine with the work being done, and they will continue to give you business.  You have to spend money to make money.

So here are my few tips on growing.  Your first hire should be a sales person.  A part time salesman works just fine and will keep you out of the hole, if you’re worried about finding the funds to pay him.  At a minimum, you will need to guarantee him one month’s salary.  Past that, you need to figure out the salary plus/or commission.  A salesman is only as good as his commission.  Most salesmen work off of a draw against future sales.  For more information on how to setup a commission schedule, talk to a car salesman.

When the salesman has customer calls / visit, you will want to be available.  Let him do all the talking, except when you need to talk tech.  After the customer visit, you should write up the time estimates and as much documentation as you feel is necessary.  Let the salesman handle the quote from there on.

The other tip is to hire a part time bookkeeper / secretary.  I know there are a lot of groans here, but that 10 hours you pay that employee $15 an hour, you could be making $80 an hour.  Time is money, and since you’re the owner and consultant, your time is even more valuable.

Once the salesman finds jobs, then you fill it with insourcing or outsourcing.  But remember to never sign agreements that give your code away to the customer and always have the work done offsite.

Lastly, this has more to do with Microsoft.  The certifications are worthless to a Partner.  Partner level isn’t very important, except for the benefits they give you.  Your customers are rarely going to care about your certs or partner level.  Customer availability, responding to their needs, and exceeding expectations are far more important.

I’ll try and go over some of the Certification and Partner actual benefits in another blog post.

read more

Congratulations & Thanks to Jay Smith & Michael Paladino

jay-smith_80x80 MichaelHeadshotSquare

A big heartfelt thank you and congratulations to two of the developer community builders in the Northwest Arkansas area, Jay Smith and Michael Paladino with special mention to Zach Young. As a Microsoft MVP, one of our benefits this year, is the ability to award people with a special prize. This prize is an MSDN Premium account with Visual Studio Team Suite, which includes nearly all of Microsoft’s business software, free of charge.

Jay Smith works for Tyson Foods, Inc. where he is a PMO Architect and Evangelist, and is the President for the Northwest Arkansas .Net User’s Group.  Jay currently serves on the INETA Speakers Committee and works diligently with others on test bed projects to learn new concepts and designs.  You can read more about Jay on his blog http://www.jaysmith.us or follow his tweets at http://twitter.com/jaysmith.

Michael Paladino is a software developer for EagleOne in Fort Smith, AR, and is the Fort Smith .Net User Group President.  Michael is passionate about building the .NET community in the area and is one of the co-founders of the Fort Smith .NET User Group.  You can contact Michael through his blog at http://www.mpaladino.com or via email at paladinomichael@gmail.com.  You can follow his tweets at http://twitter.com/mpaladino.

read more

Writing to .Net Config Files

I’ve been working with config files for quite some time.  I was recently reminded that I needed to finish my original article and share my final findings on my personal best practices for working with config files.

One of the coolest and most useful features in config files is the file attribute as displayed below (see my other article for a more detailed explaination, preferred-method-for-read-only-config-files).

configuration
      <section name="MyCustomSection" type="System.Configuration.NameValueFileSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>  

 

configuration

If you take a look at the other article, it’s a terrific way to setup a read only config file, but what about writing back to it at runtime?  Well, the best way is to use the ConfigurationManager object and then open the raw xml into an XmlDocument object.  (yes yes, I might be a Visual Basic MVP, but I can write the occasional C#)

Configuration config = ConfigurationManager.OpenExeConfiguration(FileName);
ConfigurationSection section = config.GetSection(SectionName);

XmlDocument xml = new XmlDocument();
xml.LoadXml(section.SectionInformation.GetRawXml());

But the problem is, if you have used the file attribute (file=”MyCustomConfigFile.config”), it’s not smart enough to grab the contents of the file (I’m hoping to contact the product team soon to see if they can address the issue).  Fortunately, there is a way to get the filename from the file attribute.  And by adding in a little recursion, we’re able to create an easy method to write back to the proper config file, without having to know the actual filename at runtime.

private const string SETTING_KEY_NAME = “key”;
private const string SETTING_VALUE_NAME = “value”;

public static void SetConfigValue(string SectionName, string KeyName, string Value)
        {
            SetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location , SectionName, KeyName, Value);
        }

        public static void SetConfigValue(string FileName, string SectionName, string KeyName, string Value)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(FileName);
            ConfigurationSection section = config.GetSection(SectionName);

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(section.SectionInformation.GetRawXml());

            if (xml.DocumentElement.Attributes[“file”] == null)
                {
                    foreach (XmlElement element in xml.ChildNodes[0])
                    {
                        if (element.Attributes[SETTING_KEY_NAME].Value == KeyName) element.Attributes[SETTING_VALUE_NAME].Value = Value;
                    };

                    section.SectionInformation.SetRawXml(xml.OuterXml);
                    config.Save();
                }
            else
                {
                    SetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location.Remove
                        (
                        System.Reflection.Assembly.GetEntryAssembly().Location.LastIndexOf(“\”)) + “\” + xml.DocumentElement.Attributes[“file”].Value.Remove
                            (
                            xml.DocumentElement.Attributes[“file”].Value.LastIndexOf(“.config”)
                            ),
                        SectionName,
                        KeyName,
                        Value);
                }
        }

This creates a new problem though.  You can no longer use the same format of the underlying file, specified in the file attribute.

Old format of the MyCustomConfigFile.config specified in my other article preferred-method-for-read-only-config-files:

    

New required format for writing to config files with the file attribute:

               

You’ll notice that I had a comment in the file specified in the file attritube. ()  I honestly can’t recall why this is required (I’m posting this article months after I did the work), but it has to do with reading the config file, and the filenames it is looking for.

This new referred config file format creates a new problem.  You can no longer use the reading method I used in the other article.  I’ve fixed it in the code below as well as provided the full class.

Below is the full class that I wrote.  All I ask is that you add a comment telling me how you used it.

using System.Configuration;
using System.Xml;

namespace HarvestIT.Common
{
    /// <summary>
    /// Application settings manager.
    /// </summary>
    public class ConfigManager
    {
        // Configuration file node names.
        private const string SETTING_KEY_NAME = “key”;
        private const string SETTING_VALUE_NAME = “value”;

        public static string GetConfigValue(string SectionName, string KeyName)
        {
            return GetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location, SectionName, KeyName);
        }

        public static string GetConfigValue(string FileName, string SectionName, string KeyName)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(FileName);
            ConfigurationSection section = config.GetSection(SectionName);

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(section.SectionInformation.GetRawXml());

            if (xml.DocumentElement.Attributes[“file”] == null)
            {
                foreach (XmlElement element in xml.ChildNodes[0])
                {
                    if (element.Attributes[SETTING_KEY_NAME].Value == KeyName) return element.Attributes[SETTING_VALUE_NAME].Value;
                };
            }
            else
            {
                return GetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location.Remove
                    (
                    System.Reflection.Assembly.GetEntryAssembly().Location.LastIndexOf(“\”)) + “\” + xml.DocumentElement.Attributes[“file”].Value.Remove
                        (
                        xml.DocumentElement.Attributes[“file”].Value.LastIndexOf(“.config”)
                        ),
                    SectionName,
                    KeyName);
            }
            return null;
        }

        public static void SetConfigValue(string SectionName, string KeyName, string Value)
        {
            SetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location , SectionName, KeyName, Value);
        }

        public static void SetConfigValue(string FileName, string SectionName, string KeyName, string Value)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(FileName);
            ConfigurationSection section = config.GetSection(SectionName);

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(section.SectionInformation.GetRawXml());

            if (xml.DocumentElement.Attributes[“file”] == null)
                {
                    foreach (XmlElement element in xml.ChildNodes[0])
                    {
                        if (element.Attributes[SETTING_KEY_NAME].Value == KeyName) element.Attributes[SETTING_VALUE_NAME].Value = Value;
                    };

                    section.SectionInformation.SetRawXml(xml.OuterXml);
                    config.Save();
                }
            else
                {
                    SetConfigValue(System.Reflection.Assembly.GetEntryAssembly().Location.Remove
                        (
                        System.Reflection.Assembly.GetEntryAssembly().Location.LastIndexOf(“\”)) + “\” + xml.DocumentElement.Attributes[“file”].Value.Remove
                            (
                            xml.DocumentElement.Attributes[“file”].Value.LastIndexOf(“.config”)
                            ),
                        SectionName,
                        KeyName,
                        Value);
                }
        }
    }
}

read more

MVP Summit, Being Busy, plus Presenting @ the Little Rock .Net User Group

I suppose I was naive in thinking that once I received my Microsoft MVP award, I could breathe a bit.  But we’ve had sooo much Developer Community activity, I haven’t had a chance to breathe, much less blog.  I still haven’t had an opportunity to blog about the MVP Summit!  Needless to say, the MVP Summit was a blast (other than having a digestive track illness, where I missed the last day’s keynotes).  The best thing about the Summit was the ability to meet and talk directly with the product teams.

You really get the sense of the ability to impact .Net by being an MVP!

On June 12, 2008 I’ll be at the Little Rock .Net User Group, and I hope you can join me.  I’ll be speaking on SQL Server Reporting Services.  Unfortunately, due to the late notice, I’ll be speaking on the same subject that I presented at the Tech Expo (had hoped to prep some other topics by now).  But, I’ll have more time to answer questions and hopefully get a bit more detailed on the subject.

Congrats to the new officers there at Little Rock.

Here’s a quick synopsis of the content:

One of the hardest parts of learning a technology that is new to you, is getting started.  Join us as you learn the tips, tricks, and fundamentals of Microsoft’s SQL Server Reporting Services.  Avoid those common mistakes and get up and running with SSRS in this presentation from Randy Walker, a 12 year veteran of report design.

read more