Monday, July 18, 2005

CodeSmith to MyGeneration converter

This is interesting: The guys at MyGeneration Software (the 2-man collaborative effort with the great FREE code generator, O/R mapping tool, and architecture product) have a CodeSmith-to-MyGeneration Converter available (CodeSmith is a well-known code generation tool by Eric J. Smith et al, that sports an ASP-like syntax for its templates).

SQLCLR and Serialization

I was playing around with SQLCLR and found a scenario that confused me for a long time:

I created a small class library that contained two classes. One class instantiates the other class, which is marked as Serializable. A public method of the parent class serializes the child class using a BinaryFormatter, and returns the resulting byte array. Simple, right?

Well, I imported this class library as an assembly into my SQL Server, and was able to use the Safe permission set without a problem.

I then proceded to create a CLR Stored Procedure using Visual Studio.NET 2005 that would instantiate the parent class from my previous library, and invoke the method that would serialize the child class. I built the project, had VS deploy it to my SQL Server, and then I tested the stored proc in Management Studio.

It blew up with an error resembling the following (some names were changed to protect the innocent):

Msg 6522, Level 16, State 1, Procedure Z_Start, Line 0A .NET Framework error occurred during execution of user defined routine or aggregate 'Z_Start':

System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.System.Security.SecurityException:

at System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride)

at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark, PermissionType permType)

at System.Security.CodeAccessPermission.DemandInternal(PermissionType permissionType)

at System.Runtime.Serialization.Formatters.Binary.ObjectWriter..Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)

at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)

at Namespace.ParentObject.Serialize()

I played with everything that I could think of, changing the permission set of my first class library from SAFE to EXTERNAL_ACCESS to UNSAFE. Nothing worked. To me, it seemed like a bug (and I even filed a bug report).

Turns out to be a problem with this developer. Though I played around with the permission set of the one class library, I was totally forgetting that the stored procedure's assembly has its own permission set too. I was using VS to deploy the assembly, so I wasn't concerning myself, per se, with what VS was doing with it. Come to find out, that by default, VS marks SQLCLR projects as SAFE. In order to use Reflection (which the BinaryFormatter uses when serializing objects), you need at least EXTERNAL_ACCESS permissions on ALL assemblies in the call stack, not just one or the other.

A quick trip into the project's property page allowed me to change the stored procedure assembly to EXTERNAL_ACCESS, and then my test worked as expected. Credit to Erland Sommarskog (who reviewed my bug report and posted that EXTERNAL_ACCESS worked for him).

Now onto more playing around....

Sunday, July 17, 2005

My Impulse Buy

I stopped in at the local Guitar Center this evening, and walked out with a Yamaha FG730S. I normally don't buy something without reviewing it in depth beforehand, but, this was different. This was impulsive. And, dammit, this sounds NICE! Especially compared to the no-name that I was previously plucking.

I see that it's a highly rated guitar, but I couldn't tell you anything about it for sure. All that I really know is that I walked out with a Yamaha. But, that's kind of like saying that I went to a car dealership and drove away in a Ford. Was it a Focus, Freestar, F-150, Mustang, or Crown Victoria? No clue, but it sure does drive nice!

My only real requirement that I told the sales guy was that I needed something easy to fret. He gave me this, and I loved it.... Though, I probably would have loved anything that he put into my hands at that moment. We'll see. It was only $300. I'll just eat PB&J for lunch this month.

Thursday, July 14, 2005

SQLCLR and Events

I'm still trying to figure out all of the ramifications of creating Assemblies in SQL 2005 that are marked Unsafe. Seems like the easiest way to get things done, but that's probably not the best way to think of the "Unsafe" permission set.

One of my libraries that I attempted to import today had some events in the object model, and SQL Server didn't like that (I was trying to mark it as a Safe Assembly) because the add_xxx method that the compiler tacks on for events is attributed as Synchronized, and apparently, explicit synchronization is bad, or otherwise unsafe, as far as SQL Server is concerned.

In my case, the events were simply part of an Observer pattern, and I was looking for a callback mechanism to alert the parent when something particular occurred in the child. I managed to get the code working using straight delegates (i.e., only 1 "event" handler would be allowed), and then SQL Server let me create the Assembly and mark it as Safe.

I'm probably making this more complicated than it needs to be, but I can't tell what's my fault and what is the fault of the beta software.

Playing around with SQLCLR

I had a lull in my assignments yesterday, which gave me a great opportunity to familiarize myself with SQLCLR (creating stored procedures, functions, triggers, and other SQL Server objects using .NET).

From the outside, the concept seems very cool (i.e., you can write everything in .NET code). But, a closer look shows that this is more similar to being a layer that just happens to run on the database to augment native database code instead of a full-fledged replacement for the database code.

Creating a CLR Stored Procedure is definitely a trick that you want to save for times when T-SQL just won't work, or would be overly complex. SQLCLR probably would not be appropriate for your everyday CRUD (Create, Read, Update, Delete) stored procs which are easily created using traditional methods. But, if you have some semi-complex processing, for example, where you need to do some looping (i.e., a for-loop or a while-loop), then a CLR Stored Procedure would definitely be appropriate.

Think about this:

The .NET code does not have native access to the database, like T-SQL does. As a result, the .NET code must still use ADO.NET to execute T-SQL in order to access data. So, since you never actually get away from T-SQL, you should probably plan to still create T-SQL stored procedures to access from your CLR stored procedures whenever possible (i.e., CRUD procs that your .NET code requires instead of building SQL in strings inside your code).

I also discovered a bug yesterday while trying to access CLR stored procedures from OSASPADO ("oh-SAS-pah-doh", or Old-School ASP/ADO), which was confirmed by Bob Beauchemin.

Don't misinterpret this post as thinking that SQLCLR is lackluster. It's an awesome addition to the SQL Server platform. But, it's very important to understand its limitations and design your systems around them.

Tuesday, July 12, 2005

Internet Explorer Printing without Clipping Tool

Scott Hanselman posted today about FinePrint, which is an abstraction layer between the application and the printer driver. Your application renders the output to FinePrint's virtual printer driver, and then you can manipulate the results before they get sent to the actual printer (i.e., so that you can print multiple pages on one sheet of paper, play with margins, capture the printed output to the clipboard as a graphic, and other neat stuff).

I raised the question in the comments about whether or not a tool existed that would print web pages without the dreaded right-side clipping of text/graphics. Sure enough, there is!

Kent Chen posted this link, and he also has a blog entry describing it (which in turn, points to a blog entry, etc). Thanks for the heads-up, Kent!

IE Fitted-Width Printing: http://www.visiontech.ltd.uk/software/#IEPrint

But, the best news is that it appears that the IE7 team is working on adding this type of functionality right into Internet Explorer. AWESOME!

VirtualPC Problem/Tip

