Tuesday, November 6, 2012

Part V: Maintenance (Building a small business website)

Summary: How to run your small business website.
In this section, I will go over the things you need to be aware of when running your small business website. For other topics, see:

Table of contents Domain name renewal
Your custom domain registration is not forever. Make sure you do not forget to renew the registration; otherwise, it will expire and will be up for grabs. The worst thing you can do for your online presence is lose your domain name. It also makes sense to take advantage of registration promotions when you can save 15-25% off the renewal fees.

Tools
In addition to the website builder and webmaster tools offered by search engines, you may find the following tools helpful: Search-engine optimization (SEO)
Once you publish your site and it stays online for a few months, you will probably start receiving solicitations from third parties for improving your Google ranking, or what is known in the industry as search-engine optimization, or SEO. Should you pay your hard-earned dollars for a promise of getting more visibility in search results? The short answer is: no. For a longer answer read Paul Boag's article The Inconvenient Truth About SEO.

Examples
Finally here is a list of small business websites, that were built using the principles I outlined in this series: If you want to share a small business website that was built and hosted on the cheap, leave a comment, and if I find it interesting, I'll add it to the list. When recommending a website, include pertinent info, such as where the site is hosted, if it's free, if not, how much is the annual fee, etc. WARNING: All spam will be deleted without a reply.

Resources
250 Quick Web Design Tips (Part I)
Web Developer Checklist

<< Read Part IV

Part IV: Deployment (Building a small business website)

Summary: How to publish and promote your small business website.
In this section, I will explain how to improve visibility of your new small business website on the web. For other topics, see:

Table of contents How to publish your website?
Instructions for publishing your website under your custom domain will differ (they will mostly depend on the particular website builder and domain name registrar that you use), e.g.: After publishing and making sure that you can access your website using the custom domain name, test it to make sure that it looks and works as expected.

Getting the website indexed by search engines
Once your website is visible at your custom domain, submit it for indexing to Google and Microsoft Bing: To submit your new website to a search engine for indexing, you will need to create a free Google and Microsoft (Microsoft owns Bing) accounts (unless you already have existing ones). (NOTE: Don't forget to submit the sitemap URL to the search engine.)

Verify your website
Once you add a new website to a search engine you will need to pass the site verification process to confirm legal ownership. Your website builder should have instructions explaining how to verify your website, e.g.: I could not find good instructions explaining how to verify your website hosted at Wix, or how to verify a website hosted at any of the preferred website builder against Bing. If these options are not available, you can just submit your website to the search engine for indexing: Check if your website is indexed
It may take a few days for your website to appear in the search engine index. To check if your website is indexed, go to the search engine's home page and run a search for site: followed by the domain name of your website, e.g. site:myverysmallbusiness.com. If the search returns any results, it means that the website is indexed. If you do not see your website indexed after a week or so from submission, check the search engine's webmaster tools page for articles explaining common problems.

Set up Google Analytics
Google Analytics will collect site usage and statistics from your website. The steps will vary depending on your hosting platform, e.g: Add your business to Google and Bing Places for Business
If your business has a physical address, you can advertise it on Google Places for free. The process will be complete after you enter verification code (Google will send it to you via a postcard addressed to your business address or your business phone number). After verification, Google will display your small business information in the search results. You can use Google Places portal to monitor your site statistics, create coupons and promotions, and do other useful things. Do the same on Bing Places for Business.

Create a Facebook (and/or Google+) business page
If you do not have a fundamental opposition to using Facebook (as a marketing tool), create a Facebook page for your small business. Then share it with your friends. Here are some examples of a few Facebook pages created for local small businesses: As an alternative (or in addition) to Facebook, you can create a business page at Google+.

Write a blog
This advice is not for everyone, but if you are passionate about your business, can write reasonably well, and are eager to share insights with the world, create a blog and use it to share stories, ideas, tips, and tricks. You can create a free blog at Google's Blogger or WordPress.com (between the two, I'd recommend Blogger because its free version comes with fewer limitation; on the other hand, WordPress.com has a better editor, but it will also display ads to unsuspected viewers). You can also create a blog at most website builders, like the one that hosts your small business website, but I would keep your blog separate from the website in case you decide to move your website somewhere else. It would help if you name your blog after your website (e.g. myverysmallbusiness.blogspot.com). Keeping a blog requires dedication, so if you are not sure if this is something you want to do, then do not bother.

Get people talking
If you have satisfied customers, ask them to post honest reviews on social commentary sites, such as Yelp, Kudzu, Google Places, etc. If you get negative reviews, follow up with the unsatisfied customers so that the issues are resolved and corrections are noted.

<< Read Part III Read Part V >>

See also:
How to Use Google+ for Business (eBook)
Facebook for Business
50 Ways to Get Your Site Noticed
4 Easy Steps To Promote Your Business On Facebook

Monday, November 5, 2012

Part III: Development (Building a small business website)

Summary: Basics of small business website building.
In this section, I will share some tips that can help you build a small business website. For other topics, see:

Table of contents
At this point, I assume, you have picked a website builder and went through the beginner's tutorials (if these are not enough, there are lots of tutorials -- videos and articles -- available; just search for the name of your website builder and terms such as tutorial, getting started, introduction, beginner's guide, etc, e.g.: weebly beginner's tutorial).

Set up a dedicated email address
I suspect you already have an email address (possibly, more than one). If you only have a personal email address, create a new email account dedicated to your small business, so you can keep all of your business communication separate from your personal life. Just don't create it at your Internet Service Provider (ISP), such as Comcast, AT&T, Verizon, Cox, etc. Using an ISP-specific email addresses (whether personal, or group, or business) is never a good idea because you may need to switch to a different ISP and what would you do then? Migrate all your messages? Send new email address to your friends? Modify all your online profiles (at online stores, etc)? You can do this, but why deal with such hassle when you can get a fully functional email box at Google (GMail) for free? If you don't like Google's interface, you can forward all incoming messages to any other address (including your ISP's), so if you change your ISP, then you will just need to update your GMail message forwarding settings. [Note: At the time of writing, GMail was the only email provider that allowed you to forward incoming messages to external -- i.e. non-GMail -- accounts.] To summarize:
  • Use GMail.
  • Create a separate GMail account for your business (if you already have a Google account, you can link it to your existing Google profile).
  • Give your small business GMail account a meaningful name (ideally, it should be named after your business, e.g. myverysmallbusiness@gmail.com or myverysmallbusiness.owner@gmail.com).
  • Forward messages from your small business Gmail account to the one that you prefer (in case you have more than one email accounts).
