# Monday, December 08, 2008

Absolutely Awesome!

We have a huge bank of legacy code written in vb6 that we're slowly porting over to dot net. One of these components that's getting shuffled over this week is our Invoice Printing functionality.

Previously this logic was written in Data Dynamics Active Reports 1.0 (COM based) and we're looking to upgrade this to Active Reports 4.2 (Dot Net 2.0). A quick plug, Active Reports is an absolutely awesome tool for designing and developing business reports. Even their COM-based 1.0 model shows a ton of insight into HOW we should be developing reporting applications.

Anyway, we're going to have to re-write some code as part of this process but the one component that would be nice to pull across is the "design" surface. This basically consists of all the controls and layouts. If we have to re-design this from scratch we're going to miss positions, fonts, etc so it's better to automate this piece if we can. Here's what it looks like...

Now, Active Reports supports a common design layout for AR2.0 to AR4.2, sort of a XML-based layout language they call RPX. If you can save a report layout into an RPX you can load it back later on. Trick is that our reports are AR1.0 and that old version uses a different binary format for saving layouts. I need to somehow upgrade these from AR1.0 to AR2.0 before I can save them into the common format.

Turns out this is easier than you'd think. The vb6 report design files are seperated into two components... a binary .DSX file and a text .DSR file. If you crack open the DSR file the first bit of "code" specifies which tool "manages" the resource. That's what the big ugly guid is. By changing this guid from AR1.0 to AR2.0 we can fake VB6 into thinking it's dealing with an AR2.0 report.

   

Now, when we open up the designer in vb6, we have the option to save the report layout by using the File, Save feature within the report designer. Likewise in dot net we can use the Report menu item to Load a saved layout. We've managed to save ourselves all the work in positioning, sizing, and configuring all the controls behind this active report!

 

Now, all this effort to avoid recreating some controls... worth it? To me it is. The problem with me redesiging these reports is that...

1. I'm not that great of a detail guy. Not bad, but not great. I'm positive I'd screw something up. And it may not be a huge deal to the first 20 stores that get this upgrade but at some point that change in field size would be a critical concern to some store. If I can avoid the issue altogether that's a good thing.

2. I get bored easy. I'd copy probably 5 controls before I'd get distracted and switched over to something else. I'll bet you it would take me a week to get this one report copied over. By converting the entire report in one pass I've moved the project to the point where I can have someone else take over the loading of data.

#    Comments [0] |
# Tuesday, November 04, 2008

SQL Server Collations

For some strange reason, our software requires SQL Server to run with a specific collation. Basically the collation specifies the "order" in which text data is stored and has an impact on how indexes manage and search through large amounts of data.

Our issue comes up when the DATABASE collation doesn't match the SERVER collation. We'll get something like this...

SqlException cannot resolve the collation conflict between 'Latin1_General_CP1_CI_AS' and 'SQL_Latin1_General_CP1_CI_AS'.

All I can tell you from this exception is that the two collations don't match and our software won't run. Essentially we have to re-install sql server to reset the collation on the server so that it matches the database.

You'd think this would be a pretty easy configuration option during the sql server install... not so. During the sql install you do get a prompt to choose the server collation but the list is language based... nothing mentioning SQL_Lation1_SomethingOrRather.

There is an option on there for legacy collations, since our app was developed on an older version of SQL Server this would make sense, but again nothing mentioning SQL_Latin1.

Well, turns out that the option for "Dictionary order, case-insensitive, for use with 1252 Character set" is actually equivelant to our SQL_Latin1 collation and once the database server comes up sure enough it's been configured properly.

Tricky config setting but at least now we'll know what to look for on new installs. I'd still love to know WHY we need to run with that specific setting...

 

#    Comments [2] |
# Wednesday, October 29, 2008

Aristo Instant Messenger

We just added a cool new feature to our aristo framework, embedded instant messaging! Pretty typical feature but here's what our gui looks like.

 

Now when we first heard requests for this component I was a little skeptical. It's pretty much a given that at some point ALL software applications get a request to add an instant messenger and email capability; you could be programming a calculator and eventually you'll get this request. Our I.M. does have a couple key differences.

   1. This is an internal only application. Staff can't be chatting to their friends and family through this messenger.

   2. This is an automatic application. Users don't have to start another app to get the messenger going. It's always on when they're in PBS.

   3. This is an embedded component.  Because we're running in a Terminal window we have to work whithin our existing UI space (aka the terminal window, no extra desktop apps allowed).

   4. Because we're embedded there are some very cool extensions we can add for sending "information" in our software between users. More on this in the next couple weeks.

 

Here's a quick primer on how this works.

Users now have a messenger icon in their system tray whenever they start Aristo. At login this icon will notify users that they are connected to the aristo messenger (this notification will also point out the fact that there is something new in their software).

Users can right click on this icon to either send a message to a specific user or send a broadcast message. Message windows are pretty much like any other I.M. solution and can be minimized while users are doing actual work. New messages cause the conversation windows to highlight until the user views them.

The more interesting aspect of this component will be HOW we can use it as a tool within our software but we've definitely heard this request a lot and our users should be happy to see we've reacted.

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