Every now and then, I'll launch a Virtual Machine using VirtualPC, and the screen will not change (does not refresh). I can move my mouse, but the VPC's pointer remains frozen. If I minimize the VPC window, and then restore it, the picture updates, but still remains static (so I know that the VPC is working, and it's just the screen that is not updating).

This problem seems to be related to power saving modes of my laptop. I almost never shut my laptop down, but rather just use the sleep function that kicks off when I close the display. If I leave a VPC running when the laptop sleeps, then I can almost guarantee that the screen problem will occur. However, sometimes, it occurs even when VPC (or the VPC console) is not running.

I found that when this occurs, that I can "fix" the problem by shutting down all VPC sessions (saving state, if appropriate) and then closing the VirtualPC Console. Next, start the VirtualPC Console again, and then start the VPC, and voila! Should be fixed.

This is a lot better than my old fix, which was a total system reboot.

Monday, July 11, 2005

Real World Endianess Example

With gasoline being a commodity, my brand loyalty is non-existent. Whichever station has the lowest price gets my dollar (or actually, as of this morning, my $2.34 per gallon). Oh, and the gas station MUST have pay-at-the-pump, else I don't patronize them.

One itsy-bitsy problem with bouncing between different gas stations and using pay-at-the-pump is that you have to figure out which direction to swipe your credit card in order for the pump to read it.

Sometimes, the stripe has to go to the left, sometimes to the right, and some pumps have cool readers that can read the card in either direction. I find that I always have to look at the little picture on the pump, turn my body (mentally) while holding the credit card so that my name is facing me, and then insert the card into the machine as indicated in the diagram.

Doing so this morning, I realized that this is very similar to the Endiness issue that exists with today's microprocessors. The credit card has one side that is the most significant (the side with the magnetic stripe). Inserting a card into the reader the wrong direction results in the card not being read.

Likewise, when a computer reads a value from its I/O, it expects the bits of the value to be arranged in a certain order. If the order is reversed, then a wrong value will be read in, which can have some pretty bad consequences. Some processors are "Big Endian" (i.e., Motorola), some are "Little Endian" (i.e., Intel), and some can be switched to handle either type of Endianess (i.e., ARM, PowerPC, etc). This is where I draw the parallel to the card readers at the gasoline pumps.

Saturday, July 09, 2005

Self heating coffee

As covered on Slashdot, here's a guy who took apart a self-heating coffee product to see how it works.

Interestingly, the source of heat comes from Calcium Oxide, which is also known as Quicklime. Basically, if you take some calcite limestone (Calcium Carbonate, that's the bedrock where I live) and heat it for a long time, it turns into Quicklime (and in the process, releases Carbon Dioxide). Add water to Quicklime, and I *think* that it turns into hydrated lime (Calcium Hydroxide?), but in the process, gets very hot.

The self heating coffee apparently has about 8oz of Quicklime powder packed into a chamber of the cup itself, and when activated, water is introduced into the Calcium Oxide, creating the chemical reaction.

In high school Chemistry class, we made Quicklime, and our teacher then instructed us to hold a small piece on our hand and add one drop of water. We learned "first hand" what an exothermic reaction was!

Friday, July 08, 2005

My Name was beside Rockford Lhotka's

I pulled out a book today that I served as one of the Technical Reviewers for (Professional Visual Basic 6 - The 2003 Programmer's Resource published by Wrox Press ISBN 1-86100-818-X), and looked again at the credits page (just to see my name in print, if you have to know), there was Rocky's name under the category "Original Material" and also "Additional Material", whatever that means. He also wrote the book's Forward.

Now if only I knew who Rocky was back in 2002/2003...

Wednesday, July 06, 2005

Word Wrap Version 2

I played around with the word wrap algorithm for a little bit, and came up with the following. I think it's better than my previous code, and simply inserts breaks into a string builder that already contains the text that needs to be split.

One challenge for my scenario is that my text might already have some line breaks in it, and I need to preserve those. Also, the text might have some indenting at the beginning of the line (i.e., spaces after the new line character), and it would be wrong to trim those out.

StringBuilder sb = new StringBuilder(text);

int lastBreak = -1;
int newBreaks = 0;
int lineStart = 0;

for (int i = 0; i < text.Length; i++)
{
if (text[i] == ' ')
{
lastBreak = i;
}
else if (text[i] == '\n')
{
lastBreak = i;
lineStart = i + 1;
}
if (i - lineStart + newBreaks >= m_width)
{
newBreaks++;
sb.Insert(newBreaks + lastBreak, "\n");
lineStart = newBreaks + lastBreak + 1;
}
}

Console.Write(sb.ToString());

Line Break/Word Wrap Algorithm

Anyone know of a good Line Break/Word Wrap algorithm? Word Wrapping is something that I take for granted, since most Windows UI elements take care of it for me (i.e., textbox, web browser, etc).

I wanted my console application to wrap at 80 characters, but my 5 minutes of searching didn't return anything especially useful or simple.

I wrote the following, but I'm sure it can be done better somehow:


string[] blocks = text.Split("\n".ToCharArray());

for (int i = 0; i < blocks.Length - 1; i++)
{
if (blocks[i].Length < m_width)
{
Console.WriteLine(blocks[i]);
}
else
{
int j = 0;
while (j < blocks[i].Length)
{
string tmp = blocks[i].Substring(j).TrimStart();

if (tmp.Length > m_width)
tmp = tmp.Substring(0, m_width);

int k = tmp.LastIndexOfAny(",.?!- ".ToCharArray()) + 1;

if (k == 0)
{
k = tmp.Length;
}

Console.WriteLine(tmp.Substring(0, k));

j += k;

}
}
}


By the way, there's an improved version at:

http://jasonf-blog.blogspot.com/2005/07/word-wrap-version-2.html

MyGeneration

A peer of mine (Justin) from another branch of my company has written a kick-ass code generator along with another ex-employee of my company (and old MS employee, if I remember correctly).

MyGeneration continues to receive accolades and favorable reviews. The best part, is that it's Free!

Check it out!

Excel Database

Once again, I was given a "database" implemented using Excel that I now have to use as a regular import data source. Sigh.... And inevitably, users will start to insert columns into the already established spreadsheet layout, and I'll get the call when the import fails.

Rory has already covered this corporate-world trend in just about the funniest (and relevant) comic that I've ever read:

http://neopoleon.com/blog/posts/434.aspx

or all of his blog's comics:

http://neopoleon.com/blog/category/16.aspx

Tuesday, July 05, 2005

ZMachine Continued

My little project of writing the ZMachine interpreter class in C# continues. Let's just say that I'm able to play story files now! One step closer to my goal (why am I doing this labor of love? I'll explain at a later time, but let's just say that it should be a cool demo of something).

THE HITCHHIKER'S GUIDE TO THE GALAXY
Infocom interactive fiction - a science fiction story
Copyright (c) 1984 by Infocom, Inc. All rights reserved.
Release 59 / Serial number 851108

You wake up. The room is spinning very gently round your head. Or at least it would be if you could see it which you can't.

It is pitch black.

>turn on light
Good start to the day. Pity it's going to be the worst one of your life. The light is now on.

Bedroom, in the bed
The bedroom is a mess.
It is a small bedroom with a faded carpet and old wallpaper. There is a washbasin, a chair with a tatty dressing gown slung over it, and a window with the curtains drawn. Near the exit leading south is a phone.
There is a flathead screwdriver here. (outside the bed)
There is a toothbrush here. (outside the bed)

>get up
Very difficult, but you manage it. The room is still spinning. It dips and sways a little.

>take gown
Luckily, this is large enough for you to get hold of. You notice something in the pocket.

>wear gown
You are now wearing your gown.

>open pocket
Opening your gown reveals a thing your aunt gave you which you don't know what it is, a buffered analgesic, and pocket fluff.

>eat aspirin
You swallow the tablet. After a few seconds the room begins to calm down and behave in an orderly manner. Your terrible headache goes.

>get all
telephone: You pick up the receiver. A moment later, the dialing tone is suddenly cut off. Glancing through the window you can't help but notice the large old oak tree of which you are particularly fond crashing down through the phone cable.
flathead screwdriver: Taken.
toothbrush: As you pick up the toothbrush a tree outside the window collapses. There is no causal relationship between these two events. Shouldn't you be taking more interest in events in the world around you? While you've got it...?

WAHOO!

I just found a bug in my ZMachine interpreter that I've been trying to track down for the last 5 days or so. Not that it will mean anything to the casual reader here, but I coded the STOREW opcode to use address ARRAY + byte_index, when really it was ARRAY + (2 * byte_index). My LOADW was correctly coded.

So, as I ran HHGG.Z3, I would get to the first prompt just fine, but my "TURN ON LIGHT" would always result in "I don't understand that".

Now I can finish implementing the opcodes.....

Monotony

I'm a consultant. I travel from client to client, gig to gig, solving their problems and writing software for them to use internally.

And you know what 80+% of that work turns out to be? Pulling data out of a database and displaying it on a web site. EVERYBODY needs this, and this is what every interactive system does.

At an abstract level, every client gets the same system that I previously wrote for a different client. It's their DSL (Domain Specific Language) and other nuances that makes templating the previous system somewhat of a challenge, and is what guarantees my continuing revenue.

I can't tell you how many times I've sat in elaborations where the client thinks this is some kind of novel approach to business, and they're so excited about getting started. But, to me, it's busy work. It's boring. It's been done before. It's old school.

Wanna know a secret? I have to invent new ways of doing things just to keep my mind from imploding on itself. Sometimes, they work, sometimes they don't. Luckily, in the latter category, I have previous successful implementations to recall when I'm in a time crunch.

So, the end result is that my customers are actually paying for innovation for my own selfish reasons, but think they're just getting a vanilla pull-data-from-a-database-and-display-on-a-website system.

Thursday, June 30, 2005

More Google Earth

I've just been giddy about Google Earth (new name for the old Keyhole), and it seems like every time I play with it, I discover more and more of the featureset (yeah, I know, RTFM, but it's way more fun to discover features than to read about them beforehand).

Two things totally blew me away today. Actually three, but two of them are combined.

1. 3D buildings: I turned on the checkbox for "3D Buildings", and it streamed in some shapes for buildings in selected metro areas. Big whoop, I thought, as I saw these gray shapes start to cover up the areas of my map. But then I discovered that you can tilt the camera view, so that instead of just looking straight down, you get a perspective view, and then the 3D Buildings really make sense, because you get a skyline representation of a cityscape instead of just a flat map. WAY COOL!

2. Terrain: Living in NW Ohio (and that's what I've spent a lot of time panning around), you don't get the feel for what the "Terrain" option does. But, head out to the Grand Canyon (use the Sightseeing link to automatically fly out there), use the tilt mode with Terrain turned on, and you'll see why this is the best thing in the world! Pick a spot with a lot of geographic features (dramatic elevation changes), and spin around it. The underlying elevations are displayed in 3D!

http://earth.google.com/images/grandcanyon.jpg


TO MICROSOFT FLIGHT SIMULATOR TEAM: If you haven't started already, then you MUST implement this functionality into your scenery! This is what FS is currently lacking! There's no longer any acceptable reason for why I can't fly over an area of the country and not see real imagery (Keyhole, and now Google Earth, proved that point).

Wednesday, June 29, 2005

Carl Franklin Songs: Oldies

So, [obligatory Redmond introduction] I was going through my basement this evening, and came across the box of stuff that I've kept since we moved offices a couple of years ago. In the box was my copy of Visual Basic 4.0 Internet Programming by none other than Carl Franklin.

What I was most interested in was the CD, because I remembered that Carl had included a couple of audio tracks along with the book's data, and I had only listened to the CD once before sometime around 1997. As a regular listener of Toy Boy (i.e., at the beginning and end of every DNR episode), I've gained a certain appreciation for the Sounds o' Franklin.

Anyways, the CD includes three tracks: St. James Infirmary, Bear, and The Last Steam Engine Train. As a beginning guitarist myself, who still finds it hard to go from a G to a D without pausing whatever song I'm struggling to play, I'm absolutely amazed at Carl's abilities when I listen to The Last Steam Engine Train. But, I think of these three, I like Bear the best, which Carl notes as being an original.

Ring Tones

As I sit here, coding and listening to DNR episode 55 (Kevin McNeish), I hear someone's cell phone ringing on their desk--even through my big headphones.

Seems this guy sitting next to me just got up and walked away, leaving his phone behind. Meanwhile, the caller probably thinks that my cubicle neighbor is ignoring the incoming call, so continues to call back. Over and over and over and over.....

This in itself is not that irritating. The phone's ringtone, however, is! Let's just say that I now cannot get the Pink Panther's themesong out of my head.

And thinking about that, I've noticed over the past couple of months that it seems that an unusually high number of people around here have this same ringtone. At first, I thought it was a cultural thing, since most of the time it seems like it's a H-1B employee who is in posession of the Pink-Panther-Squawking-Cell-Phone.

Then, it dawned on me that it's probably more of a reflection of my client and who their mascot is. I'll leave it as an exercise to the reader to figure out who my client is.

Include Namespaces in Sample Code

To people providing code examples: Please, please, please include the class's namespace in your code (use fully-qualified classnames). For example, instead of x=new XmlDocument(); use x=new System.Xml.XmlDocument();

It's easy for someone to put a "using" at the top of a code block, but most people posting sample code on the internet only paste snippets of code, and without having the "using" blocks, we have no idea which namespace the objects belong to!

So, unless the class comes from the System namespace, include the fully-qualified classname in your code. It will go a long way to helping people read and understand your code snippets.

Note to self: Make sure that I use fully-qualified classnames in all of my sample code.....

Northwest Ohio .NET User Group

I discovered that we (Toledo) had a local .NET user group after the spring MSDN event a couple of months ago. Last night, I had the opportunity to attend an actual meeting to see what it's all about.

The speaker was member Joseph Poirier who gave a presentation surrounding some of the process and difficulties that he encountered while developing a mobile dispatch application (that runs on an Intermec PPC). The lessons learned were probably useful, but Joseph made the fatal mistake of installing VS2005 beta 2 on his presentation machine that same day, and not verifying that the application that he was demonstrating correctly ported over to the new environment.

One thing that I learned, realized, or at least started thinking about, is the need to properly secure passwords in XML config files. Typically, I don't store passwords in this manner, but then again, I remember having some connection strings in plain text, which is probably a bad practice.

The decision to make is whether to fully encrypt the string using a strong encryption (System.Security.Cryptography namespace), or to perform your own encryption which is just strong enough to keep prying eyes from discovering the contents.

An algorithm to do the latter may resemble:

1. Convert string to byte array
2. Reverse bytes
3. For each byte in array, XOR the value with (A5H + byte index)
4. Store the Base64 of the byte array in the config file.

The benefit of this approach is that it's just strong enough to be effective, does not require complex code (not many people know how to use all of the Cryptography classes, myself included), and may be faster (I haven't benchmarked anything, so please flame away if this is not true).

// Encrypt/encode a string
string plaintext = Console.ReadLine();

byte[] arry = System.Text.Encoding.ASCII.GetBytes(plaintext);

Array.Reverse(arry);

for (int i=0; i < arry.Length; i++)
{
arry[i] ^= (byte)(0xa5 + i);
}

string base64 = Convert.ToBase64String(arry);

Console.WriteLine(base64);


// Decrypt a previously encoded string

byte[] newarry = Convert.FromBase64String(base64);

for (int i=0; i < newarry.Length; i++)
{
newarry[i] ^= (byte)(0xa5 + i);
}

Array.Reverse(newarry);

string newplaintext = System.Text.Encoding.ASCII.GetString(newarry);

Console.WriteLine(newplaintext);
Console.ReadLine();

Tuesday, June 28, 2005

Google Earth

As a followup to my "Hunt for WMD's" post, be sure to check out Google Earth:

http://earth.google.com/

Google Maps is an awesome web application. But, if you're already connected to the web, and have a decent machine (with 3D graphics card), then load up this Lite version of the old Keyhole product, and enjoy all of the benefits of a rich desktop client!

At some point, Microsoft needs to stop trying to compete with all products. Competition is great for innovation, but I'm not sure if they can catch up with the GIS stuff that Google now has (especially after their aquisition of Keyhole).

You, Too, Can Help Search for WMDs in Iraq

Not sure what the date of the satellite images are, but now Google Maps has the world online!

Here's Baghdad from way up:

http://maps.google.com/maps?ll=33.318787,44.338074&spn=1.392517,1.944580&t=k&hl=en

Monday, June 27, 2005

MSDN Lab

Just found this. I'm guessing that it's MSDN's answer to Google Labs where new technology can be previewed before it's made mainstream. I hope to see some great stuff hosted here in the future.

http://lab.msdn.microsoft.com/

Feedburner Now Active

I'm trying out Feedburner for my blog's syndication:

http://feeds.feedburner.com/AViewInsideMyHead

Blogger.com provides an ATOM feed automatically (which Feedburner then consumes), but I get no stats with that. If you currently subscribe to my old feed, please update to use the new Feedburner feed (look for the XML link in the sidebar).

I have no idea at the moment if anyone using news aggregators even read my blog. Most of the traffic that I'm aware of comes from the major search engines.

I admit that my readership is likely very low, but I still write as if some time in the future, I'll get a lot of people wanting to read my past thoughts on various subjects. I think that this is the hallmark of a good blogger, especially one trying to establish a foothold in readership numbers--envision who your audience is, and then write for that audience, even if it does not exist today.

Sunday, June 26, 2005

More Cedar Point Rides

Today was our third visit to Cedar Point this season. Hot day, long lines... :( The babies got cranky after 3 hours (2 hours past their nap time), so we had to leave. We realized that, in the future, we'll probably just have one of us take the twins out to the van for a nap, and likely to relocate the vehicle to a closer parking spot at the same time. This way, the whole day isn't cut short after only a few hours, and my 7-year old and the other adult can still stay in the park.

But, we didn't leave before I got to ride a couple of things, so I'll add to my mini-reviews:

maXair: When you see this thing, you think, "There's no way in hell that I'm going on that!" But, let me tell you, it's not nearly as sickening as you think. This thing is an 80-foot high pendulum (think boat swing) that has a rotating seating platform (think carousel). The effect, while looks absolutely sickening from the ground, is surprisingly more like a roller coaster in feel than you would ever imagine. At the top of the pendulum swing, you can be 140 feet off of the ground and inverted upside down! Because of that, the seating is a conforming shell with shoulder restraints. I had no trouble fitting the seat, but heavier guests will likely need to skip this ride (there is a chair at the ride entrance that you can test-fit yourself, if you're on the large size).

Raptor: I LOVE THIS RIDE! It's got to be just about the most thrilling inverted coaster ever. By inverted, I mean that the track is above the train, and you sit on a seat so that your feet dangle, like a ski-lift. The ride does all kinds of wicked loops and twists, so the seat is again conforming with shoulder restraints. Larger guests beware, and trial-fit at the entrance.

Friday, June 24, 2005

Sandboxing

What would be the ultimate sandbox environment to help protect you from the bad guys on the Internet?

Well, running in Virtual PC is one way. If something rogue takes over your system, it's really only taking over the Virtual PC. Of course, for the normal person, this means that you need to buy an OS license for the VPC's installed OS.

Wouldn't it be cool if your browser (or OS) would abstract out access to the hard drive, and make all writes occur to a virtual/differencing/undo drive?!!

Think of it like this: You run an ActiveX control in your browser, and it needs to write to disk. Maybe this writing to disk is just installing the control in the first place. Doesn't matter, because what we want to avoid is allowing something from the internet to persist to the live hard drive.

The OS intercepts the disk I/O, and instead of denying the request (which breaks the ActiveX control), it simply writes to a shadow drive. When the ActiveX reads from disk, the shadow information supercedes any real-disk information (i.e., if no shadow info exists for the requested I/O, then real-disk info is provided if allowed). So, the ActiveX control really isn't aware that it's not looking at the real drive. And, this shadow information can be thrown away after the session ends.

Surely, this needs to be thought out some more. I just wanted to record the thought while it was more or less fresh in my mind.

SQL Server 2005 Management Studio bug???

I was composing an update query by hand today in Management Studio. I thought it was a simple SQL statement that simply joined my Control table to a Query table using two fields to link the tables. My original SQL looked like this:

update control
set policyprocedure=q.policyprocedure
from control join query q
on control.activityfk=q.activityfk
and control.systemfk=q.systemfk


Management Studio changed the SQL to be this:

UPDATE  Control
SET PolicyProcedure = Control.PolicyProcedure
FROM Control INNER JOIN
Query AS q ON Control.ActivityFK = q.activityfk
AND Control.SystemFK = q.systemfk


Notice that the SET now pulls the PolicyProcedure field from Control instead of my aliased Query (Q). That's not what I ordered!

I finally got the desired results (sans any changing of aliases by Management Studio) using this SQL:

UPDATE  Control
SET PolicyProcedure = x.policyprocedure
FROM (SELECT c.ControlID, q.policyprocedure
FROM Control AS c INNER JOIN
Query AS q ON c.SystemFK = q.systemfk
AND c.ActivityFK = q.activityfk) AS x
INNER JOIN
Control ON x.ControlID = Control.ControlID


Is this a bug, or am I a moron who needs to study up on SQL? Maybe I should have used a CROSS JOIN and WHERE clause in my original update query instead of the INNER JOIN?

Comments anyone?

SnVzdC Bmb3IgZn VuLi4u

TWFkZSB5b3UgbG9vay4gIFRhZywgeW91XCdyZ
SBpdC4gIE5vdyBibG9nIHlvdXIgb3duIEJhc2
UtNjQgZW5jb2RlZCBtZXNzYWdlLg==

Wednesday, June 22, 2005

Overuse of the XPath "//" Shortcut?

I see a lot of people using XPaths with the "//" shortcut (lazy paths). But, consider what the processor must do when evaluating this. For example:

[test]
[a]
[b]
[c]
[d /]
[/c]
[/b]
[e]
[b]
[f /]
[/b]
[/e]
[/a]
[/test]



Using the XPath /test/a/b will return one node.
I'm in total control over which node(s) are returned,
so long as they follow my path exactly:

[b]
[c]
[d /]
[/c]
[/b]



However, using the XPath //b will return two nodes:

[b]
[c]
[d /]
[/c]
[/b]



and

[b]
[f /]
[/b]


This is okay if it's what I expected. However, I would guess that in most cases, having the second [b] node returned would not be expected, and could break an application's code.

Also, with the "//" shortcut, the processor must crawl every node of your tree in order to look for matches. By specifying an XPath that is rooted at the document element, you eliminate the need for the processor to perform this branch crawling, which greatly increases the query performance.

Oh, and as a side note, I'm starting to get irritated with Blogger trying to be smarter than me in handling my code snippets. I'm the human, dammit! You don't always have to change my formatting.

Monday, June 20, 2005

Dot Net Rocks! The Movie

Just finished watching the Dot Net Rocks! 2004 DVD ($15 shipped from Franklins.NET). As a newly established regular listener of the show, I found it absolutely worth the small price.

Think of the DVD as a way of introducing you, the DNR listener, to the DNR hosts and guests using Video (in order to put a face with the name). The DVD switches between the triple view of the taping of show #69 (interviewing Richard Campbell) alternating between Rory, Carl, and Richard (in his pre-host days). In addition, there are scenes inserted from Tech*Ed 2004 and some gathering (Devteach?) that Carl went to in Montreal, Quebec, Canada.

In a funny, but related story, we were watching TV this past Saturday, and my wife does her normal channel surfing during the commercials of whatever regular channel she was watching. All of a sudden, I catch a glimpse of Rory Blyth on my TV. I order her to stop ("please, can we watch this, sweety? Pretty please....") and watch that channel for a little bit. Come to find out, the DNR staff (Carl and Rory, with Nick Landry and maybe someone else that I didn't recognize yet) was at Ceasar's hotel in Las Vegas, I'm assuming for some conference event. The reality show on A&E called Ceasars 24/7 was filming, and did a segment of the bunch of nerds!

I had heard a brief mention about an A&E special on DNR, but I haven't listened to all past episodes yet, so I didn't know any details. It was really cool that I stumbled upon it randomly thanks to the impatience of my wife and her channel speed-surfing abilities.

UPDATE: After reviewing my blog stats today, I notice that a link to this post is being passed around in an email.... hmmm. I welcome my new readers, and hope that you take the time to check out the rest of the blog.

Cedar Point

We went out to Cedar Point again over the weekend. Fathers Day turned out to be a pretty good day to go, and there was great weather this year (temp in 70's, sunny). The parking lot was only half full (up to row 33), and we managed to find a prime spot in row 21, which is just beyond the handicap row nearest the gates.

It must have been Gay Pride day, though, for we noticed an unusually high number of same-sex couples, some sporting pretty funny slogans on T-Shirts, and some dressed in stereotypic "flaming" attire.

The usual eye candy was out and about, but there's a disturbing trend starting where young teenagers are dressing like the older eye candiers. Also, I think braless-ness is a growing trend this year for some reason. Should make walking around the back part of Frontier Trail a little interesting (that's where the water rides are).

And now for my review of the coasters that I got to ride (only a few so far this year):

Blue Streak
This oldie is still pretty good. A wooden coaster built in the mid-1960's. I took my 7 year-old on it for the first time, and she found it pretty frightening. The seats are a lot narrower than I remember (or my waistline is a lot larger than I remember), and it doesn't seem to have as much negative G's as before.

Iron Dragon
My daughter loves this ride, maybe because the train is more enclosed than other rides, so she doesn't feel like she's going to fall out. It's a slower inverted coaster (one of the first of its kind, but later trumped by the Raptor), but still has some thrilling moments.

Gemini
A great wooden racing coaster with hardly any wait at all. In the end, my daughter said that this is a fun ride, but she didn't like the lift hill (that seems to be a recurring theme, and will probably persist until she gets used to the clack-clack-clack noise). The best parts of this coaster is when the track goes through the framing--you think you're going to hit the frame, but dip just in time. There's also a thrilling loop towards the end that provides for some increased G's.

Disaster Transport
This used to be the Avalanch Run, a bobsled coaster, when I was a kid. They later enclosed the whole thing in a big building and added special effects and blacklights to the waiting area to create an experience where you have to evacuate from some catastrophe. Much of the ride itself is in blackout conditions, which is absolutely a thrilling experience. My daughter could ride this over and over again! The building is air conditioned, which helps escape the heat on hot days.

Thursday, June 16, 2005

Z-Machine

I don't know for sure, but I would guess that not many people know what a Z-Machine is.

It's the name given to the virtual (imaginary) computer that ran the old Infocom text adventure games. Even today, decades after the fact, I'm amazed at the foresight that Joel Berez and Marc Blank had in architecting this system.

Very much like .NET (and even more like Java), the Z-Machine provides for a compile-once, run anywhere architecture. Story files were compiled for this imaginary computer, and then all that Infocom had to do was write an "emulator" or virtual machine for each platform that ran the Z-machine's byte code. Very cool!

I found the extremely well written The Z-Machine Standards Document by Graham Nelson on Peer Schaefer's if-resources site. It's 182 pages, but anyone interested in Emulation, Virtualization, Infocom games, Assembly Language, Embedded Architecture, etc, MUST CHECK THIS OUT!

Given that this virtual system was first designed on a coffee table in Pittsburg in 1979 with the intention of porting it to multiple 8-bit platforms that existed at that time, it will certainly give you an appreciation for how easy we have it today.

Also, I remember using disk editors and memory editors to try to find text used by the story files (in order to try to snoop around the various games), but could never find anything more than garbage. I always thought that Infocom either encrypted their text or used an alternate character set.

Well, it's actually a form of compression that they use by stuffing three characters into two bytes. The ZSCII character set was roughly based on ASCII, but used only 5-bits per character. 3 * 5 bits = 15 bits, with the high bit of each word serving as the string termination marker. That explains why I didn't see any plain text!

Oh, and the "Z" in Z-Machine stands for Zork.

Ongoing Quest for Ways to Integrate Reporting Services with Portals

I played around some more with the HTML renderer in reporting services, and found a combination of parameters that would be most useful for portal integration:


http://server/ReportServer?%2fsamples%2fsample
&rs:Command=Render&rs:Format=HTML3.2&rc:HTMLFragment=true
This causes HTML 3.2 output to be generated, and only a fragment (not complete HTML).

The result is that you'll get a [table] with your report in it. Use whatever method you can to place this in your portlet.

An interesting side effect for multiple-page reports: You'll get a continuously rendered report with [hr /] between each page unless you include a "rc:Section=1" parameter (which will then only show the first page).

SQL Server Templates

Who knew.... For years, I've used Query Analyzer to created stored procedures, etc. At times, I've even used the Templates feature to give me a starting point, and found myself using find-and-replace to change the parametersplaceholders.

For example:

IF EXISTS (SELECT *
FROM sysobjects
WHERE name = N'[scalar_function_name,]')
DROP FUNCTION [scalar_function_name,]
GO

CREATE FUNCTION [scalar_function_name,]
([@param1, sysname, @p1] [data_type_for_param1,],
[@param2, sysname, @p2] [data_type_for_param2,])
RETURNS
...
I installed the Yukon (SQL Server 2005) CTP bits last night because I need to get caught up on that technology. I used the Management Studio today to perform some work on my current project (against a SQL 2000 database), and created a new stored procedure.

Management Studio displayed the same type of familiar template, but in the comments, it displayed "Use the Specify Values for Template Parameters command (Ctrl-Shift-M) to fill in the parameter values below".

What's this "Specify Values for Template Parameters" command? Must be something new, I thought. I hit Ctrl-Shift-M, and up pops this window with each parameter, allowing me to specify my own values. It's an automatic multi-value find-and-replace mechanism that's built in!

I opened up the old Query Analyzer, and lo-and-behold, that feature's always been there! It even has a command in the Edit menu. I'm pretty traditional, so I don't think that I'll ever use it, but it's good to know that it's available if I need it.

Monday, June 13, 2005

Grok Talks

Yay! The first of the GrokTalks from Tech Ed have been posted!

http://mediaserver.aspsoft.com/blog/FirstBatchOf6VideosReady.aspx

(GrokTalks are quick 10-minute no-bullshit technology briefings)

Season Tickets

For the first time in my life, I finally broke down and bought season tickets to this place with the intention of forcing myself (and the family) to go more than once per year. Now we won't really have an excuse to head out some evening on a whim to the greatest amusement park in America (and arguably, the entire planet).

Sunday, June 12, 2005

Client-side Business Objects?

There's a lot of buzz around AJAX these days, and I started thinking about how this type of client-side code could be put to alternative use.

I was recently asked about how to interface a web page with code that reads from the PC's serial port. For example, if the PC is connected to a scale or other sensor via the serial port, and this data should automatically be available to a form on the web page.

Of course, the traditional "Use an ActiveX Control" solution came to mind, especially since I've created a control for this exact purpose in the past. Similarly, a UserControl written in .NET can be hosted by IE (after playing with CAS policies). But, then AJAX came to mind, and I thought of this solution:

  1. A native application runs on the client (perhaps as a service, or a console app, windows app, etc). Can be VB6, C/C++, .NET, Java, or whatever, so long as it can perform the tasks that follow.
  2. The native app is able to read and/or write to the serial port as required. Much of this code probably already exists if the developer was prototyping the communications code.
  3. The native app includes a HTTP listener. (I would lean towards .NET, since it's so easy to create and use HTTP listeners).
  4. The web page includes javascript code that does AJAX-like communications between the local "webserver" and the browser.
  5. Upon receiving a request via the HTTP listener, the native app does the serial port comminications necessary to retrieve the results, and then packages it up and sends it to the browser via the response object.

The beauty of this approach is that so much of the "Business Logic" can be written in the native/compiled code, which lets you do far more than what you can do with Javascript alone (image generation/processing anyone?). Also, the AJAX-like code doesn't have to be very long or very complex to interact with the native code, the browser is not limited to Internet Explorer, and the "server" is local, so network communications are reduced.

This was a simplified example of what I feel could become a cool architecture. If security issues could be overcome (nothing that ActiveX and Java Applets haven't struggled with, such as controlling permissions to filesystem and peripherals, etc), then custom business logic could be packaged as simple modules that plug into a master "listener".

This might actually fit well into my Personal Portal Server concept.

Friday, June 10, 2005

Why Not Base 11?

We all know how to count, right? 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. That covers the sum of most people's fingers. But, 10 usually indicates an overflow, or carry, in whatever base you're dealing with. It's the effect of maxing out the digits in the base set.

For instance, in binary, you count 0, 1, 10.

In hexadecimal, you count 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10.

When you count on your fingers, your 10th finger is not the carry--it's the last element in the set. So, counting on our fingers is actually using base 11, not base 10, since you don't carry the digit until you run out of fingers.

So, counting on your fingers should go like this: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, 10 (and 10 in this case is one more than when you run out of fingers).

This doesn't mean that I have 11 fingers, it means that when I hit 10 it shouldn't actually be called 10 because the carry/overflow hasn't occurred yet.

QmxvZyduIG15IHdheS B0byB0aGUgUERDIDA1

SSBhbSBhIGR5aW5nIGJyZWVkIHdpdGhpbiBteSBj
b21wYW55LCB0aGUgbGFzdCBvZiBhIGxvbmcKbGlu
ZSBvZiBjb2RlcnMgd2hvIGJlbGlldmUgaW4gc2lt
cGxpY2l0eS4gIFdoaWxlIGV2ZXJ5b25lIAplbHNl
IHNpbmdzIHRoZSBwcmFpc2VzIG9mIEoyRUUsIEkg
a2VlcCBteSBkaXN0YW5jZSBrbm93aW5nIAp0aGF0
IG15IHNvbHV0aW9ucyB3aWxsIGdldCBkZWxpdmVy
ZWQgZmFzdGVyIGFuZCBjaGVhcGVyIAp0aGFuIG15
IHBlZXJzLiAgSSBhbSBhIFByb2Zlc3Npb25hbCBN
aWNyb3NvZnQgRGV2ZWxvcGVyLgoKQW5kLCBzcGVh
a2luZyBvZiB0aGF0LCBJIG5lZWQgdG8ga25vdyBo
b3cgdG8gdXNlIG15IHRvb2xzIAptb3JlIGVmZmVj
dGl2ZWx5LCB3aGF0IHRvIGV4cGVjdCBmcm9tIHRo
ZSB1cGNvbWluZyBwcm9kdWN0IApyZWxlYXNlcywg
YW5kIG1vc3Qgb2YgYWxsLCBJIG5lZWQgdG8gY29s
bGVjdCBjb29sIHN3YWcgdGhhdCAKd2lsbCBtYWtl
IG15IEphdmEtYmFzZWQgcGVlcnMgamVhbG91cyEK
ClRoZSAyMDA1IFByb2Zlc3Npb25hbCBEZXZlbG9w
ZXJzIENvbmZlcmVuY2Ugd2lsbCBiZSBoZWxkCmZy
b20gU2VwdGVtYmVyIDEzLTE2IGF0IHRoZSBMQSBD
b252ZW50aW9uIENlbnRlci4gIERldGFpbHMKY2Fu
IGJlIGZvdW5kIGF0OiBodHRwOi8vbXNkbi5taWNy
b3NvZnQuY29tL2V2ZW50cy9wZGMvCgpTaG91bGQg
SSBhdHRlbmQsIHlvdSBjYW4gYmV0IHRoYXQgeW91
J2xsIGZpbmQgd3JpdGUtdXAncyAKYW5kIGhvdy10
bydzIHBvc3RlZCBoZXJlISAgU2hvdWxkIEkgbm90
IGF0dGVuZCwgdGhlbiB5b3UnbGwgCnByb2JhYmx5
IHN0aWxsIGZpbmQgd3JpdGUtdXAncyBhbmQgaG93
LXRvJ3MgcG9zdGVkIGhlcmUuCgpPaCwgYW5kIGJ5
IHRoZSB3YXksIHRoYW5rcyBmb3IgdGFraW5nIHRo
ZSB0aW1lIHRvIGRlY29kZSAKbXkgQmFzZTY0IGJs
b2cgbWVzc2FnZS4gIEhvcGVmdWxseSB5b3UgdXNl
ZCB0aGUgc2FtcGxlIGNvZGUgCnRoYXQgSSBwcm92
aWRlZCBpbiBteSBibG9nIGFuZCBjb3VsZCBzZWUg
anVzdCBob3cgZWFzeSB0aGUKLk5FVCBmcmFtZXdv
cmsgbWFrZXMgaXQgdG8gcGVyZm9ybSB0YXNrcyB0
aGF0IG9uY2UgcmVxdWlyZWQKYmxvY2tzIG9mIGNv
ZGUuCgo=


blogging my way to pdc


Note: Base64 Encoded ASCII string. Read the previous entry in my blog if you have no idea what this is.

Base 64 Encoding/Decoding using .NET

Sometimes binary data needs to be represented in a text-friendly format. For instance, maybe you need to include the bits of an image file within an XML document. To do this, we typically use Base64 Encoding.

Back in the VB6 days, I had a couple of subroutines that did my encoding and decoding for me. Now, with the .NET Framework, it's extremely easy to do.

For instance, to encode a string into Base64, you simply do the following:

string b64=Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(s));

But wait! Didn't I say that Base64 was used to encode binary data? Well, yes, but a string can be transformed into binary data (a.k.a., a byte[] array), and that binary data is what is transformed.

There are different ways to represent a string as bytes of data (remember that not everyone uses the same Character Set as us-english, so some languages must use Unicode). In this example, I use the ASCII encoding class's GetBytes() method to generate the byte array for me from my string variable named "s". Each character in "s" will be represented by a single byte in my array.

Decoding a Base64 string is similarly easy:

string s=System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(b64));

A little warning here: I had to guess that my Base64 data was ASCII encoded, so I used the GetString() method of the ASCII class to decode the byte array into a string. If you use the wrong text encoding class to decode the byte array, then you could get garbage data. If you control both ends of the conversion process, then this shouldn't be a problem, but you do need to be aware of what different encoding schemes are out there.

Here is the code for a console app that will decode Base64 strings for you. The assumption is that the byte array was ASCII encoded, as above. Run the application and type or paste your Base64 data into the console. Enter two blank lines at the end, and it will then display the decoded ASCII text.

Notice that if you want to use this as an encoder, then simply uncomment the encoding line and comment out the decoding line.


using System;

namespace scratch
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
string s="";

string y = Console.ReadLine();
while (y != "")
{
s += y + "\n";
y=Console.ReadLine();
if (y=="")
{
s+="\n";
y=Console.ReadLine();
}
}
// Convert collected string to Base64
// Console.WriteLine(
// Convert.ToBase64String(
// System.Text.Encoding.ASCII.GetBytes(s)));


// Convert collected Base64 string to ASCII
Console.WriteLine(
System.Text.Encoding.ASCII.GetString(
Convert.FromBase64String(s)));

Console.ReadLine();
}
}
}

