# Friday, June 20, 2008

Send-To with Vista

One of the tools I absolutely love in windows is the Send-To feature. Basically you can setup a list of programs which will show up whenever you right-click on a file and hover over the Send-To menu item.

I use this feature all the time as I developed a little ftp uploader which takes a file as a parameter and sends it to our corporate FTP site. Turns out in Vista they moved the location of this folder slightly. It's now in...

C:\Users\<username>\AppData\Roaming\Microsoft\Windows

I found this information on another developers blog. Good info!

http://geekswithblogs.net/dlussier/archive/2006/12/30/102366.aspx

#    Comments [0] |
# Saturday, May 24, 2008

Sourcegear Vault Issue

We recently began using the Sourcegear Vault Enhanced Client for Visual Studio. Intermittently we would receive errors accessing our Vault Server. Something to the effect of...

"The Vault server could not be contacted to perform the operation."

You'd try the operation a couple more times and eventually it would go through. After a bunch of digging I found a couple articles on the Sourcegear support forums that pointed me in the direction of the default proxy settings.

http://support.sourcegear.com/viewtopic.php?t=735

What was really interesting was that a> this happened usually when working offsite and b> it happened predominantly through the Visual Studio IDE Client... the normal Vault GUI was fine.

It turns out that this default proxy setting is stored in an app.config. When I compared the VaultGuiClient.exe.config with the devenv.exe.config (Program files\Microsoft VS 2008\Common7\IDE)  I found that the Vault GUI had specified to use the system proxy settings while Visual Studio had specified that no proxy existed.

Since changing the devenv.exe.config to match the vault gui config the issue appears to have disappeared. Here's what our new devenv config file looks like... note that the defaultProxy section is the important bit.

#    Comments [0] |
# Monday, April 14, 2008

The math behind Electronic Document Management

One of the key ideals behind Electronic Document Management is that it's supposed to save you money. The idea is that by eliminating some of the paper requirements you can cut down on supply and maintenance costs. It's one of those arguments that I've heard a number of times and to be honest I'd mostly ignored it.

My thought was that KNOWING you had electronic copies of each service order was well worth the investment and that the ongoing management and filing of these documents had such a time savings that the financial ramifications weren't as big a deal. Turns out I was wrong...

 

So here's the premise...

Each work order written inside of a Dealer Management System typically consists of 6 copies.

1 x Hard Copy approving the work.
1 x Technician Copy, so the tech's can note their work.
2 x Closing Copy, one for the customer, one for the dealership.
1 x Warranty Copy for the the manufacturer (if applicable).
1 x Accounting Copy, for the accounting system.


So, a store with 12 technicians doing 5 service orders per day would generate 360 documents per day.

12 techs x 5 service orders x 6 documents per service order = 360 documents


The same store, over the course of a year would generate almost 100,000 service documents.

360 documents per day x 5 days per week x 52 weeks per year = 93,600


Based on our experience each of these documents costs around 4 cents to print. When you take into account paper, toner, and printer wear and tear this adds up pretty quickly.

4 cents per document x 93,600 documents = $3,744 per year.


And these numbers are for an average sized shop!

I still believe that alot of the benefit behind electronic documents is the ability to better manage and store your information, but these kinds of figures do make a compelling financial argument.

#    Comments [0] |
# Thursday, February 28, 2008

You call that Snow!

Next time anyone complains about weather in Calgary I gotta forward this picture of a snow pile outside a Canadian Tire in Quebec... it was probably 50 feet high...

#    Comments [0] |
# Tuesday, February 26, 2008

Unit Test / Data Generation

I’ll admit that I have a love/hate relationship with Unit Testing.  Unit Testing has absolutely saved my bacon a number of times where a seemingly inconsequential change would have crippled our software. The reality is that the only way you can verify that those tiny changes don’t wreck havoc is to script your testing for known results. By having your build process validate those results you add a very strong safety net to your development process.

But… in most software systems there’s this pesky layer that throws a real wrench into the entire thing – it’s called the database.

The problem is this… a Unit Test is meant to be autonomous. It should be free standing and require no external dependencies. In reality the code you’re executing typically interacts with an existing database and performs INSERTS/UPDATES/DELETES to verify that certain functions still work. What get’s awkward is that the “Unit Test” database is typically an external dependency for your Unit Tests – it just has to be there be in the correct state or the Unit Tests will crash hard. Things like database schema changes, new testing datasets, and changing database locations really screw the unit tests up.

I’m going to describe a solution to this problem that we’ve been using for the last couple weeks. It’s worked extremely well by streamlining issues we had with databast style unit tests and by increasing our code quality. Everything here is based on Visual Studio 2005, nUnit, and nAnt but it’s more the concept that’s interesting.

How It Works!