Couple t-sql tricks

I came across the need to do some t-sql work prior to our annual dealer conference next week. The short version is that we need to sanitize our customer data by replacing customer pictures with some stock photos of people around PBS. I certainly didn't want to have to manually change every customer record so I figured a gigantic t-sql script to update everyone would be a huge help.

Now I gotta admit - this is not the kind of component I normally work on.  Database administrators tear through these kinds of apps but when you're a bit more of a generalist you need to be pretty good at googling the right kind of questions.

Anyway, here's the requirements...

1. Update every customer record with a new photo.
2. Choose the photo from a subset of 10 or 12 stock pictures.
3. Try to make sure that "consecutive" customer records don't have the same photo.

The first thing that takes figuring out is how to load an image from a file into a table. For some reason google-ing this didn't do too good. In the end it's pretty easy. The following command loads an image file into a blob-style object for use in t-sql...

SELECT * FROM OPENROWSET(BULK N'c:\creek.jpg', SINGLE_BLOB) as i

Note that you need the rowset descriptor "as i". Otherwise you'll receive some error about corelations.

Next I wanted to build a temporary table of customer id's and picture id's. Something like...

Customer1 Picture1
Customer2 Picture2
Customer3 Picture3
Customer4 Picture1
Customer5 Picture2
...

This would make a somewhat random picture list where at least adjacent customers wouldn't have the same picture. I accomplished this using the ROW_NUMBER() function against our customer code's.

INSERT INTO #Links (ContactId, PictureId)
    (SELECT fldId, ROW_NUMBER() OVER(ORDER BY fldCode) % @Image_Count
    FROM tblContacts)

Once we've got these two pieces together we can generate our test data pretty reliably. Here's the final sql script ...

DECLARE @Image_Count int    SET @Image_Count = 2

CREATE TABLE #Links (
    ContactId uniqueidentifier,
    PictureId int
)

INSERT INTO #Links (ContactId, PictureId)
    (SELECT fldId, ROW_NUMBER() OVER(ORDER BY fldCode) % @Image_Count
    FROM tblContacts)



UPDATE tblContacts SET fldImage =
    (SELECT * FROM OPENROWSET(BULK N'c:\creek.jpg', SINGLE_BLOB) as i)
WHERE fldId IN (SELECT ContactId FROM #Links WHERE PictureId = 0)

UPDATE tblContacts SET fldImage =
    (SELECT * FROM OPENROWSET(BULK N'c:\dock.jpg', SINGLE_BLOB) as i)
WHERE fldId IN (SELECT ContactId FROM #Links WHERE PictureId = 1)



DROP TABLE #Links

#    Comments [0] |
# Sunday, August 24, 2008

Final Cut!

Finally - bathroom is finished. Today was just installing the light fixture and patching a couple rough spots on the walls. As of tonight all the tools are back in the garage and everything's done! Couple thoughts...

1> When installing drywall, cut your openings smaller then req'd and then make them larger once the drywall is in place. Avoids patching later on when you're trying to finish things like electrical.

2> Tub surrounds rock. Way easier than tiling and actually look pretty classy once in place.

3> While it's good to focus on details, don't sweat them too much. We could have patched those drywall corners till the cows came home. Once they've been painted and the room is filled up they look outstanding. Better than most of the corners in our house.

 

#    Comments [1] |
# Sunday, August 10, 2008

Day 3

Got the vanity and shower finished today! All that's left is the ter-lette and we're done!!

#    Comments [4] |
# Wednesday, August 06, 2008

Day 2...

Tile's down. Good progress today.

#    Comments [0] |
# Saturday, July 26, 2008

Bathroom Progress

Despite ongoing concerns that our bathroom will never be done we made outstanding progress today. Finished painting; 4 coats because of the mold problem - 2 coats kilz sealer, then 2 coats kitchen and bathroom latex paint). Also finished installing a new subfloor for the tile (composite backer board called Easyboard instead of the 40 year old particle board). Starting to look good!

 

#    Comments [0] |

Work Note - Aristo F&I

Quick note that Aristo F&I went into pilot last wednesday!

#    Comments [0] |
# Monday, June 23, 2008

ASP.Net Web.Config Impersonation

I found something interesting on one of our test boxes today. Our generic web listener uses a web.config file to impersonate a user with enough security access to perform basic file i/o as well as some database stuff. This impersonation command is pretty simple. Here's our web.config below...

<configuration>

   <system.web>

      <authentication mode="Windows"/>

         <identity impersonate="true" userName=".\SomeUser" password="SomePassword" />

   </system.web>

</configuration>

Note how we use .\ to indicate what I thought was the current domain... it's not!

Turns out that .\ refers to the current computer... and if you're running on a domain controller it's no big deal - the domain controller is the current computer. However, on the 1% of servers we manager where our box is not the domain controller we need to manually add an extra user account to the local machine for this account. As long as this account has sufficient security our lister works like normal!

And it's amazing that there's no documentation on this .\ component anywhere on the web!

#    Comments [0] |