Thursday, June 09, 2005

My Thoughts on Portals

I work for a company that makes its fortune off of building portals for companies using IBM Websphere Portal Server. Personally, I've only been involved with one portal project (thankfully), but it gave me some real insight into why portals kind of suck.

First of all, I cannot believe how much money companies are willing to pay for what little they receive. I mean, just the price of the software alone is outrageous, and that only gives you a basic framework and a sample portal. I hope you didn't want anything relevant to your company for that $50-100k, because that will cost you extra! But, hey, it's IBM software written completely in Java (meaning that it's not Microsoft, so it's worth the price, right?)

So, let's say that a company just dropped $50K (or whatever the going price is) to buy Websphere Portal Server Enabled. Who's going to install and configure it? The local IT department???! Really smart people from my company who have been working with Websphere for years still have trouble getting all parts of the thing up and running, and keeping it running smoothly. And each new version of the product introduces new “bugs” that make it impossible to guarantee a perfect installation by a knowledgeable person.

Oh, and I hope you have a lot of new/powerful hardware with LOADS of memory and disk space (because remember, IBM is a hardware company first!), because it ain't gonna run for you unless you do. Our development environments require 1GB minimum RAM just to be usable. Plus, you'll want to cluster your production environment across multiple servers to improve overall performance, which introduces a whole heap-load of complexity to the configuration.