We started off by adding a special project as part of each module called the Schema. Basically this is a simple class library with a bunch of embedded SQL scripts. These SQL scripts are responsible for taking a database and putting it into a known state for the Unit Tests. Execution of these scripts is done by a class called the SchemaManager, it has three methods which will become obvious in a minute.

The Unit Tests now add a reference to the Schema project. As a nUnit Setup Method we'll call out to a special class called the TestConfiguration. This TestConfiguration will be responsible for triggering the SchemaManager. Here's what a typical Unit Test in our UnitTest project would look like.

The TestConfiguration is a little more interesting. It uses a singleton pattern to create a SchemaManager, tell it to Drop the current Schema, and then Create it fresh. This executes the Drop Table/Procedure commands to clear out our database, and then uses the Create Table commands to make a fresh database.

Perfect! Now the database schema is in a state that our Unit Tests can work with – table are there, stored procedures are there, life’s good.

Now we need to create some canned data before we start our tests. Things like maintenance objects, customer codes, etc. are all expected to be in the database before our Unit Tests run so we need to create scripts in our UnitTest database which setup this data. Something like this...

We’ll embed this scripts into the UnitTest project and then change our TestConfiguration so that it gets the SchemaManager to insert this data after calling CreateSchema. We'll simply use the ExecuteResourceSql call we defined above and call it from our TestConfiguration.

And that's pretty much it! I think the beauty of this SchemaManager is that is makes the database a source-controlled resource. Instead of having some unknown dependency that the unit tests must rely on, the unit tests actually create their environment using scripts generated by the developer. If the developer breaks the Schema or the Business Logic, the unit test will catch it right away and any failed unit tests are expected to be logic errors instead of logistical problems between the development and unit test environments.

If you have any comments or suggestions on this area please drop me a line - it's a very interesting (and often underused) development practice!

PS - The foundation for a lot of this stuff is from a 4guysfromrolla posting, check it out for more details...

http://aspnet.4guysfromrolla.com/articles/040605-1.2.aspx

#    Comments [0] |
# Saturday, February 09, 2008

The Danger of Little Issues...

I came across a great article a couple weeks back about the danger of little issues... the foundation of this article was that every day we get interupted in ways that force us to change what we're focused on, deal with an emergency, and then re-focus back on the task at hand.

This articule suggested that these "shifts" cause us to lose more time then if we could just merrily work through one project at a time... makes sense, huh?  

What's really interesting is that this article suggested that the LITTLE things actually cause you more long-term grief than the big things. The reasoning was that when you come across a big issue you learn in a big way... and subconsciously take action to resolve it in the future. The problem with little issues is that they only take 1/2 an hour to resolve... and you become complacent in resolving them... twice a week... for a year.

 

Why is this worth mentioning? Today while setting up for our NADA trade show (www.nada.org) I ended up spending an hour trouble-shooting some file location issues on our demo server. It's a stupid virtual-drive issue that only occurs in certain environments and generally takes me about an hour to figure out.

The trouble is that we've grown complacent in spending an hour on this issue... instead of focusing on why we need a virtual-drive in the first place. If we'd reworked our pathing a year ago, I wouldn't get bothered by this every few weeks.

 

Once you identify the "Little Issue" it's all about committing yourself to resolving it... we're in mad-panic trade show mode right now so let's see what we can do after we get back from San Francisco...

To be continued...

#    Comments [0] |
# Monday, January 07, 2008

Cruise Control .Net / Queued Building

I just found an outstanding configuration element inside of cruise control which allows you to setup multiple projects to run in a queued environment. Basically it functions as a mutex so that while one project is building all other projects go into a queue until the first project is completed, and then another one is given control. The configuration element is really easy, here's our ccnet.config...

<cruisecontrol>

  <project name="Source Control" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <modificationDelaySeconds>10</modificationDelaySeconds>
    <sourcecontrol type="vault" autoGetSource="true" applyLabel="false">
      <executable>c:\program files\sourcegear\vault client\vault.exe</executable>
      <username>BuildUserName</username>
      <password>BuildPassword</password>
      <host>myDevtServer</host>
      <repository>Evolution</repository>
      <folder>$/Dvt-Root</folder>
      <useWorkingDirectory>false</useWorkingDirectory>
      <ssl>False</ssl>
      <setFileTime>current</setFileTime>
    </sourcecontrol>
  </project>

 

  <project name="Release Esenaar" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <tasks>
       <nant>
        <baseDirectory></baseDirectory>
        <buildArgs>-D:debug=False</buildArgs>
        <buildFile>Release.Esenaar.Build</buildFile>
        <buildTimeoutSeconds>1200</buildTimeoutSeconds>
        <targetList>
          <target>build</target>
        </targetList>
      </nant>
    </tasks>
  </project>
 
  <project name="Release Duvel" queue="ReleaseBuild">
    <workingDirectory>C:\Projects\dvt-root</workingDirectory>
    <triggers>
      <intervalTrigger seconds="180" />
    </triggers>
    <tasks>
       <nant>
        <baseDirectory></baseDirectory>
        <buildArgs>-D:debug=False</buildArgs>
        <buildFile>Release.Duvel.Build</buildFile>
        <buildTimeoutSeconds>1200</buildTimeoutSeconds>
        <targetList>
          <target>build</target>
        </targetList>
      </nant>
    </tasks>
  </project>