Create a website
When you create a website, give it a meaningful title and address. The address will be temporary, until you're ready to publish it under your own domain name, but it can be helpful if addresses match. For example, if your custom domain name is myverysmallbusiness.com, then, assuming you create your website using Weebly, set the temporary address to myverysmallbusiness.weebly.com. The website title should reflect the name or the nature of your business. In my example, a reasonable title would be My Very Small Business. You can also include keywords that you may expect customers to use when they perform searches or append a location (if you operate locally), such as My Very Small Business: Gadgets and Gizmos in New York City, NY (this may help your website get better ranking). Just don't make the title too long.

Pick a website template
When picking a website template you need to think about aesthetics (it should look nice), performance (it must load fast), and function (it must support the layout and navigation needs). Here are a few rules of thumb:
  • Avoid overly flashy templates. Lots of graphics and big pictures generally take longer to load.
  • Less is more. Try picking a template with fewer elements. It may be easier to customize and tweak than a more complex template.
  • Use bigger font. If the website builder or specific template does not allow font customization, make sure that the font size is big enough. With population aging, bigger fonts will make your site more pleasing to more viewers.
  • Think cross-browser. See how the template looks in different web browsers. At the very least, try it in Internet Explorer, Google Chrome, Mozilla Firefox, and Safari.
  • No splash page. Your website should launch at the home page with useful information, not a useless animation, invitation to click the only link, or similar silliness.
  • Keep it quiet. Interaction with your website should be absolutely quiet. This means no "cool" sounds when user clicks links, flips pages, no greeting audio on the home page, et.
  • No autoplay. If you decide to embed video or audio, make sure it does not start to play automatically (the user must click the Play button to get it going).