I'll have to say, though, that once a WPS portal is completed, that the whole thing is quite impressive. Perhaps in the same way that it is an awe-inspiring feat of engineering that we can send three people to the Moon and back, but in the end, you think about just how much money it took and wonder if the ROI was ever really there.

I'm not going to give a free pass to Microsoft SharePoint, though. While I'm happier with what they're calling a Portal with version 2 (versus the first version, where they slapped the Digital Dashboard onto the document management system and called it a portal), overall, it falls short of where it needs to be in order to draw companies away from WPS. I'll probably detail those shortcomings some other time when I have a comprehensive list, but my point is that SPS does not yet directly compete in the same space as WPS. And that gives my company a huge reason to continue pushing J2EE over .NET.

In my naive opinion, portal platforms are missing a key opportunity by making the technology server-centric. I mean, sure, being server-centric allows anyone from anywhere to connect to the portal with whatever browser is available on the machine that they happen to have access to. But, it also sends us back to the mentality of the mainframe and hub-spoke infrastructure model where you have an all-powerful machine in the center doing all of the work while dumb terminals exist only to provide the user an interface to the brains of the system.

My vision of portal technology places the aggregator at the client instead of the server. Or at least the concept of a “portal server” would be closely tied to one user instead of all of the users of a system. Let this “Personal Portal Server” be responsible for aggregating content and generating/caching the presentation. Then let the user decide what information needs to be displayed, even if that means combining Portlet/WebPart information from multiple providers onto one page.