</cruisecontrol>

The first "project", called "Source Control" is actually responsible for downloading all our code from SourceGear Vault. You can see that every 180 seconds it downloads the source code from vault to a local folder called C:\Projects\dvt-root.

The second and third projects, called "Duvel" and "Esenaar" (maintenance release names), actually call out to our nant script and compile the appropriate release.

Now, our primary goal with all this is to make sure that we don't pull down source code while we're compiling a release (and vice versa) and that's where the queue property on the project comes into play. By setting the queue on all three projects to be the same thing, cruise control will not allow two projects to execute at the same time!

http://confluence.public.thoughtworks.org/display/CCNET/Project+Configuration+Block

#    Comments [0] |
# Monday, December 31, 2007

SigPlusNet Missing Module Exception

As part of our ongoing eSignature rollout we found that a smattering of client machines have issues when attempting to load the SigPlusNet.dll.

This dll is basically our interface to the signature pad itself and would fail with a FileNotFoundException. What was really strange was that the exception contained no information about the file it was trying to load. In addition, 95% of clients worked fine the first time. On the remaining 5% as soon as we started troubleshooting by installing Windows Updates or any other sample apps the error would simply go away.

After using a great little tool called FileMon (www.sysinternals.com) I found that the SigPlusNet.dll was failing on an attempt to find and load msvcr71.dll. Apparently msvcr71.dll is basically a set of C style application methods that are somehow used internally by SigPlusNet. Since this dll is pretty common it appears that on most machines it's installed by something else and so that's why on 95% of machines we had no issues.

Once I modified the install to include this dll, life is wonderful. A very strange unexpected dependancy...

 

#    Comments [8] |
# Friday, November 09, 2007

Drivers License Scanner

In our most recent release of Aristo Contact Management we've added support for a USB Drivers License Scanner. The basis of this project is that we connect this scanner to the local pc, integrate it into our customer screen, and then use the scanner to read customer information.

We've tried to make this a very simple process... after the user selects the Scan button the reader will whir and buzz as it attempts to pull information from the license. The reader itself accomplishes this by taking a picture of the license and then using text recognition (OCR) to separate the license into different fields we can populate our customer record with.

Once we read this information it automatically updates into the appropriate fields on our screen. In addition, because we're taking a picture of the license, we can also attempt to save a picture of the customer IF the regional license supports it.

At this point we support Canadian and US licenses and pull Name, Address, License and expiry fields.

Now, as a promotion for the first 5 clients who email me (and use Aristo Accounting and Contact Management) we're going to send you a drivers license scanner free! Quantities are limited so drop me an email at freeScanner@pbssystems.com and we'll contact the winners.

 

#    Comments [1] |
# Friday, September 21, 2007

Customer Alerts

Every now and then a project comes up that really tests the foundation of Aristo, our DMS product, and exemplifies how this foundation can provide us some very powerful functionality.

 

Couple weeks back, while working on Aristo Prospecting, we had a wish-list item to have an automatic alert show a sales person whenever one of "their" customers was in the dealership. The idea is that if you make a point of tracking down a customer when they're in for service you'll help to build your relationship with that client and increase the likelihood of them returning to look at a new vehicle in the future.

 

After reviewing this concept for a couple hours we came to a startling conclusion... our application already allowed for this! The basis of this was the Customer History, a listing of all Open and Closed activity for this customer. You can see it here on the right side of the screen.

 

 

Well the idea of a Customer Alert leverages on this really well - instead of grabbing a customer and looking at all their activity, we just need to change our query and grab all Open items for the dealership, and only show them if I have a relationship with that customer! To accomplish this we add the idea of User Roles.

 

Each customer can have any number of Users associated with them as either a Sales Rep or an Account Manager. These users now need a simple gauge on their desktop to show them when this Open activity applies to them. Enter the Customer Alerts Gauge!

Again, you can click on these items to get right back into that customer activity. We now have a very simple and powerful tool to help our clients build customer relationships. And all this without a huge amount of development effort! Our Aristo Contact Management dealerships will get a general roll-out on this feature in the next few weeks, hopefully this blog entry will give them a sense as to what it can be used for.

#    Comments [0] |