If you see a website (maybe competitor's or unrelated) which design you really like, do not copy it. It's good to incorporate other people's ideas, but it's bad to make exact replicas (and it can be illegal, too).

Website structure
At the very least, your website must have the following pages:
  • Home: This is your introduction page. Use it to briefly describe your business and offer the information that would be useful to a potential customer. Don't make it too wordy.
  • Contact: Here you specify all the ways a customer can reach you: phone, fax, email, address. If you are operating a brick and mortar shop, include a map with a link to driving directions.
  • Portfolio*: If you have pictures to demonstrate your previous works or items on sale, put their photos on a separate page. This is a personal preference, but I would not use a slide show to display your work; I would use a photo gallery instead. The photo gallery will allow your customers to find what they look for quicker. If you have a lot of photos you want to share or if you continuously update them, I would keep a dozen or so of your best works on the website and store the rest at a different photo hosting site, such as Flickr or Picasa; then add a link to your web albums at the photo hosting site.
    * This is not the best name for the page, so try using something else that fits better for your purpose, such as Gallery, Photos, etc.
  • Services: If you offer fixed-price services, add a page that lists them. If you offer promotions or coupons, include this information as well (it can go to a separate page).
  • Resources: If you have links to useful information that you think can be helpful to your customers (even if they never contact you), include them in this page. Be a good citizen regardless of business impact (although, this can indirectly help you, too).
  • About: Use this page to offer a more detailed overview of your business. Specify when your business has been lunched and where it operates. List the terms of your workers compensation insurance. Include your business or permit license number. Use links to sources that customers can use to verify the information.
Web graphics
I'd recommend that at the first draft of your small business website, you do not put any pictures on the web pages (unless they are part of the template). Try to make it look nice without any graphics. Then add graphics but try to limit it to one primary graphics file per page (not counting smaller images, such as thumbnails or logos). Of course, you can break this rule if you have a valid reason.

Where to get graphics?
It is best to use your own graphics files. If you operate a brick and mortar business, you can take a photo of your shop. You may also want to display a photo of yourself and/or your employees and partners (make sure you get their permission in advance). If you include your business' history in the About page, photos from the past (most likely scanned) can make the information more interesting. When using your own images, make sure you optimize them for the web (e.g. trim white space, reduce picture dimensions, set JPEG quality to 80%).

Stock photos
It gets a bit tricky if you want to use stock photos. The basic rule is: do not copy photos from other sites (or link to them) unless you are absolutely sure that you will not violate the copyright laws (in most cases, you would). Some website builders (such as Weebly) allow you to easily search for and embed images in your web pages. You can also buy stock photos from such sites as iStockPhoto or get some for free from stock.xchng. You can also search for free images at GettyImagesFlickr, Google, or Creative Commons. Just make sure that you follow the terms of use for the particular license type (i.e. don't forget to include attribution when needed).

Writing for the web
When you add text to a web page, keep in mind the following rules. First, remember that people do not read business websites; they scan them for keywords and click the very first link that vaguely resembles a match. Therefore, do not write a composition. Use lists, short phrases, and brief paragraphs. Eliminate all unnecessary words. After your first draft, see if you can reduce the amount of text by half. Do it. Then try reducing what is left by half again. When you write text for a web page, use the exact combinations of keywords that you expect your potential customers to search for. This will help you get better page ranking.

Layout
When it comes to the web page layout, the simpler, the better. Use a simple layout and simple content. Don't try to impress people with sophistication (unless this is the nature of your business). Keep it minimal, keep it simple. Limit styles to the minimum. You should use at most 3 font sizes (one for headings, one for paragraphs, one for small print) and two font faces (one for headings and another for everything else).

Getting better
If you are a novice building your very first website, here are some books that can help you get better. If you were to get just one book on the topic, I'd recommend Steve Krug's Don't Make Me Think: A Common Sense Approach to Web Usability (this is a short and entertaining book, which I finished in a couple of evenings). The Non-Designer's Design Book by Robin Williams is a good primer that will help you understand the basic design principles.
Final touches
Do not publish your website (to your custom domain) until it's ready. If you publish a half-baked site, you will be penalized by search engines. When working on your website, and especially when making lots of changes, leave it for a few days and then visit it again. Taking a break from your website will give you a better perspective and help you catch the problems with a fresh eye. Before publishing the site, show it to someone and ask for an honest feedback. It would be helpful to find someone with background in web design and/or web development, but even without it, having more people to check out your work will help you find the things that you have missed. Also, make sure that you check the following:
  • Verify that the site works in all major web browsers (Internet Explorer, Chrome, Firefox, Safari).
  • Test it using a smart phone and/or a portable/mobile device, such as a tablet.
  • Inspect all content: text (make sure there are no error or typos), images, links (click on every link to see if it points to the right location), downloads (if you host any files, such as PDF documents).
Once you have reviewed and tested your website, you should be ready to publish it.

<< Read Part II Read Part IV >>

See also:
How to create a website // Photographers Need Their OWN website
How to keep your text clean
10 Things Every Small-Business Website Needs
How To Make A Website - Free Tutorial
How to use photography in web design

Monday, October 15, 2012

Part II: Exploration (Building a small business website)

Summary: Basic things you need to do when building a small business website.
In this section, I will describe the basic aspects of building a small business website. For other topics, see:

Table of contents How to pick a platform?
If you decide to build a website for a small business, you need to pick a platform or technology which you will use. The most obvious options include:
  • Build it from scratch
    If you are familiar with programming and feel comfortable around web technologies such as PHP, ASP.NET, or Ruby on Rails, you can try building your small business website from scratch, but in most cases and for most people, this would be the least recommended approach. Without getting into the gory details, take my word: don't even think about it.
  • Create a Facebook page
    In case you did not know, you can create a Facebook page for a small business website (see these examples). It will not cost you any money (at least, at this time, Facebook does not charge for hosting small business pages). While having a Facebook page is an excellent idea (and I'll come back to it in an upcoming post), I would not recommend Facebook as a primary website for a number of reasons. For example, it will not allow you to have your own domain address, which may make it harder for customers to find you. Your website's Google ranking will also suffer.
  • Use a blogging engine
    Currently, both Google's Blogger and WordPress.com allow you to create static pages for you website. It's a nice idea, but the last time I checked, the features were very limited, and the website templates looked really unprofessional. I hope that these services improve with time because they definitely have potential, but for now, I would skip them. Another alternative would be to use a self-hosted version of WordPress.org, but this option belongs to the next category of content management systems (CMS).
  • Use content management system (CMS)
    Popular CMS options include: Joomla, Drupal, and WordPress (see comparison of these three platforms). This is another option for tech-savvy users and unless you have already done this before or plan to make it a carrier skill, I would not recommend it. Keep in mind that you will need to find a hosting company that supports the CMS of your choice (charges normally start around $5/month).
  • Use a website builder
    A website builder allows you to build a website using available templates. You pick a template and start adding pages. You can customize the layout of each page, although customization options are limited to the widgets that the website builder supports. Some website builders charge fees, while others are free.
I think that for a typical small business owner, a website builder is the best option for a number of reasons.

Why use a website builder?
Many reasons, such as:
  • It's cheap
    If you do not mind a couple of minor limitations, you can host your website for free. You can also upgrade to a fee-based hosting package (with no limitations), most of which are not terribly expensive.
  • You're the boss
    Once you get a website, you will not depend on anyone and can do changes any time you want. No need to call or email anyone, and wait for the change.
  • Quick setup
    You can get a few pages done in (literally) a few minutes. Sure, they will probably not look very professional, but once you find a more-or-less decent template and make a few tweaks, they can look no worse than an average web page you find online.
  • Easy to maintain
    I'm not gonna lie: initial setup of the site will take some time and effort to get a semi-professional look, but once done, it should be really easy to make changes (assuming that you do not want to do a major redesign).
  • Limited technical knowledge is needed
    Some understanding of basic HTML and web design will definitely be helpful, but you don't need to be a technical guru to build and maintain the site and your sense of aesthetics will be more important than technical skills.
  • Self-hosted
    Since website builders also provide hosting, you don't have to look for a hosting company.
  • Self-contained
    You will not need any tools (other than a web browser) to build your website. No need to keep a local project and deal with backups, etc. Your website's control panel will be available from anywhere.
  • Optimized for mobile
    Most website builders automatically optimize your web pages for mobile browsers clients, such as iPhone or iPad.
However, you must be realistic and understand that all website builders have limitations. The major limitation is that your design capabilities are constrained by the limitations of the available templates, page widgets, and page layouts. And a typical selection of templates is rather small (especially if you count multiple versions of the same template with different color schemes as one). Majority of templates I've seen look like they were put together for a high school project in the late 90's. But you should be able to find one or two better templates. I believe that most small business websites can live with these limitations.

Which website builder to choose?
My criteria for choosing a website builder includes the following:
  1. Must offer a free hosting package with few limitations.
  2. Free package should not contain banner ads.
  3. Free package should not have silly bandwidth restrictions (e.g. 1,000 page views and then it will die).
  4. Free package must allow custom domains.
  5. A premium package must be reasonably priced (I'd say $120 or less/year).
  6. Website must be built as regular HTML (must not be Flash-based).
Currently, these requirements limit my choices to the following options: I played with Google Sites just a little bit, but did not like what I saw: the site template looked really basic, very amateurish. Unless Google adds features and makes the site template more visually pleasing, I'd stay away from it.

Wix used to produce Flash-based websites, but they stopped this silliness a while ago, so it's worth checking out. (NOTE: It looks like Wix requires you to purchase a premium support package to use custom domains, which is significant limitation.) I have more intimate experience with Yola and Weebly, and at this time, I prefer Weebly, although Yola keeps adding improvements, so I'd recommend both of them (for a detailed comparison between the two, see my Free web site builders: Weebly vs. Yola post).

UPDATE: I can no longer recommend Weebly for free hosting because it's free plan does not allow custom domains (so you website will always be something like http://mysite.weebly.com; for a paid plan, this is not an issue).
It's not going to cost you anything (other than time) to create a website, so register for each service, poke around, and see which one you like best. Here are some tutorials, which can help you get started (you can find more by googling terms such as "getting started Yola" or "beginner's guide Wix" or "tutorial Weebly"): For the rest of this discussion, I'll assume that you will build your small business website with the help of one of the free website builders. I'll make my recommendations generic enough to apply to either service.

Do I need a domain name?
Regardless of where you host your small business website, you will need a domain name (i.e. unique web address by which your site will be known on the internet, such as myverysmallbusiness.com). Technically, while you're playing with the website builder, you don't really need a domain name (your website can be tested and even published as a subdomain of the website builder, such as myverysmallbusiness.weebly.com), but once your site goes public, you better have your own domain. It will cost you very little, make your website more professional, and help you in future, e.g. if you decide to migrate your site to a new host.

How to pick a good domain name?
Your domain name should ideally be named after the registered name of your business, but since small business names are not unique, it's likely that the name is already taken either бы a functioning website or simply reserved for future use (some people buy the whole ranges of domain names hoping to resell them later for more money). If your desired domain name is already taken, don't get discouraged. First, check if the same name is available under a different top-level domain (TLD), e.g. myverysmallbusiness.com may be taken, but myverysmallbusiness.biz is not. If the name is not available under any desired TLD, try improvising:
  • Use a more (or less) formal name, e.g. myverysmallbusinessllc.com, or myverysmallbusinessinc.com.
  • Add name of the city or county to the name, e.g. myverysmallbusinessNYC.com.
  • Instead of (or in addition to) using the name of your business, try describing the nature of your business using the keywords by which you want the potential customers to find you online. For example, if you operate a printing business, and you want a link to your web by searching for "custom signs posters", try something like customsigns.com, customposters.com, customsignsposters.com, or signspostersetc.com.
Keep in mind that, while it's desirable, your website's domain name does not necessarily have to match the registered name of your business. Just make sure that it's descriptive and easy to spell (try spelling it out for an imaginary customer). Never use uncommon abbreviations. Avoid punctuation (unless the name of your business contains special characters -- such as dashes -- stick with alpha-numeric characters).

Which TLD to use: .com, .net, .org, .biz, etc?
If you are running a non-profit, start with .org. The best option for everybody else is .com. If .com is not available, try .biz (keep in mind that domain name registration for .biz is more expensive by a couple of bucks per year). If neither option is available, try .net. Although, there are other TLDs available, I would be very cautious using them because they are not common (they may sound suspicious to your customers).

Where to register a domain name?
A service that allows you to register a domain name is called a domain name registrar. Most registrars will let you purchase the first year registration at a steep discount (such as 99 cents or $1.99). Before you fall for the first year promotion, check the regular price; otherwise, you may find yourself in a trap similar to the recent Yahoo! scam (Yahoo! have been offering a very low first year registration fee, but at some point it tripled the renewal fees for the existing customers). It is possible to transfer your domain name registration from one registrar to another, but it involves a bit of a hassle, which may not be worth a few bucks you're planning to save. So if you have no reason to chose a particular registrar, start with GoDaddy. It offers frequent promotions, but even the regular prices are reasonable.

IMPORTANT: Most website builders allow you to purchase a custom domain name through them. Do not fall for this offer! For one, their fees are normally higher than you would get from an external domain name registrar. Also, at some point, you may want to move your website to a different website builder or a brand new hosting provider, so having your domain name registered elsewhere would eliminate one more hassle in the process.

How much will I have to spend?
At the very minimum, your costs will be limited to the cost of domain name registration (and the corresponding fees). For a typical domain this would amount to about $15 per year. In many cases, the first year can cost you close to $1. When you are about to renew the registration, check if the registrar offers any coupons or promotions (notice that promotions for the first time registration normally do not apply to renewals). Keep in mind that when you register a domain name, the personal information you submit will become public. If you want to protect your privacy, opt for a private domain registration that most registrars offer for a few extra bucks (normally, less than $10). Registrars also offer a whole range of other add-on services, but you will most likely not ever need them.

Now, as I have mentioned, I assume that you will be using a free version of the website builder. If you decide to upgrade to a fee-based package, it will be extra cost. I would not recommend doing this immediately. Try staying on the free version for a couple of years and see how it works out for you. If you find the limitations of the free package burdensome, consider upgrading. A fee-based package will give you some bonuses. For example, in the case of Weebly, you will be able to remove the sponsorship footer (it's rather unobtrusive, though) and use a favicon.

So, should you upgrade or not? Here is my logic. A typical web hosting service fee starts somewhere around $5 per month (this comes to $60 per year plus any processing fees). So if an upgraded package costs less $100 or so, why not help out the company that offers you a valuable service? Help the business and bring good karma. But if the cost of the premium package is significantly higher, or if you do not mind living with the limitations of the free hosting package, or if you are in dire straights and are counting every dollar, be free.

<< Read Part I Read Part III >>

See also:
About That Small Business Website Of Yours
Find the right website builder
Build a Website for Your Small Business: 5 DIY Services
How Much Does A Small Business Website Cost in 2013?
Five Free Website Builders
A Web Presence Without a Website
10 Facebook Business Page Features You Should Be Using
Plato Web Design (see prices)

Thursday, October 4, 2012

Part I: Pre-exploration (Building a small business website)

Summary: Should you build your small business website yourself, pay a professional to do it, or do something else?
In this section, I will cover the most important decisions you need to make before you start building a website. For other topics, see:

Table of contents Buy or build?
The first and most important decision you need to make is: whether to hire a professional or build the site yourself (possibly with some help). Either option has pros and cons. Building a website yourself will most likely be the cheapest option. It will also give you full control of the site, so you will not depend on anyone. But the result will most likely (although, not necessarily) look less polished. So if you have a sufficient budget, consider hiring a professional.

How much would hiring a professional cost?
It will cost more than building the site yourself (at least, money-wise), but the exact amount could be $200, $2,000, more, or somewhere in between. The cost will depend on the website's complexity and other factors. Keep in mind that development cost should not be the primary concern when hiring a professional. The first question you need to address is: who (and how) will be in charge of the website maintenance after the site is up and running? Here is a common conversation I often get into when someone (SO) asks me (ME) for help:
- SO: I have a website built a year ago. Can you take a look at it?
- ME: Sure. It looks nice. Who built it? And how much did you pay?
- SO:Some guy from Poland charged me $400 for it.
- ME: That's not bad, not bad at all. So what do you need me for?
- SO: Could you make a small change? I need to update price list on this page?
- ME: Okay, do you know where it is hosted? Or which platform it is built on?
Now the conversation takes a bad turn. The small business owner does not know where the site is hosted (in response to the question about hosting, I normally get the site's URL). Or he may know, but have no idea how to access the control panel or source code. Hardly ever does the owner know which platform (PHP, WordPress, ASP.NET, etc) the site is built on. To make matters worse, the original developer is nowhere to be found or cannot be easily reached. [By the way, I'm not picking on Polish developers here; this can happen with contractors from U.S., Mexico, Russia, China, India, or any other country.] So, the poor small business owner is out of $400 and needs to rebuild the site from scratch.

How to avoid problems when working with a contractor?
Here are some topics you need to consider and discuss with your contractor to avoid common pitfalls (here, I'm focusing only on the aspects most likely to be missed by novices; you will need to discuss requirements, payments and other important topics that should be obvious):
  • Check contractor's experience and the websites he has already built (the longer the contractor has been in business, the more sites he should be able to show you). Do you like them? Notice the sites built for the same type of business (feel free to borrow ideas from them).
  • Determine who will own and maintain the site once it's build. If the contractor will be responsible for maintenance, discuss the associated costs (normally, maintenance involves monthly fees). Make sure you understand terms of maintenance, i.e. what the maintenance fee will cover. Ask for a typical response time (if you need to make a minor update or fix a problem).
  • Ask where the site will be hosted and how long the contractor has been using this host. Were there any issues? How long did it take to resolve them? Check if it would be possible to move to a different host if you experience consistent problems (such as long response time, outages, etc). Make sure you agree on who will be responsible for troubleshooting the issues if the site is down or experiences problems.
  • When discussing costs and fees, ask for a payment breakdown to see how much goes where, e.g. how much web site hosting or domain name registration will cost, how much the contractor will take, etc.
  • Make sure you own your website's domain name. If you cannot be the owner, ask the contractor if he can transfer ownership to you in case you decide to move on.
  • Ask which technology the contractor will use to build the site. Stay away from Adobe Flash-based sites: they can look flashy on your computer, but may not work on other devices (such as iPhone), and will most likely cause you problems in the long run.
  • Request to have a copy of the source code (you will need the complete project). Source code may not make sense to you now (or ever), but if you hire someone else to maintain your site later, source code will be needed.
  • Make sure you website will be optimized for mobile access and will work on slower connections.
  • Ask the contractor about his search engine optimization (SEO) strategy. Don't fall for the paid SEO services.
  • Discuss the separation procedure. If you are not happy with the contractor, or want someone else to take over support or redesign the site, how will you get the source code and other files (such as photos, etc)?
  • Check if you can be allowed to access the site's hosting control panel (in case you want to make changes). If so, do a walkthrough and make sure you know how to log on and get around.
  • Once the site is built, check the following:
    • See how it works using different web browsers (Internet Explorer, Firefox, Chrome, Safari).
    • Check site for content: read all text, look at images.
    • Test all hyperlinks to make sure they point to the right locations.
    • When hosting files (such as PDF documents), make sure you can download them.
How to be a good client?
Other than being a prompt payer, try to provide the information requested by your contractor on time. Remember that while the contractor takes care of the site's web design and operation you own its content. We know that you are busy with your primary business, but without your feedback, the contractor will have nothing to put on the web pages.

To DIY or to not DIY?
If you have little money or cannot (or do not want to) spend more on the online presence, the do-it-yourself (DIY) is your only option. In the rest of this series, I'll discuss how to make the best of it, but regardless of the path you chose -- buy or DYI -- I hope it will be informational to you.

P.S. After publishing this post, another alternative (in addition to hiring a professional or doing it yourself) came to my mind. Depending on the type of business you are conducting, you may be able to find a provider specializing in hosting small business websites for the folks just like you. For example, my local auto mechanic, hosts his site at Repair Shop Websites. I haven't checked, but I suspect that other businesses may have something similar (e.g. here is one targeting food service businesses: BistroSquare). On the positive side, such providers optimize their services for the needs of specific industry, their websites normally look professional, and they should be more reliable than a random guy you find on the internet. Unfortunately, such services are not inexpensive, at least, when compared to the DIY option. But I would check them out anyway. Maybe you can find a deal that will make sense to you.

<< Introduction Read Part II >>

See also:
4 Easy Steps To Create Your Small Business Website

Tuesday, October 2, 2012

How to build a small business website for less

Summary: This series is intended for small business owners who want to establish web presence on a limited budget.
Say, you are a small business owner operating a local bakery. Or maybe you are an accountant. Maybe you manage an auto shop. Or work as a general contractor. You would like to have a website, but think it will cost you too much. Or maybe you just don't know how to start. Worry not: you can build a website yourself (or with little help). And you can do it on the cheap. And it does not have to be bad. In fact, it can be better than an average small business site you find now on the web. In this series, I'll tell you how you can do it.

First, let me set the expectations. This series is not about building the next Amazon.com. A website I have in mind will not get you design awards. It is also not intended for businesses operating primarily online, such as online stores. The idea is to make a basic site with a handful of static pages, which will expose your business to the internet.

Before we start, let me answer a few questions that small business owners often ask:
  • Do I need a website?
    For majority of small business owners: yes, you do... unless you are one of the best or one of the worst. If you are very good, your reputation is spread by the word of mouth, and clients are chasing you instead of you chasing them, then the website will probably not make it better (although, it will not hurt, especially when business slows down). But if customers complain about you a lot, then visibility on the web will do you more harm then good (unless you take it as an opportunity to improve).
  • Will a website help me generate more business?
    Don't expect immediate inflow of customers right after publishing your website. It will take time for search engines and people to find you. There are ways to speed up the process a bit, but even under ideal conditions, you may not see obvious results, at least, not immediately. But in certain cases, it may help, especially, if you consider the competition. Do your competitors have websites? If they do, you can't afford to not have one. If they don't, a website will give you a competitive advantage. Also, web presence can bring you business opportunities that you may not even expect.
  • How much effort will building and maintaining a website take?
    Initial setup will take most of the time. If you already know what you want to put on the website, you can do it in a couple of days. Once your website is up and running, maintenance (if you follow my recommendations) will not take much effort.
  • Can I build a website myself?
    In theory, many people should be able to. In reality (at least, based on my experience), majority of small business owners seek help with initial setup. Hopefully, this series will help you chose the path that is right for you.
  • How much will a website cost?
    My goal is to get you up and running for less than $20 per year for a basic site (with a handful of pages). This assumes that you do everything yourself or get help for a more technically and aesthetically savvy friend or relative. If you need professional assistance for initial setup, it may cost you more, but it would be a one-time cost. Also, if you need some special bells and whistles, it may be more expensive (but not by a lot). I'll discuss costs in more detail later.
So, let's get started, shall we?

Here is the list of topics I will cover (I'll enable links when I make the topics available):
  • Part I: Pre-Exploration
    - Pros and cons of hiring a contractor
    - How to avoid common pitfalls when working with a web developer
    - Why do it yourself?
  • Part II: Exploration
    - Choosing a web host and platform
    - Picking a domain address and registrar
    - Cost allocation
  • Part III: Development
    - How to get started?
    - Basic website structure
    - Where to get graphics?
    - Where to store files?
    - Do's and dont's of web design
    - How to get better?
  • Part IV: Deployment
    - Steps to publish your website
    - Make if visible to search engines (Google, Bing, etc)
    - Website promotion
    - Getting social
  • Part V: Maintenance
    - Things to keep in mind when running your website
    - Examples of small business website
    - Resources
If you have a general question relevant to the subject, please leave a comment.

See also:
The Website as a Business Resume
How To Get Your Small Business Online Today

Wednesday, September 26, 2012

Technobrief #14

Summary: Recent findings of software, articles, and more.
Books CSS Data Design Graphics HTML5
  • Back to basics: how to code an HTML5 template
    Dain Miller covers the basic constructs of HTML5.
  • HTML5Boilerplate
    A template that helps you build fast, robust, and adaptable web apps or sites.
  • HTML5 Form Validation
    Stephen Walther describes how you can take advantage of HTML5 client-side validation regardless of the type of application that you are building.
  • Paul Irish on HTML5 Boilerplate
    In this video, Paul Irish, the man behind the project will show you how you can use HTML5 Boilerplate to get your projects up and running quickly while keeping best practices covered.
JavaScript/jQuery
  • An introduction to Modernizr for designers
    Louis Lazaris introduces a way to ensure that you’re designs are able to take advantage of new HTML and CSS features using the Modernizr JavaScript library and API.
  • Create a Windows-like Interface with jQuery UI
    A walkthrough by Nikko Bautista.
  • Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()
    Elijah Manor attempts to shed some light on confusion about the real differences between these methods and when they should be used.
  • Essential jQuery Plugin Patterns
    Addy Osmani takes the official jQuery plugin authoring guide a bit further
  • Forsight.js
    Gives webpages the ability to tell if the user's device is capable of viewing high-resolution images (such as the 3rd generation iPad) before the image is requested from the server. Additionally, it judges if the user's device currently has a fast enough network connection for high-resolution images. Depending on device display and network connectivity, foresight.js will request the appropriate image for the webpage.
  • Introduction to the ASP.NET Web API
    Stephen Walther offers a brief overview of the features of the new ASP.NET Web API. You learn how to use the ASP.NET Web API to retrieve, insert, update, and delete database records with jQuery. We also discuss how you can perform form validation when using the Web API and use OData when using the Web API.
Life Mobile Opinions Process Programming Software
  • ActivePresenter
    The free edition allows you to create screencasts in three simple steps. Supported formats: AVI, MP4, WMV, WebM.
  • Adapter
    Free video and image converter for Mac and PC.
  • Kaspersky WindowsUnlocker
    A free program that you can use to remove the effects of malware that is blocking you from accessing parts or all of the system.
  • MP4Cam2AVI
    Free MPEG4/MJPEG to AVI converter/joiner for MPEG-4 camcorders and digital photo cameras (also cell phones that shoot video in MP4 format). It repackages video content to AVI container without video recompression, it's fast and loseless.
  • Siren
    Free file renamer.
  • XVI32
    Free hex editor.
Tools
  • Ambient-mixer
    Listen to relaxing music, ambient atmospheres and astonishing sound effects. If you want, you can even create your own atmospheric sound mix, online and for free. Every audio template can be easily edited for your own needs.
  • Compfight
    Image search engine tailored to efficiently locate images for blogs, comps, inspiration, and research. We make good use of the flickr™ API, but aren't affiliated with flickr.
  • jsFiddle
    Offers an easy way to test HTML, CSS, and JavaScript online.
  • Codeacademy
    Great learning resource for teachers and students of computer programming.
  • Marklets
    Bookmarklet search engine.
  • Mockup Builder
    Build mockups of websites and software apps online (free).
  • Invoiceable
    Free online invoicing app (the free version will include a link to the site).
Work UX Windows

Friday, July 13, 2012

How to pass arrays of objects from C# to C++

Summary: Sample illustrating how a C++ code can access a collection of objects returned by a .NET application.
Say you need to make a legacy C++ app call a web service. Since C++ is not very friendly to anything SOAP, the easiest option could be to write a helper .NET app, which would make SOAP calls, and expose it to your C++ app as a COM object via COM interop. This approach is rather straightforward, but it will get more complicated if your .NET COM object needs to pass collections to your C++ app. Here is how you can do it.

Disclaimer: There is no sample project and the code snippets below are incomplete, but they should be sufficient enough for a person familiar with C++ and C# to come up with the final solution. Also, no VB.NET samples, but C# snippets should be easy to follow and convert to VB.NET.
Step 1: Create a C# project for your .NET COM component.
I assume you already know how to do this, but if not, you can start with these articles: Make sure to build a class library (DLL) and check the Register for COM interop option under the project's Build settings. Also, if you do not want to expose every public class, method and property from your assembly (e.g. if it calls a web service, you would not want the Visual Studio-generated proxy classes to be exposed as COM objects), uncheck the Make assembly COM-Visible option in the Assembly Information dialog box (to open this dialog, select the Application tab in the project properties and click the Assembly Information... button).

Step 2: Implement the primary COM component.
Your C++ app will use this COM component's methods to get data. The articles reference in the previous step explain what you need to do, but here are the main points:
  • You need to define an interface and implement a class derived from this interface (component class).
  • Your C++ app will only see the methods declared in the interface.
  • Both the interface and the component must be marked with unique GUIDs.
  • By default, ProgID of a .NET COM component is derived from the namespace and class names; to override it mark your component with an explicit ProgID.
  • I prefer to keep both the interface and component code in the same file, but you can put them in different files.
Here is an abbreviated sample:
using System;
using System.Runtime.InteropServices;

namespace MyCompany
{
    [Guid("11111111-1111-1111-1111-111111111111")]
    [ComVisible(true)]
    public interface IMyComObject
    {
    }
 
    [Guid("22222222-2222-2222-2222-222222222222")]
    [ProgId("MyCompany.MyComObject")]
    [ComVisible(true)]
    public class MyComObject: IMyComObject
    {
    }
}

Notice that we have not defined any methods, yet.

Since our ultimate goal is to pass a collection of objects from C# to C++, I will first implement a method that returns a custom object, and then a collection of these custom objects. Obviously, C++ will not be able to access this object as is, so we need to expose it as another .NET COM object. As with our primary object, the C++ code will access this component via an interface. Keep in mind that C++ does not understand the concept of property, so each property will need a helper getter (and -- if needed -- setter) method.

Step 3. Implement a COM component holding your data.
Let's say your C# app wants to return user info to the C++ app. We'll define a .NET COM object that will hold user properties. In this example, I assume that the C++ code will only need to get object properties, so we will omit COM methods to set them. Notice that we can still set the properties in the C# code:
using System;
using System.Runtime.InteropServices;

namespace MyCompany
{
    [Guid("33333333-3333-3333-3333-333333333333")]
    [ComVisible(true)]
    public interface IMyUser
    {
        [ComVisible(true)]
        int GetIdn();
  
        [ComVisible(true)]
        string GetUsername();
  
        [ComVisible(true)]
        bool GetIsDisabled();
    }
 
    [Guid("44444444-4444-4444-4444-444444444444")]
    [ProgId("MyCompany.MyUser")]
    [ComVisible(true)]
    public class MyUser: IMyUser
    {
        [ComVisible(false)]
        internal int Idn { get; set; }
  
        [ComVisible(false)]
        internal string Username { get; set; }
  
        [ComVisible(false)]
        internal bool IsDisabled { get; set; }
  
        public MyUser()
        {
            Idn        = 0;
            Username   = null;
            IsDisabled = false;
        }
  
        [ComVisible(true)]
        public int GetIdn() { return Idn; }

        [ComVisible(true)]
        public string GetUsername() { return Username; }

        [ComVisible(true)]
        public bool GetIsDisabled() { return IsDisabled; }
    }
}

Now that we have a .NET COM wrapper around our user info structure, let's define methods that return a single user object, as well as a collection of user objects.

Step 4. Implement COM methods in .NET component.
For the purpose of this discussion, implementation of user data retrieval from the back end is not important, so I will abbreviate it. You may get data from a web service, database, Active Directory, or some LDAP store, it does not really matter here. But you will need some way of communicating errors from the C# code to the C++ app. There are multiple ways to do this. I will use an integer return value to communicate error or success code (with zero indicating success) and use a string parameter to pass error information.
using System;
using System.Runtime.InteropServices;

namespace MyCompany
{
    [Guid("11111111-1111-1111-1111-111111111111")]
    [ComVisible(true)]
    public interface IMyComObject
    {
        [ComVisible(true)]
        int GetUser
        (
                int     idn,
            ref IMyUser user,
            ref string  error
        );
  
        [ComVisible(true)]
        int GetUserList
        (
                string    mask,
            ref IMyUser[] user,
            ref string    error
        );  
    }
 
    [Guid("22222222-2222-2222-2222-222222222222")]
    [ProgId("MyCompany.MyComObject")]
    [ComVisible(true)]
    public class MyComObject: IMyComObject
    {
        [ComVisible(true)]
        public int GetUser
        (
                int     idn,
            ref IMyUser user,
            ref string  error
        )
        {
            int result = 0;
      
            try
            {
                // GetUserFromBackend would retrieve data from
                // backend and covert it to a MyUser object.
                // We then need to cast the MyUser object as
                // an IMyUser type.
                user = GetUserFromBackend(idn) as IMyUser;   
            }
            catch(Exception ex)
            {
                // GetErrorMessage would retrieve error
                // messages from immediate and all inner 
                // exceptions.
                error = GetErrorMessage(ex);

                // Set proper return code indicating error.
                result = GetErrorCode(ex);
            }

            return result;
        }

        [ComVisible(true)]
        public int GetUserList
        (
                string    mask,
            ref IMyUser[] users,
            ref string    error
        )
        {
            int result = 0;
      
            try
            {
                // GetUserListFromBackend would retrieve data
                // from backend and covert it to array of 
                // IMyUser objects (each element of the array
                // will actually point to a MyUser object).
                users = GetUserListFromBackend(mask);   
            }
            catch(Exception ex)
            {
                // GetErrorMessage would retrieve error
                // messages from immediate and all inner 
                // exceptions.
                error = GetErrorMessage(ex);

                // Set proper return code indicating error.
                result = GetErrorCode(ex);
            }

            return result;
        }    
    }
}

Now, the fun part: how do we access these methods and handle returned objects from the C++ code?

Step 5: Build type library (TLB) file for .NET COM assembly.
The easiest way to incorporate .NET COM classes in the C++ assembly is by importing the type library. By default, the .NET class library project build does not generate the type library, so add the following to the project's Post-build event command line settings (under the project's Build Events tab):
call "$(DevEnvDir)..\..\VC\vcvarsall.bat" x86 >nul
tlbexp "$(TargetPath)" /out:"$(TargetDir)$(TargetName).tlb" /win32 /silent /nologo

Now, when you build the assembly, Visual Studio will also generate the TLB file along with the DLL. You will need the TLB file only for development.

Step 6: Import type library of the .NET COM assembly into the C++ project.
Add the import statement to the source (or header) file(s) of your C++ project (you can use path relative to the C++ source or header file containing the import statement):
// Set path to .NET COM project relative to the current file
#import "<path_to_project>\bin\Release\<assembly_name>.tlb" no_namespace named_guids raw_interfaces_only

When this line gets compiled, Visual Studio will generate a TLH file with proxy classes for you .NET COM components. The file is located in your user account's AppData\Local\Temp folder. You do not need to explicitly reference this file in the source code or project; Visual Studio will do this for you implicitly. Something to keep in mind: if you make a change to the .NET COM object's public members, you need to recompile the C++ source (or header) file containing the import statement; otherwise, Visual Studio will not see your changes.

Step 7: Create .NET COM object in C++ code.
You can create a COM object in a number of ways: via CoCreateInstance, using smart pointers, etc. Here is how you do it via plain old CoCreateInstance:
HRESULT       hr            = S_OK;
IMyComObject* pIMyComObject = NULL;  // data type matches name of .NET interface

hr = CoCreateInstance
(
    CLSID_MyComObject,       // CLSID_ + name of .NET COM class
    NULL,
    CLSCTX_ALL,
    IID_IMyComObject,        // IID_ + name of .NET COM interface
    (LPVOID *)&pIMyComObject
);

Notice how names of the generated proxy classes, GUIDs, etc match the names you use in the .NET code. If you are not sure what the names are, find the TLH file and see the definitions there. Again, keep in mind that you will make all calls via the interface.

Once you verify that you C++ program successfully crated the .NET COM object, you can invoke the methods.

Step 8: Call .NET COM methods from C++ code.
If you are not sure what the data types of the COM method parameters should be, check their definitions in the TLH file. Normally, Visual Studio does translation correctly between basic data types, i.e. .NET string values will correspond to BSTR strings, .NET DateTime will map to DATE, bool values will turn into VARIANT_BOOL, etc. In this example, I'm interested in the more complex data types used to pass user data collection.

Let's start with the call to get a single user object:
// Error message returned by .NET COM method
BSTR bstrErrMsg = 0;

// Error code returned by .NET COM method
long nErrCode = 0;

// .NET COM object (interface) holding user data
IMyUser* pIUser = NULL;

// hr (HRESULT type) will indicate whether COM call
// was successful
hr = pIMyComObject->GetUser
(
    nIdn,        // numeric identity (key) of the user (int type)
    &pIUser,     // returned .NET COM object
    &bstrErrMsg, // passed by .NET COM method
    &nErrCode    // passed by .NET COM method
);

The code here distinguishes between the (unexpected) errors encountered when making COM calls and (expected) application errors encountered within the called .NET methods. The (unexpected) COM errors may occur due to problems in the environment. For example, if the .NET COM assembly is not properly registered or missing a dependency, the GetUser call will fail. COM errors are detected by checking the HRESULT return code (in this example, the hr value).

But the code in the .NET COM method can encounter an error, too. It can be an unexpected (read, system) or expected (read, application) error. To handle all errors gracefully, I recommend trapping all logic in .NET COM methods within exception handlers. If a method encounters an expected error condition (e.g. the specified user is not found), it should return an appropriate error code (there must be a agreement between the C++ and C# code on the meaning of the error codes) and an optional error message. In case of unexpected exception (e.g. network error when the .NET code calls the backend), the .NET code should set an appropriate error message and return a generic error code (for different ideas on error handling and communication, read my Dissecting Error Messages article in the Dr. Dobb's magazine). Here is an abbreviated example of error handling:
if (FAILED(hr))
{
    // We could not even call the GetUser method.
    // Prosess HRESULT value and get COM error info.
    // Log retrieved error message.
    // Handle error condition.
}
else
{
    // At the very least, we know that we successfully
    // called the GetUser method. But the method itself
    // may have returned an error code and/or message.
    if (nErrCode == 0)
    {
        // Assuming that 0 code means success,
        // we can now acess properties of the pIUser
        // object via the IMyUser interface methods.
        // Do not forget to release this interface
        // when it is no longer needed.
    }
    else
    {
        // At this point we know that we were able to
        // call the GetUser method, but there was some
        // error or problem within this method.
        switch (nErrCode)
        {
            // Handle various error codes.
        }
  
        if (::SysStringLen(bstrErrMsg) > 0)
        {
            // Process error message (log it, or whatever)
            // Remeber to free it when it's no longer needed.
            ::SysFreeString(bstrErrMsg);
        }
    }  
}

I will not show how to use the pIUser object, because it is no different from any other COM object implemented in C++ or any other language.

The most confusing part involves accessing a collection (in our example, this collection is returned from a successful GetUserList call). To make it work, you need to do the following:
  • Define a variable of the type SAFEARRAY* (pointer to SAFEARRAY). You will pass the address of this variable (pointer to a pointer) to the method returning your collection.
  • Upon successful .NET COM call, check the data type of the SAFEARRAY members. If the method returns an array of objects (exposed as .NET COM interfaces), it's most likely that each member of the SAFEARRAY variable will hold an element of the type of VARIANT, IDispatch, or IUnknown interface. Once you detect the correct data type, convert it to a proper interface (in our case, IMyUser interface).
Here is an abbreviated example:
// Array of objects returned from .NET COM method
SAFEARRAY* psaUserList = NULL; 

hr = pIUser->GetUserList
(
    bstrMask,
    &psaUserList,
    &bstrErrMsg,
    &nError
);

// Process errors.
...
// The following assumes that the GetUserList call was successful.

// Data type of the elements of SAFEARRAY elements.
VARTYPE vt;

// Get data type of elements.
if (FAILED(hr = SafeArrayGetVartype(psaUserList, &vt)))
{
    // Cannot detect data type of SAFEARRAY elements.
    // Handle error and clean up.
}

// Check data type of SAFEARRAY elements.
if (vt == VT_VARIANT)
{
    // Each element of SAFEARRAY is a VARIANT.
    // Use a CComSafeArray wrapper class to process
    // elements of the SAFEARRAY.
    // Notice that it holds the VARIANT objects.
    CComSafeArray<VARIANT> saUserList;
 
    // Convert our SAFEARRAY into CComSafeArray.
    if (FAILED(hr = saUserList.Attach(psaUserList)))
    {
        // Conversion attempt failed.
        // Handle error and clean up.
    }

    // Iterate through all items in our collection.
    for (int i=0; (ULONG)i<saUserList.GetCount(); i++) 
    {
        // Use smart pointer to access user objects.
        // Notice that we retrieve the original object
        // from the appropriate member of the VARIANT
        // data structure.
        CComQIPtr<IMyUser> iUser = saUserList[i].punkVal;
  
        // We ccan now acess properties of the iUser
        // object via the IMyUser interface methods.
    }
}
else if ((vt == VT_UNKNOWN) || (vt == VT_DISPATCH))
{
    // All elements of SAFEARRAY are COM interfaces.
    // Use a CComSafeArray wrapper class to process
    // elements of the SAFEARRAY.
    // Notice that it holds IUnknown pointers.
    CComSafeArray<IUnknown*> saUserList;

    // Convert our SAFEARRAY into CComSafeArray.
    if (FAILED(hr = saUserList.Attach(psaUserList)))
    {
        // Conversion attempt failed.
        // Handle error and clean up.
    }

    // Iterate through all items in our collection.
    for (int i=0; (ULONG)i<saUserList.GetCount(); i++) 
    {
        // Use smart pointer to access user objects.
        // Notice that we retrieve the original object
        // directly from the array element.
        CComQIPtr<IMyUser> iUser = saUserList[i];

        // We ccan now acess properties of the iUser
        // object via the IMyUser interface methods.
   }
}
else
{
    // For other data types, add your own handling.
}

Now, was this fun or not?

See also:
Simplifying SAFEARRAY programming with CComSafeArray
SafeArray/idispatch issue
C# ATLCOM Interop code snipperts - Part 1
VARIANTS inside a SAFEARRAY