If Google Maps and GMail has taught us anything, it's that the client (even a web browser) can offload a lot of processing from the server, and this is not much different than what I'm suggesting here. Centralized servers do not completely go away, but become specialized for the task at hand—providing specific content to a whole host of remote aggregators.

This concept really needs some refinement to become practical, but this is just a View Inside My Head at this moment.

Tuesday, June 07, 2005

Extracting Air From Water

Slashdot had an article the other day about an aparatus that would extract breathable air from water. The way that it works is that a battery powers a centrifuge, which lowers the pressure, allowing the trapped gasses to escape (due to Henry's Law). This is how fish breathe, in stark contrast to using electrolysis to separate hydrogen and oxygen.

I wanted to test this myself to see how it works. Instead of a centrifuge, I used a syringe (when my babies take antibiotics, the pharmacy always gives us a new syringe to use for dosing, so I have lots of them laying around).

I filled the syringe with a couple mL of tap water, got rid of extra air, and then put my thumb tightly over the opening. I then pulled back the plunger, thus lowering the pressure inside the syringe. Immediately, air bubbles began to form on the walls of the syringe (or at least it looked like air, but for all I know, it could be vacuum space). So, it works!

But, as soon as I released the plunger, the air bubbles dissolved back into the water. I wonder how the breathing aparatus inventor solved that issue???

PC's I've Used Over Time

I'll play along with John Koziol's post about odd computers that he's owned over time. I'll just list my history instead of claiming anything odd....

TRS-80 Model I/Level II: My first memories of any computer was that of my Dad sitting in the attic of our home with his Level II in the late 70's. Later, I remember him setting it up on our kitchen table so my brother and I could play with it. That was the same computer that I learned BASIC on (in way of typing in programs from various manuals).

What I remember most about it was that programs were loaded off of cassette tapes, with the computer being plugged into a headphone jack (or something similar) on the cassette recorder. Dad had tons of tapes around, with a large portion of them from "80 Micro" magazine, if I recall. Those cassettes came in handy years down the road when I routinely recorded songs off of the radio (and/or needed a tape for one of the Commodores). ;-)

TRS-80 Model III: My Dad's next computer was the Model III. I believe, if I reach back into the part of my memory that I've long since blocked out, that I was responsible for the death of the Level II. The Model III had dual floppy disk drives, and could play Zaxxon and Zork!

TRS-80 Model 100: Can you tell that my Dad was a frequent visitor to Radio Shack??? The Model 100 was a portable that used AA batteries. It had a small LCD display built into the same plane as the keyboard (not a clamshell like today's laptops), and sported a 300 baud modem built in! I remember sneaking this to school in the 6th grade and used it during an oral presentation instead of notebook paper.

Commodore VIC-20: This was my own computer, and I believe that I got it for my 7th or 8th birthday. Maybe it was Christmas... Can't remember, but at first, I only had the computer, and spent many hours typing in programs from COMPUTE! Gazette. I couldn't save the programs, though, so they were lost as soon as power was lost (or the computer locked up).

Then, I think for Christmas (or birthday, whichever was next), I got the Dataset, which was a silent cassette recorder (no speakers) that plugged into a data port. Finally, I could save programs!

TI-99/4A: I didn't actually own this computer, but my neighbor Mike Trumbauer did. He was a great programmer as a 4th/5th grader, and I'm sure he's gone on to become an impressive technologist (he moved away when I was young, and I heard that he went to Purdue). This guy could create from scratch a version of just about any video game, and they were actually fun to play! I remember versions of Missile Command and Donkey Kong for sure, but there were so many more.

Commodore 64: The defining moments of my childhood (and early teenage years) were spent programming this beast. I had the floppy drive, and 1200 baud modem, though that modem got me into a lot of trouble when a $300 phone bill came through. A Seikosha printer rounded the system out.

Three of us at school (Tim, Jon, and myself) shared warez (there, I said it), with some of the best things included were known as "Demos" (kind of a packaged marquee program that the pirate groups would include with the warez to play music and show text). We were also fans of the Infocom adventure games (Zork, Planetfall, Hitchikers Guide to the Galaxy, etc). But, this all leads to a little story that I think is humorous:

We had heard of these computer viruses that were infecting, well, probably IBM's. So, I told Tim that I had the latest copy of Double Dragon, or something cool like that. I give him the disk, he goes home and then LOAD "*", 8, 1 (something like that), and WHAM! There's a sprite of an evil looking PacMan floating around his screen with words that says "YOU ARE INFECTED WITH A VIRUS".... He promptly calls me sounding freaked out, and I let him in on the fact that I wrote the program the previous afternoon.

IBM Portable: Don't know the model number, but during my first two years of Yearbook Staff, I used this old 45-lb beast of a computer that had floppy drives and a small amber monitor built in.

IBM PS/2: I convinced my teacher that we needed this for Yearbook because it allowed us to run the newer yearbook publisher's software. It was better than the old portable.

386-DX: Just some clone that I picked up in college. I think it had 4MB RAM, a 40MB hard drive, and I put in the 3.5" floppy drive myself. It ran Geoworks just fine (even better than Windows 3.1!).

And then we come to the "modern" platforms with various versions of the Pentium architecture that I won't get into.

Removing Special Characters from .NET Strings

I came across a need today where I couldn't find an easy method on the internet. I had strings that I wanted to turn into simple filenames by removing a list of bad characters. I would have loved to have been able to use Trim(char[]) to do this, but that only works at the beginning and ending of strings.

I'm not sure how elegant and/or efficient my solution turns out to be, but here it is for anyone googling years down the road:



public override string ToString()
{
string junk = "~!@#$%^&*<()+=`',.?>/\\\"";
string[] ret = _displayText.Split(junk.ToCharArray());

return string.Concat(ret);
}



The Split(char[]) method creates an array using the provided characters as deliminators. This effectively strips out the "junk" characters, leaving you with broken bits of your original string. The Concat on the return line brings together the broken bits into one string.

Friday, June 03, 2005

Improve Browser History, Please!

The browser session history is linear, and works fairly well, but it really doesn't take advantage of how people surf the web. The way that it works today is that while you're surfing, you can hit the back button go return to a previous page, and once you use the back button, you have the option to use the forward button.

But, if you go back a couple of clicks in history, and then navigate to a new link, then you lose everything that was in your "forward history".

How do you improve this behavior? Instead of having the history be stack based (or whatever linear data structure is actually used), make it tree based. In this way, if you go back a couple of clicks and then follow a different hyperlink, a new branch is started in the session history. When you click the forward button from a page with multiple branches, you're prompted as to which branch to forward into.

Thursday, June 02, 2005

My Stats

It's interesting to see where my readers come from. Especially those arriving here from search engines. Just for fun, here's a summary of keyword themes that have brought readers to my blog:

30% Dog Crap in Lawn
25% GBPVR
10% Arcade monitors
10% Rejuvenator
8% 2004MN
6% ILWWCM
6% Other
5% Presidential Aircraft

Wednesday, June 01, 2005

Using VB Functions from C#

This seems like a no-brainer, but let's say that you're struggling trying to figure out how to do something in C# that you know how to do in VB. Like, maybe taking the right 5 characters of a string.

It's not that you can't do this in C#, because you surely can (it's trivial after working with C# strings for a while), but in a RAD or prototyping environment, you may find yourself wishing that the Right() function existed in C#, and may even be tempted to write one. [Some people would be wondering why you're not just using VB.NET in the first place, but that'$ a different argument].

The point here is that you can access all of the VB.NET functions that you're used to from C# by simply adding a reference to the Microsoft Visual Basic .NET Runtime assembly.

Consider the following code, which at least demonstrates how to get to the Mid and Format functions:



using vb=Microsoft.VisualBasic.Strings;

namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Console.WriteLine(vb.Mid("FOOSBALL",3,2));
Console.WriteLine(vb.Format(12345, "00000000.00"));
Console.ReadLine();
}
}
}



I highly recommend that you explore to see what other familiar functions are available in the Microsoft.VisualBasic namespace (for example, the Microsoft.VisualBasic.FileSystem class could be real helpful!)

Tuesday, May 31, 2005

No TechEd for Jason

:-(

I totally missed the opportunity earlier this year to enroll in TechEd, which kicks off this week. I'll catch the webcasts when they're made available, but it sucks that once again, I'm stuck working instead of seeing the cool new stuff.

Disclaimer: It would have been really tough for me to attend anyways, which could not have been predicted earlier this year--my current project is readying for "go live" this week, which would have been hard to do while in Orlando.

RSS and SharpReader

Ok, I've been using SharpReader to subscribe to multiple RSS feeds for more than a week now.

I was first really apprehensive--I mean, this is essentially web browsing for me using an email reader instead of IE. But, the more I used it, the more I finally "got" why it's such a powerful tool.

Once you learn of an RSS feed that you're interested in, you simply instruct SharpReader to open that feed and subscribe to it. SharpReader will then periodically download the XML and notify you when there's new content, much like an email reader would. It definitely saves on the time spent browsing the same sites looking for changes, that's for sure!

I still think that there's a niche for my personal portal concept. The power of RSS is that the content is easily extracted and transformed, so it fits perfectly into this idea.

Saturday, May 28, 2005

Movie: Primer

I was turned onto the movie Primer by my friend Jim. They claim that this movie was produced for a total of $7,000, and it has been nominated for and won some indie film awards.

The main characters, who appear to be in their twenties or early thirties, wear shirts and ties throughout the movie, so I thought that was a little unrealistic. ;-) Another thing that bothered me was seeing a flyback transformer hanging off of their "time machine" with the anode disconnected and hanging freely. I mean, what's up with that?

The actors are not polished actors, and the sets are nothing fancy. These flaws only add to the possibility that maybe we're watching something that could actually happen. I'm even in the process of watching the DVD a second time, just because it's one of those out-of-sequence time-shifting story lines that make more sense when you see it again.

If you see it on the shelf at your neighborhood rental shop, or use Netflix, then check it out! I've seen movies with millions of dollars in them that sucked, and this, for the sum of its production costs, is actually a cool story (read: it doesn't suck at all).

Couple More Puzzle Solutions

Not much work got done yesterday....

You are an employer of a company and you are in the process of hiring a new employee. You must pay this employee in gold at a rate of 1 oz. per day. This employee will work for you for 7 days and must be paid every day, no more and no less then 1 oz. per day. You happen to have one 7 oz. bar of gold and may make two cuts on this piece of gold. What cuts would you make in order to successfully complete the task?

I had to think about this one for a while. I kept thinking "two cuts....I wonder if you need to make one cut, and then stack the pieces and make another cut somehow". Then it dawned on me that the only way this would work is if the employee gave back some of his earnings in exchange for the total sum that he was due up to that point in the week. This breaks down to be a binary number problem. The two cuts leave you with 1 oz, 2 oz, and 4 oz chunks (powers of two).

Day 1: Give employee 1 oz
Day 2: Employee gives you 1 oz, you give employee 2 oz
Day 3: Give employee 1 oz
Day 4: Employee gives you 1 oz and 2 oz, you give employee 4 oz
Day 5: Give employee 1 oz
Day 6: Employee gives you 1 oz, you give employee 2 oz
Day 7: Give employee 1 oz.

Please write a function that will determine if a number passed into it is a perfect number. How would you test this?

I'll admit, I had to look up what a perfect number was. I knew that it was related to Mersenne primes, but I did not remember all of the details. (Simple definition: A number whose factors sum up to the number itself. Example: 6 has factors of 1, 2, and 3 [don't use 6 as a factor for this purpose]. 1+2+3 = 6).

A theorem states: If 2k-1 is prime, then 2k-1(2k-1) is perfect and every even perfect number has this form.

Nobody has found an odd perfect number thusfar, so chances are that they do not exist. So, I'll take advantage of this theorem while writing my code. Having a knowlege of binary arithmetic is extremely helpful here.

2k-1 will be a string of 1's when represented in binary. For example, 23-1 = 7, which is 111 in binary.

2k-1 is simply a power of two, and when you multiply a binary number by a power of two, you're simply doing a bit shift (i.e., adding zeros to the right side of the number). For example, 23-1 = 22 = 4, which is 100 in binary. 111 * 100 = 11100, or 111 shifted two bits to the left.

So, the function to check if a given number is a perfect number would be as follows:



static bool IsPerfect(long number)
{
string x=Convert.ToString(number, 2);

// Check for form: 111110000

int lastOne = x.LastIndexOf("1"); // 4 = k - 1
int firstZero = x.IndexOf("0"); // 5 = k

if (firstZero < lastOne)
return false; // There's a 1 after a 0

if (lastOne + firstZero != x.Length)
return false; // Improper bit length

// The number is now in the form of a perfect number, but that
// is not sufficient. We need to prove that 2^k - 1 is prime before this
// can be a perfect number. Luckily, there's a very small list of
// mersenne primes that fit our number's 64-bit length, so let's just
// see if k is one of these.

int[] mersenneExponents = new int[] {2,3,5,7,13,17,19,31,61};

for (int i=0; i < mersenneExponents.Length; i++)
{
if (mersenneExponents[i] == firstZero)
return true;
}

return false;
}



To test as I was building it, I came up with a list of known perfect numbers and known numbers that were in the form of perfect numbers but were not perfect numbers, and I ran them through the function to verify the appropriate results.

Probably took me 45 minutes to an hour to write the function and blog it here... That's probably way too long for an actual interview environment, which is why I live in Ohio and not Washington. :P

Also, it might have been easier since we have a finite list of possibilities to just calculate the known perfect number, and then check against the given candidate. Wouldn't have to dork around with strings that way....

Friday, May 27, 2005

String Puzzle

I found mention of this on Eric Maino's old blog (link):

You are given lengths of string that will always burn in 60 minutes from one end to the other. You have been tasked with measuring 45 minutes using these string how would you do it? Now imagine that the strings will burn from one end to the other in 60 minutes but they will not always burn at the same rate. Sometimes the strings will burn faster or slower at parts. How would you measure the time now?

I had not seen this puzzle before today, and since it's the day before a holiday weekend, and I'm working instead of taking my assigned company holiday, I thought that I'd give myself a break, eat some peanut M&M's, and think up a solution (pretending all-the-while that I'm at the mothership in Redmond with some uber-cool geek [oxymoron] interviewer waiting for my answer).

My solution to the first scenario is to simply cut 1/4 of the length off, and start burning from one end. The assumption here is that the string burns at a constant rate. To find the 1/4 length, fold the string in 1/2, and then in 1/2 again. If you can't cut, then just start the burn at the 1/4 mark, and the flame should go in two directions (towards each end). When the longer segment finishes burning, that should be 45 minutes.

For the second scenario, a constant burn rate cannot be assumed. This means that if you start burning a string from one end, it will reach the middle point at a different time than if you started from the other end. But, if you burn both ends at the same time, then when the flames meet and burn out, you should be at 30 minutes (regardless at what point in the string that event takes place).

If you started burning a second string from only one end when you lit the first string, then you know that regardless of how much of the second string is burned up at the end of 30 minutes, that you'll have 30 minutes left to go. Using the same principle as the first string, light the other end of the second string at the 30-minute mark, and when the flames meet and extinguish, then you should be at the 45-minute mark.

Thursday, May 26, 2005

Motorcycle Ride through Chernobyl

This is kind of an older site, but fascinating whenever I see it. A motorcycle-riding hottie named Elena tours the ghost town near the Chernobyl reactor, and posts her photos. A Must See Site!

L O S T

I love LOST (on ABC). I'm so sad that I have to wait the entire summer to get my weekly fix of new episodes. Luckily, there's little things planted around the Internet related to the show.

Like this website, for instance.

Code: The Hidden Language of Computer Hardware and Software

I first heard of Charles Petzold's Code: The Hidden Language of Computer Hardware and Software [amazon link] from DNR.

My copy arrived in the mail yesterday, and I've had a chance to read a few different sections. So far, I'm impressed by Charles' description of the logic hardware that is used to build a binary adder, as well as his description of ones-compliment and twos-compliment (a topic that is often hard to describe to someone). I can't wait to read more!

Monday, May 23, 2005

Voice Recognition: Cool Stuff, But Is It Practical?

Voice Recognition has come a long way, but it has a long way to go yet. My health insurance provider uses a voice recognition system to handle customer service phone calls, and the result is that it is nearly impossible to get to an actual human operator.

As I sat working today, I listened as my wife called the insurance company to verify something. The first phone call was a bunch of her saying single words: "Yes" "Coverage" "Pharmacy".... Stuff like that. Eventually, she somehow got a prompt that asked if she wanted to talk to someone, but that was maybe 2 minutes into the call.

Come to find out that she ended up at the wrong department or something, because that person could not answer her question, nor could they transfer her. She would have to call back and navigate the voice system again.

This time, her "Yes" "Coverage" "blah blah" responses were much more irritating. Eventually, she again was prompted to speak to an actual human. (BTW--she did try dialing Zero, etc, to see if it would circumvent the voice recognition system, but it wouldn't).

This person was useless as well, so she had to call back again! (They must outsource their call centers or something--not being able to transfer between departments seems like a rediculous incapacity).

The third time, the voice system wasn't recognizing her clearly irritated/almost outraged tone of voice, because she was starting to repeat each response. "YES' "YES" "I SAID YES!". At one point, I heard her say "GIVE ME SOMEONE REAL!".

Until we have actual Star Trek-level voice recognition, I don't see why companies are using them in customer service roles without providing up front a way to reach a real human.

MSPaint Masterpiece

Check out this guy's artwork, all created using MSPaint! (And Photoshop for some blurring effects):



(Hopefully they'll allow this link to the thumbnail, otherwise just click on the blank square above)

Saturday, May 21, 2005

RSS needs a Personal Portal Server

I'll admit, I'm really behind the scene on adopting RSS feeds as a primary source of information. Chiefly, I haven't found an aggregator that I particularly like. I gave it another try today using SharpReader, so we'll see how it goes.

My primary problem is that I don't want to think of news items (and blog entries, etc) as email, which is what aggregators seem to do. I want a portal-like interface, and do everything from my browser, but I don't want to run a dedicated portal server, and I don't want feeds to be collected at the time that I request them.

What I really want is a personal portal server to augment my browsing. I already have a pretty predictable list of sites that I visit multiple times a day, and most visits are only to see if anything new was added. What the personal portal server (running on my PC) would do is periodically crawl those sites or RSS feeds, get the new info, and compile into my portal page. When I get the urge to surf, my browser only needs to load the "compiled" portal page from the local hard drive, instead of going to some overpowered server chunking through code to assemble my page on-the-fly.

Shrinkster Helper

As I listened to the live Mondays show last night, I realized that there's something about trying to keep up with all of the Shrinkster URLs while listening to a live feed (i.e., you can't pause it) that was a little overwhelming. I mean, in reality, it's only a matter of remembering three characters, but I found myself typing in "h t t p : / / s h r i n k s t e r . c o m / " and then trying to remember the three letters for the URL.....

I made a recommendation this morning to Kyle, who took it as a valid suggestion, to offer a launching page from Shrinkster where you only need to type in the unique part and click a button. It wouldn't need a round-trip to the server, because the browser could spawn a new window. Something like the following:

[html]

[head]
[title]Shrinkster Launcher[/title]
[style type="text/css"]
.code {font-family:monospace;font-size:small;}
[/style]

[/head]

[body]

[span class="code"]http://shrinkster.com/[/span]

[input class="code" type="text" id="suffix" name="suffix" size="5"
maxlength="5" /]

[hr /]

[input type="submit" id="clicky"
onclick="window.open('http://shrinkster.com/' +
document.getElementById('suffix').value, 'ShrinksterURL')"
value="Launch" /]

[/body]
[/html]

Note: I had to translate the angle brackets into square brackets because I gave up trying to fool Blogger. If you want to use this code, just replace all "[" with "<" and replace all "]" with ">".

Friday, May 20, 2005

Carl Franklin's "Mondays"

I just finished listening to the live taping of Mondays. I actually was hoping to catch the live episode of DNR, but came in too late, I guess. It wasn't until they said the show's title that I realized what stream I was actually listening to.

Anyways, I have tried to listen to recordings of Mondays in the past, but didn't find them, well, all that captivating. The live show was much better, giving a peek behind the scenes of just how many times Carl and the gang mess up (which all get edited out) and swear during the 2 hours of taping that will be edited down to an hour. Plus, being an active participant in the chat only enhanced the entire experience (maybe this is what I was missing while listening to previous recordings).

If I'm not busy next Friday night, I'll probably be back! ;-)

A Reporting Services How-To

Here's my quick Reporting Services tip for the day:

Suppose that you have a chart (or full report) that you want to display on a web page as an image (i.e., within a portlet or web part). You can easily use URL Access to do that!

Consider the following IMG tag:

< img src="http://servername/ReportServer?
%2fMyReporting%2fChartExample&rs:Command=Render
&rs:Format=IMAGE&rc:OutputFormat=PNG" border="1"
>

Breaks down like:

http://servername/ReportServer?

The URLAccess URL.


%2fMyReporting%2fChartExample

This is the path and report name. Note that %2f is the URL escape character for a slash.


rs:Command=Render&rs:Format=IMAGE&rc:OutputFormat=PNG

Causes the report server to render the report as a PNG image.

Do I need to pick a specialty?

I've always been a jack-of-all-trades. I've been equally comfortable working on my own automobile, digging with a backhoe, rapelling down a cliff, repairing an arcade monitor, working on math problems, writing software, installing Windows, performing electrical work on my home, installing a satellite dish, etc.

But, my career field (computer technology) has just exploded over the last decade, and I'm finding it overwhelming if not impossible to keep up on everything.

I'm not about to stop learning, but at what point do I need to stop knowing something about everything and start specializing in one or two things? How do I personally decide which technologies to specialize in? How do I ensure that I maximize my income while maintaining a high level of personal satisfaction?

BTW, I've come to understand a long time ago that I derive great satisfaction from prototyping (R&D). My productivity level at the beginning of a project during the problem-solving stage is so much higher than at the end of a project (when there's nothing left but tying up loose strings). How do I get someone to pay me just for this type of engineering while letting someone else finish and refine a project?

Wednesday, May 18, 2005

Hantarex Polo Repair Log

Problem: Weird "wavy" horizontal linearity. Crosshatch pattern would gradually get narrower, and then wider, and then repeat. Vertical linearity was fine.


Simulation of H-Linearity problem of Polo

Solution: Discovered that D135 (BYV95C) was burnt and broken in half. Replaced with a BYV28-200, since that's all that I had and it is rated higher than the original part.

Tuesday, May 17, 2005

UFOs On Google Maps?

We'll probably hear a good explaination in days or weeks, but here's a phenomenon that people have found while Google Siteseeing: Difuse blobs on the satellite images that are not explained.

http://www.mikeslist.com/2005/05/ufos-spotted-on-google-maps.html

http://www.googlesightseeing.com/2005/05/12/ufo/

Now, let's just put on our Fox Mulder hats for a little bit. Suppose that we are under constant survelliance by aircraft, be that alien or perhaps [warning: conspiracy theory] experimental millitary. And suppose that there is a cloaking mechanism that would make these aircraft "transparent" when viewed from the ground against a cloudless blue sky. That same mechanism might not be as effective when viewed from above, and could explain what's in these photos.

Or, maybe it's a flaw in the stitching program that Google/Keyhole uses. Who knows.

From UPI: Major Geomagnetic Storm Heads Toward Earth

I have to chuckle whenever I see "science writers" for major media mix up facts in stories about auroras and space weather, a topic near and dear to me. It's not their fault--I mean, they probably got the short straw on that day, so they missed out on the sports reporting. Let me dissect the part of the story that I have the biggest problem with:

Statement: A major electromagnetic storm from a solar flare was headed toward Earth Monday, possibly causing power distribution, cell phone outages and other problems.

Fact: The Coronal Mass Ejection (CME) that occurred as the result of a major solar flare on Friday had impacted Earth early Sunday morning, USA time. The resulting Geomagnetic storm had all but subsided on Monday.

This would have been a good "heads up" story to run on Saturday, not on the Tuesday following. In my opinion, it seems that they want to put people into a panic over an event that is over (by making the uninformed believe that it is yet to occur).

Monday, May 16, 2005

Next Generation Microwave Oven Idea

Here's an idea: Why not slap a LCD display onto the door of a microwave oven, drop in an embedded OS, and suddenly, that huge block of space on your countertop can become a useful Internet Appliance that you can use to check your email while waiting for the popcorn to stop popping.

Some challenges to overcome: Keeping the LCD clean, considering what the door of my microwave looks like, and if it's wi-fi enabled, overcoming the RF conflict, since microwaves and 802.11b/g use the same frequency band,

Saturday, May 14, 2005

The Coderoom 2

Episode 2 of The Coderoom is now out. I watched it on TheServerSide.NET, who was the first to host it. In this episode, a group of developers must make a bluetooth-enabled application to more or less simulate interaction that a shopper might have in a shopping mall (i.e., be able to view specials going on in the stores via your phone).

The show gives face-time to Rory Blyth, who serves as the MSDN dude that accompanies each episode (or at least, that's been the trend so far). Rory was the co-host of .NET Rocks for 50 episodes, but got too busy when he started working for The Man, and had to relinquish his title!

And speaking of TheServerSide.NET, I just found this site today. My company, which is primarily a Java shop, has sent out broadcast emails before referring to content on TheServerSide.COM. I glanced over that site, and had wished that there was a .NET equivilent, especially since you can get free ebooks, etc. Come to find out, there is an equivilent, just a TLD away!

Friday, May 13, 2005

.NET Rocks!

Yeah, I know, it's 112 episodes into the series at this point, but I've been listening to old episodes of Carl Franklin's .NET Rocks! internet radio talk show focusing on .NET technologies (thank you MSDN for putting all of the first 100 episodes on the spring DVD). I find Carl pretty entertaining, as well as the collection of regulars and featured guests that participate. I was already familiar with Carl's work as the author of Visual Basic 4.0 Internet Programming, which is one of the few technical books that I actually own. Since it's VB4 technology, that's kind of dating myself a little bit (but not as much as stating that I used VB3 professionally for a year or more before VB4 came out!).

Great way to make it through a monotonous workday, as well as being introduced to the major players in the .NET world (whether employed by MS or not).

Tuesday, May 03, 2005

Great Way to Learn Assembly

I don't program in Assembly language on a regular basis, but every now and then, I get the opportunity to play with microcontrollers or other devices that require knowledge of assembly and/or machine code.

Being a high-level developer (VB, Java, C#), it's both interesting and extremely confusing to work at the machine's level. But, I found that a great way to teach myself a new assembly language is to actually write an emulator (simulator) in the high-level language to execute real/compiled machine code.

For instance, in the past, I wrote a simulator for the TMS370 microcontroller because I needed to learn its assembly language to write some serial I/O routines.

A better example for this audience might be to create an emulator for the Z80 microprocessor, simply because there's a lot of real-world programs that you can run (i.e., "Donkey Kong" arcade game used the Z80). Of course, emulating arcade machines involves more than just simulating the CPU and memory--you also need to emulate the graphics system in order to "see" if your CPU emulation is working correctly or not.

But, my point is simple--by forcing yourself to implement each opcode as part of an emulator, including all the different addressing variations, you will truly understand how the opcodes work. And, if you get stuck, you could always check the MAME source code (which emulates a multitude of popular CPUs).

Try it, if you dare! (btw--I'm toying with this very same idea for a book, if I can find the time....damn, I hate working so much).