Monday, April 06, 2009
In a few hours I will be giving a new presentation to the Atlanta MS Professionals User Group. The topic for tonight is Asynchronous UI. I will be talking about a number of common development patterns, along with discussion of the benefits and tradeoffs of each, and demos of the more mainstream approaches. I will also be covering a very simple and elegant solution that meets most async requirements – Jeffrey Richter’s AsyncEnumerator. In advance of tonight’s presentation, I am posting my slides and code early. You can download them from this link. They may also become available as a download for members of the MSPros user group after the session. Also, as a raffle prize, I am donating a one-year subscription to MSDN Premium with Visual Studio 2008 Team Suite Edition. If you were to buy it from Amazon, this subscription would cost over $10,000, so be sure to show up tonight if for nothing else than to win.
Thursday, June 19, 2008
I ran across SoundSnap today – what a great resource for finding free sound effects and music loops. For those participating in the GGMUG Silverlight Game Development Contest, this might come in handy for you, so please check it out! http://www.soundsnap.com/ By the way, the GGMUG is a great venue to meet new people who are passionate about .NET development. If you live on the East side of town, and just can’t make it to those Alpharetta meetings held by the other user groups, then please check this new group out if you haven’t already.
Monday, June 09, 2008
Audio support is all too often one of the last things a developer thinks of when it comes to building a user interface. Fortunately, Silverlight offers some basic building blocks that make it fairly trivial to add event-driven sounds to our applications. I have taken the built-in functionality one step further, and created a simple run-time audio engine that makes it even easier. First, I will discuss the requirements that I had in mind when I created this engine. Second, I will discuss the ideal API for a complete solution. Third, I submit the simple effects engine that I developed in order to meet those requirements and API. Sound Effects Engine Requirements - Must be able to play looping “background music” tracks.
- Must be able to play smaller sound effects on demand.
- Must support concurrent (and overlapping) sounds effects without interfering with already-playing audio.
- Must adequately handle the possibility of download delays when pulling down external audio files.
- Should cache audio files between playbacks.
- Should allow serving of audio from high-bandwidth CDN such as Silverlight Streaming.
An Ideal Sound Effects API - Should be very approachable. If possible, only a single line of code to play any audio (similar to PlaySound() API).
- Should support any formats supported by Silverlight.
- Should be efficient.
- Should offer download and playback completion callbacks (for chaining and synchronization).
- Should support aggressive background pre-caching of audio files.
The SilverlightToolbox Solution To address the simplicity requirements, this sound effects engine is implemented as a single static C# class that can be easily included into any Silverlight project. It can exist in a referenced class library, or can be linked directly into the main project. To address looping background music, a single method SetBackgroundLoop() is supplied. This will begin playback of a single audio clip, and will automatically repeat it. Only one track can be played as the background loop – calling this method again will terminate the running track and start the new one. You can also pass String.Empty to stop all background music. To address typical sound effect clips. two overloads of the PlaySoundEffect() method are supplied. The simpler of the two methods will simply play a clip once it has been downloaded. The extended version allows you to specify a callback for when the clip has been downloaded and started playing, and a second callback that can be used for notification that the clip has ended. To address the scenario where multiple sound effects might be played at the same time, the engine internally maintains a queue of MediaElements. When a new sound needs to played, it pulls an unused element and puts it into service. Once the sound is finished, the element is returned to the queue. This allows Silverlight itself to handle media mixing, and by caching those MediaElements, it does so without placing undue stress on the environment. To address the issue of download delays, the startedCallback and completedCallback parameters of PlaySoundEffect() were introduced. To address caching of audio files, a WebClient is used (which in turn leverages the browser’s cache). Furthermore, the engine will reuse any downloaded file streams (and is smart enough to not re-queue the same file if it already queued for download). By using a MediaElement for playback, audio tracks are automatically supported from streaming sources and Content Delivery Networks, and can be of any type supported by Silverlight. To support chaining of audio effects, and to support synchronization of UI with audio, the PlaySoundEffect() method accepts callback events that are fired when the clip has been downloaded, and again when it has completed playback. To further help with UI synchronization, a second utility class is provided (DelayedAction) which provides a simple wrapper for BackgroundWorker that can be used to easily delay execution of a block of code after a specified amount of time. To support pre-caching of audio files, the PreloadMedia() method can be used. Typical usage: In order for the sound effects engine to function properly, it must be provided with a top-level XAML container (MediaElement currently will not perform playback without a parent object). This is done by calling the Initialize() method, typically from your program’s startup code: SoundEffects.Initialize(this.LayoutRoot);
After this has been done, background music can be played, and we can also queue up some sound effect clips for later:
SoundEffects.SetBackgroundLoop("cautious-path.wma");
SoundEffects.PreloadMedia("pop1.wma");
Then, at various points throughout the application, we can play the sound effect (for example, in response to a control event):
SoundEffects.PlaySoundEffect("pop1.wma");
If at any point we need to delay the sound effect slightly, we can control this be introducing a short delay:
DelayedAction.Execute(2.0, () => SoundEffects.PlaySoundEffect("pop1.wma"));
Complete Source Code for DelayedAction.cs:
1: using System;
2: using System.ComponentModel;
3: using System.Threading;
4:
5: namespace Wintellect.SilverlightToolbox
6: {
7: public class DelayedAction
8: {
9: class DelayedCallback
10: {
11: public TimeSpan Delay { get; set; }
12: public Action Callback { get; set; }
13: }
14:
15: public static void Execute(double seconds, Action callback)
16: {
17: BackgroundWorker Delay = new BackgroundWorker();
18: Delay.DoWork += (s, e) =>
19: {
20: DelayedCallback DelayCallback = (DelayedCallback)e.Argument;
21: Thread.Sleep(DelayCallback.Delay);
22: e.Result = DelayCallback.Callback;
23: };
24: Delay.RunWorkerCompleted += (s, e) =>
25: {
26: Action Callback = e.Result as Action;
27: Callback();
28: };
29: Delay.RunWorkerAsync(new DelayedCallback
30: {
31: Delay = TimeSpan.FromSeconds(seconds),
32: Callback = callback
33: });
34: }
35: }
36: }
Complete Source Code for SoundEffects.cs:
1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Net;
5: using System.Windows;
6: using System.Windows.Controls;
7: using System.Windows.Media;
8:
9: namespace Wintellect.SilverlightToolbox
10: {
11: public static class SoundEffects
12: {
13: static Panel Root;
14: static MediaElement BackgroundLoop = new MediaElement();
15: static WebClient EffectDownloader = new WebClient();
16:
17: static Queue<MediaElement> AvailableSoundEffectGenerators = new Queue<MediaElement>();
18: static Dictionary<string, Stream> DownloadedEffects = new Dictionary<string, Stream>();
19: static Queue<string> PendingDownloads = new Queue<string>();
20: static Queue<QueuedEffect> PendingEffects = new Queue<QueuedEffect>();
21: static Dictionary<MediaElement, Action> PendingStartupCallbacks = new Dictionary<MediaElement, Action>();
22: static Dictionary<MediaElement, Action> PendingCompletionCallbacks = new Dictionary<MediaElement, Action>();
23:
24: enum TargetType
25: {
26: BackgroundMusic,
27: SoundEffect,
28: }
29:
30: class QueuedEffect
31: {
32: public string MediaName { get; set; }
33: public TargetType Target { get; set; }
34: public Action StartedCallback { get; set; }
35: public Action CompletedCallback { get; set; }
36: }
37:
38: public static void Initialize(Panel root)
39: {
40: Root = root;
41: InitializeTarget(root, BackgroundLoop);
42: EffectDownloader.OpenReadCompleted += (s, e) =>
43: {
44: DownloadedEffects[(string)e.UserState] = e.Result;
45: DownloadEffects();
46: PlayEffect();
47: };
48: }
49:
50: static void DownloadEffects()
51: {
52: if (PendingDownloads.Count == 0)
53: return;
54: string MediaName = PendingDownloads.Dequeue();
55: EffectDownloader.OpenReadAsync(new Uri(MediaName, UriKind.Relative), MediaName);
56: }
57:
58: static void InitializeTarget(Panel root, MediaElement target)
59: {
60: target.Width = 0;
61: target.Height = 0;
62: target.Visibility = Visibility.Collapsed;
63: root.Children.Add(target);
64: target.AutoPlay = false;
65: target.MediaOpened += (s, e) =>
66: {
67: MediaElement Target = s as MediaElement;
68: Target.Volume = 0.35;
69: Target.Play();
70: if (PendingStartupCallbacks.ContainsKey(Target))
71: {
72: Target.Dispatcher.BeginInvoke(PendingStartupCallbacks[Target]);
73: PendingStartupCallbacks.Remove(Target);
74: }
75: };
76: target.MediaEnded += (s, e) =>
77: {
78: MediaElement Target = s as MediaElement;
79: Target.Stop();
80: if (s == BackgroundLoop)
81: Target.Play();
82: else
83: AvailableSoundEffectGenerators.Enqueue(Target);
84:
85: if (PendingCompletionCallbacks.ContainsKey(Target))
86: {
87: Target.Dispatcher.BeginInvoke(PendingCompletionCallbacks[Target]);
88: PendingCompletionCallbacks.Remove(Target);
89: }
90: };
91: }
92:
93: static MediaElement GetUnusedEffectGenerator()
94: {
95: if (AvailableSoundEffectGenerators.Count > 0)
96: return AvailableSoundEffectGenerators.Dequeue();
97: else
98: {
99: MediaElement Result = new MediaElement();
100: InitializeTarget(Root, Result);
101: return Result;
102: }
103: }
104:
105: static void PlayEffect()
106: {
107: lock (PendingEffects)
108: {
109: if (PendingEffects.Count == 0)
110: return;
111: QueuedEffect Effect = PendingEffects.Dequeue();
112: if (DownloadedEffects.ContainsKey(Effect.MediaName))
113: {
114: MediaElement TargetElement = null;
115: switch (Effect.Target)
116: {
117: case TargetType.BackgroundMusic:
118: { TargetElement = BackgroundLoop; break; }
119: case TargetType.SoundEffect:
120: { TargetElement = GetUnusedEffectGenerator(); break; }
121: }
122: if (Effect.StartedCallback != null)
123: PendingStartupCallbacks.Add(TargetElement, Effect.StartedCallback);
124: if (Effect.CompletedCallback != null)
125: PendingCompletionCallbacks.Add(TargetElement, Effect.CompletedCallback);
126: TargetElement.SetSource(DownloadedEffects[Effect.MediaName]);
127: }
128: else
129: {
130: PendingEffects.Enqueue(Effect);
131: }
132: }
133: }
134:
135: static void PlaySound(TargetType target, string mediaName, Action startedCallback, Action completedCallback)
136: {
137: if (target == TargetType.BackgroundMusic)
138: if (BackgroundLoop.CurrentState != MediaElementState.Stopped)
139: BackgroundLoop.Stop();
140:
141: if (mediaName != String.Empty)
142: {
143: lock (PendingEffects)
144: {
145: if (!DownloadedEffects.ContainsKey(mediaName))
146: {
147: PendingDownloads.Enqueue(mediaName);
148: }
149: PendingEffects.Enqueue(new QueuedEffect
150: {
151: MediaName = mediaName,
152: Target = target,
153: StartedCallback = startedCallback,
154: CompletedCallback = completedCallback
155: });
156: }
157: DownloadEffects();
158: PlayEffect();
159: }
160: }
161:
162: public static void SetBackgroundLoop(string mediaName)
163: {
164: PlaySound(TargetType.BackgroundMusic, mediaName, null, null);
165: }
166:
167: public static void PlaySoundEffect(string effectName)
168: {
169: PlaySound(TargetType.SoundEffect, effectName, null, null);
170: }
171:
172: public static void PlaySoundEffect(string effectName, Action startedCallback, Action completedCallback)
173: {
174: PlaySound(TargetType.SoundEffect, effectName, startedCallback, completedCallback);
175: }
176:
177: public static void PreloadMedia(string mediaName)
178: {
179: if (!DownloadedEffects.ContainsKey(mediaName))
180: {
181: PendingDownloads.Enqueue(mediaName);
182: DownloadEffects();
183: }
184: }
185: }
186: }
Sunday, June 01, 2008
As a follow-up to the previous post, I have entered Gem Blaster into a game development contest held by the Microsoft RIA Development Center Portal web site. I am happy to say that it has made it into the Finalists group of 6 games that are being showcased for the next few weeks on the RIA web site: http://www.devx.com/RIA/Door/37728 The final judging is done based on popularity among visitors there. They basically track number of visits to each game, as well as how long people stay there, whether they come back and revisit, etc. So if you like it, please pass the link around to your friends and ask them to check it out too.
Tuesday, May 13, 2008
I finally got around to updating my Gem Blaster game from Silverlight 1.1 alpha to the 2.0 beta bits. Since there were very heavy changes to the control model and other aspects of the managed runtime, I had to rewrite a lot of the original code (this was fully expected by the way). While I was in there, I also took the opportunity to add a number of other new features such as a simple sound FX engine, a self-playing "demo mode", and a bunch of other improvements. I intend to update CodePlex soon with the new source code, but for now you can try out the game here (embedded below). It is hosted on the Silverlight Streaming service, so feel free to pass the link around (it won't kill *my* servers). If you like, you can also directly embed the game using the following embeddable HTML snippet: <iframe
src="http://silverlight.services.live.com/invoke/5683/GemBlasterV2/iframe.html"
scrolling="no"
frameborder="0"
style="width:800px; height:625px">
</iframe>
Now that this project has been updated for Silverlight 2, I can move on to my next game project idea which (I am hoping) should really push the runtime to its limits :)
Thursday, April 03, 2008
I have been running a Media Center PC as the hub of my home media network for a few years now - first MCE 2005 and then VMC (Vista Media Center) once it became available. In fact, I am about to install my 3rd XBOX 360 in my house (I use those as media extenders wherever I have a TV). I love my media setup - and more importantly - so does my wife. I pretty much just let things run and don't think too often about it... but this week I ran across this completely awesome application which makes my setup even better... Lifextender. Lifextender has a very simple premise, which is stated on the home page of it's website: "Lifextender is a dead-simple commercial-removal application". The program basically runs in the background where it monitors your system for new recordings. It then analyzes those recordings and removes any commercial pods that it finds. It is pretty good - I would say the success rate is about 95%. When it makes it mistake, it seems to always err on the side of caution and has never removed something I didn't want it to. The modified recordings are about 75% of the size of of the originals - which means it is literally giving me back 15 minutes of my life for every "hour" of commercial-infested programming that I watch. And oh did I mention - It's also FREE (free as in beer)!
Sunday, March 02, 2008
We are happy to announce that the 2008 Atlanta Code Camp is coming up soon. We have confirmed the event date of Saturday, March 29th, and it will be held at the Devry University campus in Decatur (this is the same place as last year). We are actively seeking speaker submissions for the event. You can get the speaker form from our speakers page. We are also looking for volunteers to help on the day of the event. If you are interested in volunteering, please sign up here. Attendee Registration is not open yet, but check back often because it is likely to fill up quickly once opened.
Monday night, March 3rd (tomorrow), I am lined up to present on the topic of "Surviving the Multi-core Revolution". This presentation focuses on the concepts and skills needed to bring scalability and performance to server-based processing.
Wednesday, February 27, 2008
This year I will be heading to MIX in Vegas along with thousands of other UX enthusiasts. I have always had a deep interest in all things related to User Experience, and for the past couple years have wished I could attend a MIX event, and finally this year I get to go! What will I be doing at MIX? Well I will certainly be soaking up any and all information related to Silverlight and WPF. I will also stick my head into some of the designer-oriented sessions. It's a good thing to see how the other half lives. In between sessions I am hoping to meet all kinds of people who are also passionate about UX. And of course this is Vegas, so I am sure I will lose a few dollars in a casino at some point and drink more booze than is healthy. Joining me will be a number of Wintellectuals including Steve Porter, Sergio Loscialo, Rik Robinson, Sara Faatz, and Todd Fine. I know of a number of other local Atlanta folks will be making the trip as well: Sean Gerety, Doug Turnure, and Shawn Wildermuth to name a few. Are you going too? If so, let me know and we can get together for a cup of coffee or a beer.
Sunday, February 24, 2008
I have uploaded my slides and associated source code that was demonstrated, for the benefit of those who were not able to attend my session, or for those who have asked for copies of the code and slides. I understand that these will be made available from the Alabama Code Camp web site, but I am also making them available for download from my server as well: http://www.mindfusioncorp.com/weblog/content/binary/AlabamaCC6-Silverlight-KeithRome.zip
Thursday, January 31, 2008
Last fall I showed off a new game that I had built using Silverlight 1.1 at a few User Group meetings across the southeast. I showed the internal "guts" of the puzzle game, and I think people generally thought it was a really cool project. I promised that I would make the code available, but never actually got around to publishing it. Until tonight. Gem Blaster is now (finally!) published to CodePlex at http://www.codeplex.com/gemblaster Full source code is available there. Also, if you just want to play the game (after all, it IS a game, and somewhat addictive too), I have a "live demo" posted to the Wintellect server here: http://demo.wintellect.com/gemblaster/default.html Enjoy!
Wednesday, January 30, 2008
Yes, you read that right. Silverlight 1.0 - as in unmanaged JavaScript - and 3D. Last week I was reminded of the FarSeer Physics engine for XNA and Silverlight 2.0. I have a strange fascination for 3D software - stemming back from the years when I was a beta tester and plugin developer for Caligari trueSpace 3D - so I decided to poke around in the source code from CodePlex to see what they were doing. Turns out it was just mostly linear algebra and some simple mechanics - things I remembered working with many years ago before the age of managed runtimes and rich visual APIs. Back then we had to do all the heavy lifting with highly optimized C++ routines and drawing directly to an HWND. But things are different now, and what seemed incredibly hard in years past really didn't seem all that hard anymore. So I was inspired I guess. I know I could have started with the FarSeer code, and built upon that using C# and targeting the managed runtime. But oh no - that was too easy! I figured that if it can be done using simple trig and a solid model design, I bet I could make it work in JavaScript. After all, JavaScript's Math intrinsic object supports Sin() and Cos(), extensible objects, and arrays - and at the end of the day, that's all one really needs in order to create a 3D runtime. Sure, it involves a fair amount of matrix operations and dot-products and cross-products, but all those things can be learned by reading up on Wikipedia these days (or mathreference.com). So with that, I set out to create an unmanaged 3D visualization engine for Silverlight... I am making the code freely available and have already published out to CodePlex here: http://www.codeplex.com/polygraph3d My efforts so far are looking pretty good (I think). Over the course of about 8 hours of coding and testing, I have the basics working. I can create a 3-dimensional polyhedron (a mesh if you will), and I can display the object in a Silverlight Canvas. I can apply scaling, rotations, and positioning of the polyhedra, and I can also build complex objects using polyhedron groups, each of which has its own local scaling/rotation/position transforms. It also supports a movable camera and performs rudimentary perspective correction as well as small optimizations for backface-culling. It currently only supports simple brushes for the object faces - I would like to implement a real texture mapping system, but that will require some very creative use of image skewing to pull it off. I have a test page up that demos a simple 3D cube that you can move around the virtual viewport space... For sure, it is a very simple demo. Clicking the red, green, and blue axis bars will move the cube around. The "spin" button introduces a gradual rotation around the Y axis... but since my rotation transform code is currently broken, the effect isn't quite what I had in mind. Hopefully I will figure that particular bug out soon. One major hurdle I encountered was the fact that Silverlight does not let you draw directly on a Canvas, nor does it let you create your own controls. This posed a problem since I wanted to display things that simply could not be expressed using 2D XAML. I "solved" this problem by performing all of the mathematics needed to project the 3D scene into a 2D viewport, and then I use the vertex data from the projected mesh to build a series of 2D Path elements. It was indeed a dirty trick - but hey, sometimes you just have to make do with the capabilities of the platform.
Last Friday was a sad day for Atlanta. One of the local radio stations went off the air. It wasn't just any old radio station though - for a decade and a half 99x was THE station that thousands, probably hundreds of thousands, of people tuned in to every day. You see, 99.7 FM was one of the first "alternative" stations back in the 1990's. Many people heard Nirvana, Pearl Jam, Stone Temple Pilots, and a vast array of other little-known artists for the first time on 99x. Nowadays, many of those "alternative" bands are considered mainstream - but back then they weren't so widely listened to. And 99.7 played a big part in bringing that music to the younger generation. Not to mention all of the local events they supported - Big Day Out, Mistletoe Jam, and many other concerts and other events. When I first came to Atlanta for a job interview, I remember driving into the city for the first time. In fact, it was April 17th, 1997. It was a very nice day - clear sky and about 80 degrees - a typical spring day in Atlanta. As I rounded a corner of I-20 (from the West) and saw the skyline for the first time, I began tuning my radio dial to maybe find a local station that I could bear to listen to. I quickly found 99.7 - I think they were playing a Weezer song (or maybe it was Green Day). Since that day I pretty much never moved my dial from 99.7. Well... except for those painful band interview segments that Axel used to do... Over the last 10 years the station has had ups and downs. More down than up in the past year or so though. I think they were bought out by a large syndicate around that time (the station was independent prior). It is kinda hard to know exactly what was going on, since the station management never seemed to want to just come out and let the listeners know what was happening. Early last week I noticed they started running some weird advertisements about some new "Visual 99x", recommending that people go visit their web site. I blew that off since online streaming music (or worse - video) is just not something I can use while in my car or at a customer site. And then Friday morning I was driving in to work.... And WTF do I hear on the radio? JUSTIN TIMBERLAKE! Or at least that's who I think it was. I was too busy cursing under my breath at my wife who I assumed had run an errand using my car and changed to station to some Top 40 garbage. But no, the tuner claimed it was on 99.7 as always. Then one of little filler stations ads came across - announcing that I was listening to "All the hits - Q100". I think I threw up a little in the back of my throat. So apparently, the new management had fired most of the on-air staff for various reasons over the past few months, and now they finally put the last nail in the coffin and took it off the air completely... and in the process giving the high-power transmission tower to one of their other stations. They could have at least given a real warning to the (many) loyal listeners. So R.I.P. 99x, hopefully another local station will step in to fill your shoes. Because if there is one thing this city does NOT need is another god-awful top-40, country, or hip-hop station.
Thursday, January 10, 2008
To work with an "attached" property in Silverlight (such as Left and Top and ZIndex), we must normally use the pair of accessor methods GetValue() and SetValue(). This is because these properties are not defined for the object that actually uses them, but they are instead defined by another object that contains them. In the case of the Left and Top properties, this would be the containing Canvas. So in order to position an object, we often find that we must write code that resembles this: var LeftPosition = MyXamlElement.GetValue("Canvas.Left"); LeftPosition += 100.0; MyXamlElement.SetValue("Canvas.Left", LeftPosition); This works just dandy, but I often forget that there is an easier shorthand way to work with these attached properties. It turns out that the default indexer for all Xaml objects is implemented through those very same accessor methods. This means that we can write the code from above as such: var LeftPosition = MyXamlElement["Canvas.Left"]; LeftPosition += 100.0; MyXamlElement["Canvas.Left"] = Left Position; This is considerably more readable and even saves a few bytes of JavaScript code, which cuts down on code bloat - even if only slightly. Of course if I really wanted to reduce my code as much as possible, I could have reduced the above snippet even further to this last version: MyXamlElement["Canvas.Left"] += 100.0; And that's about as condensed as it gets.
Monday, January 07, 2008
I ran into a small, but dastardly quirk in Silverlight today. I haven't seen it mentioned out there so figured I would post this in case someone else might suffer from the same problem someday...
If you have a MediaElement being used to display video, chances are pretty good that you also have what is known as a "scrub bar". or at least some buttons used to jump forward or backward in the video timeline. The documentation says that you can accomplish this by interacting with the Position property of the MediaElement. The Position property is of type TimeSpan, which is documented as being immutable except for the Seconds property, which is read/write. In other words, the only way to change the current playback position of a playing media element is to set Position.Seconds to the location you wish to jump to.
The only thing is - this actually doesn't work if you take the documentation at face value. This bit of code doesn't work as you might think it would:
MyVideo.Position.Seconds = MyVideo.Position.Seconds + 10.0;
In fact, that code has no effect at all. No error message, but also no change to the position.
The secret here is that while the TimeSpan is indeed modifiable through the Seconds property, the MediaElement doesn't really care about it unless you reassign the Position property itself. To compound this, there is no way to create your own TimeSpan from code in Silverlight 1.0, so the only option we have is to take an existing one. Here is the code to change the current position (which actually works):
var pos = MyVideo.Position;
pos.Seconds = pos.Seconds + 10.0;
MyVideo.Position = pos;
HTH
Saturday, December 01, 2007
I have not yet found a workaround for this problem. The setup is simple: Create two Canvas elements. In one canvas, place a MediaElement. Point the media element to a valid video source. It doesn't matter if it is set to AutoPlay or not (but if using manual play, then you will need to initiate playback in some manner after loading). Now once that video playback has begun (it doesn't matter how), if you remove the MediaElement from the original canvas using Children.Remove() and then add it to the other canvas using Children.Add(), then the playback position will reset and will start playing from the beginning. I would possibly expect this behavior if the MediaElement has the AutoPlay property enabled, but this also happens when AutoPlay is false. Basically, as long as the media is active, it is restarted if you relocate the element to another parent control. I am guessing this is a bug in the MediaElement's OnLoad implementation that is not respecting the AutoPlay setting if the media is currently being played, and is internally calling Stop() and Start().
I ran into this nasty little bug today... it is not easy to reproduce, but when it happens it is very annoying to debug.
First, this bug only occurs when you are using a ZIP file to package your external resources and using a Silverlight Downloader object to bring the package to the browser, and subsequently using Image.SetSource() to provide the image files to the visual elements.
Second, it's not really a bug in functionality exactly, but more of a nuisance to the viewer. You see, the images get displayed correctly, but Silverlight throws extra error messages.
The problem occurs when you reuse a single image resource from a downloaded zip archive for multiple Image elements. And it only happens when the two images are assigned to the same resource consecutively. Example:
function downloadComplete(sender, eventArgs) { // this one is OK sender.GetHost().FindName(“Image1”).SetSource(sender, “picture.png”); // this one fails sender.GetHost().FindName(“Image2”).SetSource(sender, “picture.png”); }
This is using Silverlight 1.0, but I assume the same issue also happens in 1.1.
The problem appears to be related to referencing the same resource twice consecutively. If you reference another resource from the Downloader between the two calls to SetSource(), then the problem goes away. Also, if you simply don't reuse the same resource like this, then it can be avoided.
UPDATE January 2008: My previous "fix" of referencing another resource in between uses of the same resource does not seem to always work. In addition, some Silverlight installations (not all!) are also raising spurious ImageError 4001 messages. The only complete fix I have found is to implement a custom error handler, and ignore those ImageErrors:
function handleError(sender, errorArgs) { if (errorArgs.errorType == "ImageError" && errorArgs.errorCode == 3002) { // This error is raised sporadically by SetSource return; } if (errorArgs.errorType == "ImageError" && errorArgs.errorCode == 4001) { // This error is raised sporadically by SetSource return; } Silverlight.default_error_handler(sender, errorArgs); }
Friday, November 30, 2007
This coming Monday night would normally be our monthly Atlanta MS Pros / Atlanta Cutting Edge .NET / Atlanta VB.NET user group meeting, but this month we have a special treat lined up... Microsoft (aka Doug Turnure) will be providing a FREE copy of Visual Studio 2008 (Professional Edition) to the first 150 people that arrive. This is a GREAT way to get an upgrade right away without having to convince your boss to buy a license! Well, technically we will be giving out DVDs with the trial version, but as soon as the Retail Packages are ready, each person that gets a Trial copy on Monday will receive a full Retail Boxed copy. So bring your laptop. Most folks will be loading it up right there, so you might as well join in and get your upgrade on. And then, after the LoadFestivities, everyone will be welcome to come join in some XBOX fun... we have 9 (yes, NINE) xbox 360 consoles and 9 matching big-screen TV's, so there should be plenty of room for everyone to have a good time. The name of the game is Halo3, so put on your MJOLNIR armor and get ready to frag your buddies! And if John-117 is too intense for you, we will also have Guitar Hero cranking on some of the consoles... so you can come and rock out to some Hit Me With Your Best Shot on Easy. I hear the Master Chief himself might be there to take on challengers! Please register in advance, so that we can have an accurate count of attendees. The registration link is here. Location: Microsoft Corporation [Alpharetta] 1125 Sanctuary Pkwy. Suite 300 Atlanta, GA 30004 See you there!
Thursday, November 15, 2007
A few weeks ago, for no obvious reason, I lost the ability to multi-select files in Windows Explorer. Control-Click, Shift-Click, Control-A, none of those hotkeys would work. The mouse "rubber band" selection tool was non-functional, and even the corresponding selection options from the View menu were disabled. I never realized how dependant I was on the multi-selection feature. Tasks that were normally simple were suddenly monumental. Lucky for me, a little bit of Live Searching helped me find a solution: apparently the per-folder settings that Explorer likes to save can get corrupted. The fix is to delete the folder settings data. For some people, you can simply go to Folder Options under the Tools menu, and click the button to "Reset Folders". That didn't work for me though. I had to manually delete the folder settings data from the registry. Warning: Messing with the Registry is Bad mmmkay At this key location, you can find a few sub-keys filled with lots of nasty gobbledy-gook data values and nested sub-keys: HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\ Deleting the BagMRU and Bags subkeys here (and obviously all of their contents) corrected the problem for me (for now). Your mileage may vary.
Tuesday, October 23, 2007
My last post was somewhat negative. I acknowledge that. I was annoyed. Let me make amends by posting some useful, positive information for those who find themselves on the other end of the interview table (or phone). Google Live Search your interviewer. Most recruiters will tell you who will be performing your interview. If they don't venture the information, then ask for it - chances are if they know then they will tell you. Take that name and do some research. Get to know what your interviewer is most likely to be questioning you about. If they have written a book on security best practices, then there is a pretty good chance they will ask you questions about security. Do drop subtle hints that you read their weblog - most tech people like to hear that - just be sparing in it. You don't want to come off as a stalker. - Be honest about your skill level. Many interviewers will ask you how you rate yourself, so that they can judge just how delusional you are. Be honest here. If you claim to be a 10 out of 10 in a subject area, then you had better be an absolute expert. A 10 out of 10 is expected to know that subject inside and out, perhaps even teach the interviewer a thing or two. Don't be too humble though. Rating yourself as a 2 out of 10 is highly unlikely to get you into the interview room in the first place.
- Don't interrupt. When the interviewer is speaking, never (and I mean NEVER) forcibly interrupt them. I have had many interviews where the candidate would inject words, statements, or questions while I was trying to guide the interview towards the next topic. Doing that does not impress the interviewer with your profound wisdom. What it does is send a clear message that you feel your thoughts are more important than the interviewer's... which is nothing but a fast track to bottom of the resume stack.
- Speak clearly. No need to shout, but you should be certain that you speak confidently and with ample volume to be heard clearly. Avoid slang terms - especially cursing! Try to provide concise and accurate answers, with as few "umms" as possible. And for heavens sake, if you don't know the answer to a question, just say it rather than trying to BS your way through it.
- Be prepared to ask questions about the employer's business and work environment. Even if you already know the answers (you did research the company's website beforehand, didn't you?). This shows an interest in the company and team.
- Be prepared to answer strange, sometimes seemingly irrelevant questions during the interview. Good interviewers are not looking for right or wrong answers to every question - they are looking for clues about how you work your way through problems and how you are able to handle stressful situations. This is especially true in the Consulting industry, where your reaction to a crisis is often more visible and more important than the act of correcting the underlying problem itself.
- Follow-up. If you already did a technical screening and are now in for the "big face to face" interview, chances are good that you missed at least one of the questions during the screening. You should note those questions during the initial interview, and research them before going to the main interview - especially if the interviewer is the same person. Let them know that you felt compelled to research the topic on your own time, and that you now have an answer for that missed question if they would like to hear it. Chances are they won't want to hear the answer, but they will take notice that you followed up and did your homework in between the interviews.
- Be calm. It is normal to be nervous. Some folks even have obvious nervous twitches that come out in full color during something as stressful as an interview (sweating, fast talking, jittering). Take a few steps to defeat those demons beforehand - exercise rigorously the morning before your interview, this will clear your mind and stabilize your metabolism, which helps control sweating problems. Learn some deep breathing exercises if you need help calming down beforehand. Never, under any circumstances, drink a "Double Vente Latte Machiatto" or other "energy drink" less than an hour before the interview. All that caffeine will lead to a panicky interviewee that talks WAY too fast and incoherently, and that is trying to hold their bladder for an hour. Nothing good can come of that.
- Sleep well the night before. Don't study your "interview cheat sheet" late into the night. Go to bed early, and go to bed with a clear mind. You will not sleep well if you spend the night ruminating over those questions and answers. In fact, I understand that taking an over-the-counter aid (if you are healthy enough) can help. Seasickness medications such as Bonine can clear nausea from "stomach butterflies" that might precede a stressful interview, and also have the nice side effect of being a sleeping aid (causes drowsiness). As always, check with your doctor before taking something like that.
- Smile. The interviewer is not only looking to see if you know the technical answers to their questions, they are also evaluating whether they would want to work with you on a team or not, and if you know how to enjoy working with others. When interviewing, the measuring stick I often use is to ask myself "Would I be comfortable having a beer after work with this person?". You might be surprised how often the answer to that is "no" (especially in the ultra-bizarre circus of tech workers).
And here is a "bonus" tip submitted by David Daughtrey... 11. Dont eat at the Wing Factory on the night before an interview. Or any hot wing establishment for that matter.
I have been in this industry for quite a while... about 15 years. I have spent the majority of that time in upper-tier roles, or at least as "upper tier" as it can be without losing touch with the technology itself. I am one of those "hands-on" folks that would never ask a person on my team to build something that I wasn't 100% positive that I could (and would) do myself. As a result, my technical skills have always been kept sharp. And because of those very solid technical skills, I have almost always been deeply involved in the recruitment and interview process at whatever companies I have worked for. I typically perform several interviews per month, sometimes more, sometimes less, generally depending on hiring urgency or other market conditions. But this morning I have had without a doubt the WORST interview I have ever had to participate in. I will not divulge the name or anything else about this person, as that's not my style, so please do not ask. But what I can do is provide some advice on things you should NOT do unless you really want to bomb an interview horribly... What NOT to do in an interview: - If you are asked to "self rate" yourself, give yourself a 9 out of 10 in a new "buzz" technology that you really don't know much about. The interviewer won't know the difference anyway.
- Give the recruiter your cell phone number even though you know you get horrible reception where you expect to be taking technical screening calls.
- Before starting a technical screening, be sure to tell the interviewer that your skills are "more broad than deep" so that they will see just how fabulously excellent you are even if you miss a bunch of the questions.
- When the interviewer asks an entry-level question that you don't know, complain that "those kinds of nitpicking questions are for a more junior person than me", and follow it by "I usually manage people who would answer those kinds of questions".
- Try to turn the tables on the interviewer if you don't think you are doing well. Try to convince them that they are being unreasonable by asking them a technical question of your own. The idea here is to make sure that they can't answer it correctly - in fact, just make something up! Here is a good one to try: "what’s the parameter five of the MoveWindow?". Without a doubt, you will have made your point to the interviewer.
- Be sure to argue with the interviewer that they are wrong about their own entry-level question. After all, only a moron would claim that "SQL Server" was one of the three "out of the box" configurable options for Session State storage in ASP.NET.
- Remember, nothing can prove you wrong, not even Truth itself. If the interviewer isn't asking you the questions that you want them to ask, then it is surely because they are not worth your time. In fact, you should tell them that they ask too many nitpicking questions, and then hang up on them.
What a complete tool.
Thursday, October 18, 2007
While it probably will not get as much attention as a Visual Studio or Windows Service Pack release, the Expression Team blog announced that there is an SP now available for Expression Design that solves some very nagging issues with the RTM version of the product. These problems mostly impacted those of us using Design and Blend with Silverlight, most were a nuisance and had workarounds, but this update really improves the "flow" of creating a Silverlight or WPF UI. Some of the "big" fixes from my perspective: - Gradient Midpoints are now exported (glass fanatics across the globe rejoiced). This was one of my pet peeves with gradients - you could use Midpoints to create truly spectacular glass and glow effects in Design - but they would end up more along the lines of "craptacular" when exported to XAML. The workaround wasn't 100% equivalent, and was fairly annoying (convert midpoints to new gradient stops before exporting).
- Exporting to XAML will now emit the correct (forward) slash character in image paths for Silverlight exports. This was an annoying problem when Silverlight 1.0 was sent to RTM and no longer supported the backslash.
- Text exported as TextBlocks instead of Paths. Thatsa verra niiice!
One thing that hasn't been addressed that still bugs me is how the exporter handles layers: Each layer becomes a canvas stacked, each stacked on top of the other. This isn't inherently troublesome, except that the canvases all start at 0,0 and fill the workspace... which basically means that only the topmost canvas will recieve mouse events by default. It would be better if the exported canvases were only as large as they needed to be, and positioned accordingly. Then again, I guess I could always file a bug/suggestion report that would be more likely to be seen by the Expression Team...
Wednesday, October 17, 2007
John Robbins, the wizard of debugging, is looking for suggestions for the Devscovery 2008 Keynotes. To encourage submissions, he is offering a FREE conference pass to the person with the best idea. Full price for such a pass is $900, which is a bargain in itself, but FREE is even BETTER! The spring Devscovery will be in New York, and the fall Devscovery will be held in Redmond - the winner will get to choose which event they prefer to attend. Having attended the fall Redmond conference this year, I HIGHLY recommend it! Even if I weren't a Wintellect employee, I would still be comfortable claiming that this is hands-down the best way to spend your training time and budget. To submit a keynote idea, please either comment on John's post here or email your suggestion directly to him. You can submit as many ideas as you like.
Thursday, October 11, 2007
I haven't posted much recently. Not that I haven't had anything to say, but I have just been really quite busy. In fact, I just returned from my first visit to the Netherlands and England, where I spent a few weeks vacationing, I mean working, on a solution architecture assessment for one of our clients. Accounts vary, but here is more or less how the first day of our trip unfolded (according to my admittedly hazy recollection): We arrived at Schipol airport in Amsterdam on Sunday morning. Early on Sunday morning... 6:30 AM to be exact. But we could not check into our hotel in Emmen (almost a 2 hour drive from Amsterdam) until later in the afternoon, so we decided to explore the city a little. But first thing's first - it was early in the morning, and Roger needed a cup of coffee. After asking a number of locals where we could find the nearest "coffee house" and getting puzzled facial expressions in return (or the odd "isn't it rather early in the morning for that?"), we decided to take matters into our own hands. So we punch in the instructions to Roger's GPS-enabled PDA... Within a few short minutes, the GPS has located a suitable establishment. There is just one problem - the "road" it sends us down appears to cross this body of water somehow (I don't see a bridge or tunnel...): No worries. We select the next place in the list. Just a few miles, err kilometers (we are in Europe now) away. So we forge ahead, and lo and behold... Apparently Roger's PDA thought we were looking for really large, red trash containers. Undaunted, we press on. The third entry in the GPS list looks more promising, so again we follow it's directions. We get to see some interesting places along the way... And finally we arrived at the cafe. The coffee seemed to really help Roger's alertness for the rest of the morning, but I did notice he had difficulty concentrating on things and carried a bizarre grin for hours... With our morning caffeine secured, we decided to spend the rest of the day exploring the history and architecture of Amsterdam. Our first stop was the museum, where we both learned a lot about things that happened in our families' past: We admired the remarkable structural engineering of the Dutch. I was especially impressed with their uncanny ability to build perferctly level buildings on flat land. By the end of the morning we were quite tired. We found a group of people who seemed like locals, and asked them where they would recommend we stop for lunch. They were very helpful indeed, and pointed us to a nearby establishment where we had a bite to eat and were able to quench our thirst. I must say, the tap water there is significantly more tasty than what we have here in in the US. 
Saturday, September 01, 2007
We have not sent out a bulletin message yet, but we will not be meeting on Monday 9/3 due to the holiday. The next Atlanta Cutting Edge / VBUG / AMP meeting will take place in October.
Tuesday, August 28, 2007
Steve Porter and myself are driving up to Charlotte tonight to present on Silverlight at the Developers Guild meeting. Steve will be giving an overview of Silverlight features and development, and of course I will be deconstructing my newest Silverlight game - Gem Blaster!
If you remember Popper!, this is the next generation of that game engine, upgraded to work with the newer Alpha 1.1 Refresh, and with better graphics and gameplay. You can also go directly here to play the game: http://www.mindfusioncorp.com/gemblaster/
EDIT: The game has been moved to the Wintellect servers at: http://www.wintellect.com/gemblaster/
I am also working on getting the source code published to CodePlex, but it has taken a while due to my very busy work schedule.
Wednesday, August 15, 2007
Using the August CTP of Expression Blend 2? Worried about the lack of a registration key and that ever-decreasing "remaining days" counter at startup? The Expression team has released a new refresh build to address that. This build is supposed to not expire until January 2008. It also has a refreshed Silverlight template that creates projects compatible with the Alpha 1.1 refresh that shipped earlier this month. You can go here to find out more. Too bad they didn't get in a quick fix for the clipped menus bug too...
Wednesday, August 08, 2007
Here is a second Silverlight demo you may or may not have seen already... this one is from a former colleage, John West. AirportWait (http://www.airportwait.com/) is a website that provides congestion data for the various checkpoints in your local airport (where provided). It basically lets you get an idea of just how early you should plan on getting to that gate in order to make your flight. Silverlight is being used to create the polar (circular) charts. Check it out!
Jeff Prosise just published a new code sample to his Wintellect blog to show his Silverlight adaptation of the classic Game of Life, which he calls "SilverLife". It's a really cool demo of Silverlight capabilities and programming model, and pretty fun to play with as well. Best of all, he has the source code available to download as well so you can see exactly how things are being done under the hood. Go check it out! 
Monday, July 09, 2007
This year, both Dan Attis and myself recieved MVP awards from Microsoft. I am very honored that my contributions to the developer community have been recognized, and I hope to continue giving to the local community in the years to come... but at least now my wife can see something tangible to show for all of my involvement (she has a hard time with the fact that I spend almost every monday night out at UG meetings instead of being home with her). Anyways, I am very pleased to have been given this award. Special thanks go to Doug Turnure for supporting us local guys, and also thanks to my wife for putting up with it all, and both my current (Wintellect) and former (Intellinet) employers for having the vision to support involvement in the community.
Monday, July 02, 2007
Popper! is a simple Silverlight puzzle game. I wrote it as an exercise of my own skill with the platform, but then decided it was a rather fun (at least for a little while...) little game, so I am sharing it with the rest of the developer community. Popper! is written against Silverlight 1.1 alpha, and is mostly in C#, although the initial splash screen is done using unmanaged javaScript (yes, on purpose). I will be walking through the innards of Popper! at the Atlanta Cutting Edge .NET User Group meeting tonight. So if you will be attending, then come check it out. Or if you just want to kill some time at "work" today... then play with it a little and let me know how it goes (good or bad)... http://www.mindfusioncorp.com/popper/ I know of one minor bug so far: if you try to click around while a set of bubbles is in the process of "popping", then an error is raised internally, and the game pretty much stops working. I just haven't had the time to get that bug addressed yet. I intend to post the source for this sometime after this month's meeting. Pretty much that equates to "when I have time to do it".
Thursday, June 14, 2007
UPDATE 10/25/2007: Updated this sample to function correctly with the Silverlight 1.0 release. The main changes necessary were the typical 0.9 to 1.0 changes (remove "Sys.", isWindowless now takes a string and not a boolean, event handlers no longer string based), and I also had to explicitly set the z-index of the INPUT element. Thank you Erik for bringing it to my attention.
I have seen a lot of questions and confusion regarding capturing input when using Silverlight. There are no Button, TextBox, or other similar controls to work with. I see many folks asking for help with building their own directly within Silverlight - and bless their hearts, that is a daunting task indeed! The UI model currently does not offer basic input capture features such as "focus" or "tabbing", or even control-level keystroke capture. So folks tend to start building those basic services first, before they ever even get to writing code and xaml to support that simple textbox they need.
If you read that first paragraph and thought "thats crazy, it shouldn't be that hard!", then I would agree with you. Fortunately, there is a FAR easier and more robust way to achieve the same thing. In fact, its something that is not new to Silverlight at all, it's been with us for years. I am of course talking about the tried-and-true html <input> tag.
One of the most overlooked aspects of Silverlight is that it is a component, not a platform. Your browser is the platform. It can do a lot of stuff, if you just ask it to. Nobody wants an entire site as a single Silverlight canvas, just like nobody wants an entire site as a Flash canvas (unless possibly it is a mini-game or rich media application)... Flash designers realized this fact years ago. And as a component, a part of the solution if you will, Silverlight can play nicely with it's neighbors. With just a little bit of effort and sprinkling a very minimal amount of javascript pixie dust, we can get a Silverlight applet talking to the rest of our html DOM. And that's exactly what I am going to show in this topic...
You can download the code demonstrated in this article here (QuickTip-TextboxesInSilverlight.zip).
First of all, I am doing this with Silverlight 1.0 beta (the javascript one), as I think the 1.1 alpha is far too likely to change, and this technique should work with either. That, and I am lazy and don't want to come back and revisit this post later to correct the code...
Secondly, I am using the current CTP builds of Visual Studio Orcas and Blend 2 (the May 2007 bits), both with the Silverlight extensions. If you are using something else, then your mileage may vary.
UPDATE 10/25/2007: Code updated for VS2008 beta2 and the RTM version of Silverlight 1.0.
Now on to the code... to be sure we are on the same page, I am creating a new project from scratch...
First, Create a new project in Blend. Select the Silverlight 1.0 (JavaScript) project type. It does not matter what you name the project, but for this example I went with "TextboxesInSilverlight".
Switch to XAML view and replace the default canvas with this markup:
<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="252" Height="272" Background="#FFFF2121" > <TextBlock Width="64" Height="24" Canvas.Left="8" Canvas.Top="8" Text="Opacity" TextWrapping="Wrap"/> <Ellipse Opacity="1" Fill="#FF0406FF" Stroke="#FF000000" x:Name="TheCircle" Width="180" Height="180" Canvas.Left="36" Canvas.Top="64"/> </Canvas>
This will create a simple red canvas, with a blue circle.
At this point, I generally switch over to Visual Studio Orcas since Blend does not have Intellisense nor does it really know how to deal with JavaScript. You can do this easily by right-clicking a project item (such as the xaml file) and selecting "Edit in Visual Studio".
Next, we need to do one small housekeeping chore to make sure that our Silverlight canvas plays nicely - specifically, we need to ask it to operate "windowless", which will allow other dhtml elements to overlay it, Open the Default.html.js file, and modify the call to Silverlight.createObjectEx(). We want to add the parameter for isWindowless...
Silverlight.createObjectEx({ source: "Scene.xaml", parentElement: document.getElementById("SilverlightControlHost"), id: "SilverlightControl", properties: { width: "100%", height: "100%", version: "0.9", isWindowless: "true" }, events: { onLoad: sceneLoaded } });
To make things a bit more "clean", we will create the input element directly from code, however it's always good to control visual styling with CSS. Therefore, open up the Default.html, and alter the <style> tag to match the following:
<style type="text/css"> div, body, input { margin: 0; padding: 0; } #opacity { margin: -272px 0 0 75px; z-index: 100; } .silverlightHost { margin: 40px auto auto auto; height: 272px; width: 252px; } </style>
This will handle the placement and sizing of the silverlight container <div> as well as the input control itself. The negative margin is not a typo - this is used to pull the input control "on top" of the silverlight canvas. We could have also used absolute positioning, but that is much more brittle, relative positioning FTW. Also, notice the use of "auto" margins for the main Silverlight Host <div>. This is how you can center content without resorting to using <center> or <table>... if you take nothing away from this post, at least remember that one trick.
The last thing we must do is wire the whole thing up. This can be done in many places, in many ways. I consider this particular TextBox to be an extension of the Xaml "scene", so I will add my code to the TextboxesInSilverlight.Scene class which was created for us by the Blend project template. This is not the only place you could do this kind of code, but I found that in this particular example it made the most sense. Had I been building a dialog for a game engine, I might have this code in a seperate script file that manages my game mechanics (but thats another article...).
First, we need to capture a global reference to the Scene object that is created (this object is instantiated by the createSilverlight() function of the Default.html.js script file we edited in a previous step). The purpose of capturing this reference is that we will need it later in an event handler. This will allow our html <input> control to communicate back with the silverlight content. This is easier done than said. Open the Scene.xaml.js file. Just before the definition of the TextboxesInSilverlight.Scene.prototype (look up javascript prototype for what this is if you are interested, but that discussion is out of scope for this article), add a line of code to declare the global reference:
var globalScene = null;
Now we will create a callback function that will be used to create our JavaScript object and initialize it:
function sceneLoaded(control, userContext, rootElement) { globalScene = new TextboxesInSilverlight.Scene(); globalScene.handleLoad(control, userContext, rootElement); };
Now, the idea for this example is that the value of the text box will determine the "Opacity" Xaml property of the Ellipse shape in our markup. In order for the event handler we are about to add to be able to do this, we will capture a reference to the circle object (technically we can wait and use findName() later during the event handler, but I prefer to capture it only once - its just my style of coding). Add this line to the handleLoad function:
this.circle = control.content.findName("TheCircle");
Next, we will create the input control and add it to the DHTML document. We will add it directly to the same <div> that Silverlight has injected itself into, and therefore any layout or positioning that affects the Silverlight canvas will also affect our <input> box. Add this code to the end of the handleLoad function:
var opacityEdit = window.document.createElement("input"); opacityEdit.type = "text"; opacityEdit.id = "opacity"; opacityEdit.name = "opacity"; opacityEdit.value = "1.0";
We are almost done - only two more steps and then we can fire this thing up! First, we need to add an event handler to react to changes in the value property of the input control. Add this code to the very end of the handleLoad function:
opacityEdit.onpropertychange = function() { if (event.propertyName == "value") { globalScene.circle.Opacity = event.srcElement.value; } }
This effectively creates an anonymous function to handle property change events on the <input> control, which in turn updates the Opacity property of the circle shape. Cool, huh?
The last thing to do is finally add the new <input> element to the page, otherwise all the work until this point will have had no discernable impact at all... add this one last line to the handleLoad function:
this.control.parentElement.appendChild(opacityEdit);
At this point, your Scene.xaml.js file should look like this:
if (!window.TextboxesInSilverlight) window.TextboxesInSilverlight = {};
TextboxesInSilverlight.Scene = function() { }
var globalScene = null;
function sceneLoaded(control, userContext, rootElement) { globalScene = new TextboxesInSilverlight.Scene(); globalScene.handleLoad(control, userContext, rootElement); }
TextboxesInSilverlight.Scene.prototype = { handleLoad: function(control, userContext, rootElement) { this.control = control; this.circle = control.content.findName("TheCircle"); var opacityEdit = window.document.createElement("input"); opacityEdit.type = "text"; opacityEdit.id = "opacity"; opacityEdit.name = "opacity"; opacityEdit.value = "1.0"; opacityEdit.onpropertychange = function() { if (event.propertyName == "value") { globalScene.circle.Opacity = event.srcElement.value; } } this.control.parentElement.appendChild(opacityEdit); } }
If the typo gods favor you, then you should be able to use F5 to run the page and see it all working together:
Notice the positioning of the input textboxes, and the interaction of them with the underlying Silverlight canvas. This is just a simple example, but can be a very powerful way to "plug in" Silverlight into the surrounding DHTML.
Thursday, May 10, 2007
The Geek Dinners are back. Although usually attended by microsoft developer types, these are really open to anyone with a geeky side that needs reassurances from their peers that "it's OK to be a geek". Shawn has more details here. Be sure to RSVP with him if you are going - so tha he can handle the accomodations properly.
Sunday, May 06, 2007
Tomorrow night is the Atlanta Cutting Edge .NET User Group meeting for May. Actually, it's also the May meeting for the Atlanta MS Pros and VB.NET groups as well. We will all be sharing the facility and sponsorship, as well as having a combined networking period before the meeting and a combined "keynote" presentation for the first half hour. After that, we will split up into 3 rooms (well technically, we will probably just close the walls and divide the main room into individual sections), each of which will offer a seperate track of material. We have a track for Cutting Edge, one for VB.NET, and one for MS Pros. For more details, including the topics and speakers that are scheduled, please refer to the user group website at http://www.atlantace.com/
Monday, April 30, 2007
It has been a good while since this industry has had a significant shake-up, where the world as we know it changes almost overnight, and our skills and practices are all made obsolete. We generally seem to have one every few years or so, and according to my calculations, it has been about 7 or 8 years since the last one. I am sure there were other events, but the first I can recall was the introduction of Object Oriented programming in the 80's. This paradigm shift left multitudes of mainframe COBOL and RPG analysts behind, forever to toil in a world of green on black terminal displays. Then in the early and mid 90's there was an explosion of "client-server" and "N-Tier" applications in the business world. These were all the rage, and again the flock was divided. Many OOP purists were left in the dust, trying to fend off the "younger kids" that embraced the 3GL and 4GL tools of the day. But as luck would have it, only a few years later the terms "client-server" and "N-Tier" took a back seat to the newest technology explosion - the age of the Web. Right or Wrong, everyone wanted to be on the web. Try as they might, the n-tier supporters could not withstand this assault. To this day, there remains a contingent of developers that cling to the world before the web - in the Microsoft kingdom, we call them "Windows Forms Programmers", or perhaps the slightly more dignified "Smart Client Developers". But the significant majority of development work admittedly goes into Web applications. So for the last few generations of the industry, roughly every five to seven years, we experienced a wholesale disruption in the status quo. Things are no longer what we thought they were. Skills become unmarketable. Management becomes confused. Projects get scrapped. We have to retool - retool or else go the way of the Do-Do Bird (extinct). The only problem is - it has been about eight years now since the last paradigm shift (I do not count .NET as a paradigm shift - it is simply a consolidation and improvement on ideas and methods already in place). It has been eight years, and I fear that we are long overdue. More than that though - I feel that perhaps, just perhaps, the paradigm shift has already begun - and that I can't see it due to my own Myopia. And what if the shift has already passed me by, and I have missed it entirely? In conclusion, I think the shift is just now underway. I have smelled the crispness in the air that precedes a thunderstorm. I think the industry is about to change again, in a very significant way, and I hope to be a small part of it yet again. But in order to accept and participate in a significant change, a person must adapt to the new way of things. To that end I have begun the arduous task of retooling and rebranding myself. This will not be the first time, nor likely the last. As a as/400 specialist, converted to PC technician, converted to Delphi developer, converted to DBA, converted to Web Developer, and finally to .NET windows/web developer, I can say that I have definately been through this process before, and it does not scare me. What scares me is the thought of not adapting. Some of the people I know and trust feel that they too have "seen the light". Some have their own theories about where to be when the music stops playing. My good friend Scooter seems to think that Sharepoint is the entire future. I don't necessarily agree with that. I have heard similar theories about the grand direction of things from others as well ("Linux is the future!", "Everything will be AJAX!", "OMGZ It's all going to Pocket PC format!") - most of which I cannot find reason with either. Everyone seems to agree that the winds are changing, only nobody appears to agree on the direction. But I have my own ideas and theories and will once again be betting the next half-decade or longer of my career on that insight. It hasn't let me down in the past - I trust it will not let me down this time either.
Wednesday, April 04, 2007
Today I was on MSDN Subscriber Downloads to pull down an ISO that I needed. First I noticed this in the Partner VLA Keys section: Then I noticed the new download in the downloads area: Then I checked my RSS Reader and saw these posts by Somasegar, Walt, Tim, and Forest. To make a long story short, Expression Web is now available to folks with MSDN Premium subscriptions, and Expression Blend will be available upon release. If you have one of the flavors of VS Team Suite w/ MSDN Premium then you will also have access to the full Expression Suite (I think this includes Expression Design and Expression Media?). And while it was not reported on any of the above blogs, I assume that Certified and Gold level Microsoft Partners will also be granted a certain number of licenses for internal use - since I currently see it listed in that section. This is great news for WPF fans. Tool availability is one of the biggest things holding back adoption of Fx 3.5, and this move to make Expression tools available to MSDN subscribers (without jacking up the price ala TFS) will help smooth the transition.
Friday, March 30, 2007
In case you missed the highly successful Atlanta Code Camp, there is another one coming up in Mobile, Alabame on April 14th. Registration is currently open, and I do not think they are sold out (yet). Like always, this Code Camp is a free event and it is jam-packed with lots of great topics being delivered by great speakers. If you are anywheres near Mobile that weekend, it would be worth signing up for. http://www.alabamacodecamp.com/
Saturday, March 03, 2007
Please join us on Monday, March 5th at 6:00 PM for the monthly Atlanta Cutting Edge .NET User Group meeting. ************************************** This month we have two speakers: Paul Lockwood will be presenting Semi-Advanced Production Debugging - a brief discussion on little known debugging techniques including WinDbg and the sos.dll. About the speaker: Paul maintains a weblog at http://www.dotnetworkaholic.com/. Also speaking this month is Eric Engler who will be presenting ASP.NET AJAX: Beyond the UpdatePanel. This session will provide an overview of ASP.NET AJAX. Eric will briefly cover the basics of ASP.NET AJAX, and then he'll drill down on some of the less commonly known, but very powerful aspects. Among the subjects to be discussed will be: - The parts of the AJAX Distribution
- UpdatePanel - a brief obligatory overview
- The ScriptManager
- AJAX Control Toolkit: design of server-side control extenders and custom controls
- JavaScript: how to use objects in a non-OOP language
- AJAX Client Library: micro sized version of the .NET Framework written in JavaScript
- ASP.NET AJAX Application Services
- Calling Web Services from the Client
- Debugging AJAX applications
About the speaker: Eric is a Senior Software Engineer at ZC Sterling, a real estate insurance and tax servicing company in Atlanta. He has over 20 years of experience programming many languages, on many platforms. His current focus is on Visual Studio and C#, including all types of applications: Windows, Web, and middle-tier. He holds a MCSD.NET certification. Website: http://www.EricEngler.com Thanks go to our sponsor Intellinet (www.intellinet.com) for graciously providing refreshments during the meeting. This month's agenda (Monday, March 5th) * Networking starting at 6:00 * Announcements at 6:15 * Paul Lockwood – Production Debugging at 6:30 * Break at 7:00 * Eric Engler – ASP.NET AJAX at 7:15 We will be meeting at the Microsoft Regional Headquarters at the Sanctuary Park complex in Alpharetta (Mansell Rd. Exit). The meeting begins at 6 PM so folks can mingle, however the announcements and presentations are not scheduled to begin until 6:15 PM. For more information on this month's meeting, please visit our website at: http://www.atlantace.com/ If you are not familiar with the meeting location, please print out the driving directions for reference: http://www.atlantace.com/MeetingLocation.aspx **** A CALL FOR SPEAKERS **** If you have a topic that you would like to present to the group, please contact me to discuss your ideas. We have lots of available time slots in the coming months, and our group is a fantastic place to hone your public speaking skills and to contribute back to the user group community. ***************************************** NOTE: You have received this message because your email address was registered at the Atlanta Cutting Edge .NET website at http://www.atlantace.com/ or the Atlanta C# Developers Group website at http://www.atlantacsharp.org/. ***************************************** Thanks, and I hope to see everyone at this month's meeting! Keith Rome MCPD-EAD MCSD MCDBA MCAD
Wednesday, February 21, 2007
For those who know me well, this will be old news. As of last Monday, I have been a consultant with Wintellect. This new position gives me the opportunity to "get in early" and help shape a consulting organization from the ground up. I will also get to continue building my technical and management skills and perhaps have a chance to get in on some more exciting projects that leverage the newest technologies. My two years at Intellinet were a great employment experience, and I would definately recommend them to prospective employees and clients without hesitation. I still have many good friends there. Frank Bell and the Intellinet EMT have managed to build a great working environment, and they have some of the best technical specialists in the region. I wish them the very best, as it was a very difficult decision when I decided to move on to this next phase of my career.
Wednesday, February 14, 2007
I used to love Berry 411 for my old Intellinet-supplied BlackBerry. But now I have a T-Mobile Dash (Windows Mobile 5) and need a good local business search / mapping tool. Lucky for me, Windows Live Search for Mobile went final this week... and it is awsomely better than Berry 411. And by Awsome, I of course mean Totally Sweet. If you have a Windows Mobile 5 phone, you can install it directly from http://wls.live.com/.
Thursday, February 08, 2007
At this month's Atlanta Cutting Edge, I presented a short talk on basic project management and estimation using PERT techniques. This is a topic that I find most developers (and managers too!) tend to ignore because they assume it woul dbe uninteresting or perhaps "fake science". Quite the opposite is actually true, and it can be astounding how much positive impact some of these techniques can bring to a software development project. So if you were there and requested the slides, or if you were simply not able to make it, here they are.
Wednesday, January 31, 2007
OK, so I was tagged by Brendon quite some time ago. Here are 5 things you may or may not know about me, but probably do not: - I am really picky about the comfort of my clothes. This drives my wife nuts. Especially when I remove the tags from most of my shirts (they itch!).
- Food that is supposed to be warm is utterly revolting to me when cold. The mere thought of cold pizza sends a shiver down my spine. I don't mind eating leftovers, but my wife has to open the refrigerated container and heat it (I can't even be in the same room - I can pick up the foul smell of cold leftovers from 20 feet away).
- I can smell several offensive odors from a good distance. If you eat something with heavy garlic, onions, or curry, then I can generally smell you sweating the odors for up to two days afterward. Coffee and asparagus I can also detect for up to 12 to 24 hours. When I have a cold though, I cannot smell any of it.
- I am hooked on XBOX Live gamerscore points. At 5295 points, I finally surpassed Shawn. My next goal is 10k points, which I hope to reach by mid-year. I did not own an xbox until 7 months ago, so hitting a 10k score is not unheard of.
- People who insist on talking or interrupting a movie are at the very top of my peeve list. I like to watch a movie from start to finish without interruption and without being asked questions. This is why I rarely go to the theater, and why when I actually do watch a movie, I try to do it without my wife being there (she feels compelled to talk through a movie and to try to get my attention when I am obviously focused on the film).
So there you have it, 5 things about me. The good thing about waiting a full month to respond to the tag is that I don't really know 5 other regular bloggers who haven't already been tagged, so I am going to terminate this branch of the blogtag. After all, chain letters inevitably end with someone unable to continue the chain.
Thursday, January 25, 2007
One of the skills I have had an opportunity to sharpen over the past year has been Team Leadership. And I would like to take a moment to get my thoughts "on paper" for those who might be reaching a point in their own career where the information could be useful. It's not really something I thought much about before coming to Intellinet - it was always something that had been thrown upon me, and I was expected to quite simply "sink or swim". Luckily for myself and the projects I was involved in, I always landed on my feet and did at least an OK job with leadership - even if I had no idea what I was doing at the time. Fast-forward to Intellinet, my responsibilities here, and my participation in an internal leader training program modeled on the writings of Andy Stanley, who also happens to be a highly successful pastor for what some would call a "megachurch" based in Alpharetta. Through this program, we studied his "Next Generation Leader", a very short (160 pages) book that attempts to convey his thoughts on what makes a good leader. Of the many things learned through this experience, the one thing that was truly eye-opening is his Andy's assertion that "leadership is about having and conveying clarity and vision in a sea of uncertainty". In other words, a good leader does not simply follow a pre-mapped course - if so then he would merely be just a guide. A good leader rises through confusion and uncertainty, defines the path ahead, and drives forward towards that end goal - with willing followers in tow. That's not the only thing we learned however. We also learned that leadership is earned - it is not something that people will usually give to you simply because of title or rank. Not only is leadership earned, but it comes through strength in character and morals (moral authority)... people will not follow a corrupt leader for long. The last really big thing I picked up from the leadership study sessions - in Andy's words "Only do what only You can do". There is a strong tendency to try to improve skills that you are lacking in - in an effort to achieve "balance". In fact, this just draws focus away from the things that we have a natural strength in. Besides, by focusing on the things we are naturally good at, we can make room for others who are natural complements to our skills - who themselves have a natural strength in those areas where we are weak. And that's what team-building is all about. Anyways, I could go on about this for a few pages more... but would rather not spoil the entire book in case you might be considering giving it a read. Its good stuff - and now I at least understand why and how some things work well in a leadership position and others do not.
Tuesday, January 09, 2007
Databinding in .NET is immensely powerful. You can bind nearly any property of any object to any property of any control. The source object can be any .NET object - a business component, a DataSet, a built-in .NET class, or even another Control! Of course like any powerful feature, the Devil is in the Details.
Simple versus Complex Binding
To understand the databinding system first requires acknowledgement that there is in fact two "flavors" of databinding. You can bind to two very different categories of objects, and this is what differentiates the flavors of binding. The two flavors are called Simple and Complex binding. This is somewhat of a misnomer in my opinion as there is nothing inherently more complicated about Complex binding - it's just different. I would prefer to call these two forms of binding Item and List binding, as that more accurately describes their use. In fact, I will try to refer to them as such throughout these posts.
Item Binding
Item Binding refers to the connection of a source object property value to a target control's bindable property. These connections are typically two-way, in other words you can change either side of the connection and the databinding system will push the change to the other side. Another cool aspect is that you can bind many controls to the same source property - however you cannot bind a control's property to more than one source. An example of this would be binding the Text property of a Label control to the FirstName string property of a Customer object.
List Binding
List Binding refers to the connection of a source list of objects to a target control that is capable of display and/or navigating between multiple items in the list. The source list can be any .NET object that implements IList, ICollection, IEnumerable or IBindingList, including arrays, collections, generic lists, and DataTables. In more advanced scenarios, an object that implements IListSource can also be used - IListSource simply defines a list of lists. Controls that are able to participate in List Binding include the ubiquitous DataGrid/DataGridView, and many other controls that consume lists of items for various reasons - DropDowns, ListBoxes, and TreeViews to name a few.
Mixing and Matching
Unfortunately, you usually cannot mix (or should not mix) both Item and List Binding in the same source objects. Due to the way the databinding system discovers and uses databinding interfaces (will be discussed in a followup topic), it is not possible to have both Item and List bindings on the same object. An example of this would be binding to Customer entries in a list as well as the Count property of the list itself.
Examples
Item Binding Examples
When creating Item Binding connections, you always begin with the target control, and add to its DataBindings collection a list of property names and their sources. DataBindings.Add() is an overloaded method with two main usage scenarios. Most of the time you will use the form of Add(PropertyName, DataSource, SourcePropertyName). In more rare situations you might want to create a Binding object directly and and use the form Add(Binding)... this can be useful when you want to override default formatting and parsing of values.
- Binding to a property of a business object
Customer C = new Customer("John");
TextBox TextBox1 = new TextBox();
TextBox1.DataBindings.Add("Text", C, "FirstName");
-or-
Binding B = new Binding("Text", C, "FirstName");
TextBox1.DataBindings.Add(B);
- Binding to a public field of a business object
You can't do it in this version of the framework!
- Binding to a field in a DataTable
DataTable CustomerDT = new DataTable("Customers");
CustomerDT.Columns.Add("FirstName", typeof(string));
CustomerDT.Rows.Add(new object[1] {"John"});
TextBox TextBox1 = new TextBox();
TextBox1.DataBindings.Add("Text", CustomerDT, "FirstName");
- Binding multiple controls to the same source data
CheckBox CheckBox1 = new CheckBox();
TextBox TextBox1 = new TextBox();
TextBox1.DataBindings.Add("Enabled", CheckBox1, "Checked");
List Binding Examples
- Binding a grid to a DataTable
DataSet CustomerDS = new DataSet();
DataTable CustomerDT = CustomerDS.Tables.Add("Customers");
CustomerDT.Columns.Add("FirstName", typeof(string));
DataGrid CustomerGrid = new DataGrid();
CustomerGrid.DataSource = CustomerDT;
Note that the following can also replace the above DataSource assignment:
CustomerGrid.DataMember = "Customers";
CustomerGrid.DataSource = CustomerDS;
However, it is very important to realize that while on the surface they may appear to give identical results, these datasource assignments are not the same! I will explain this further in part 6 of this series.
- Binding a ComboBox to an array
string[] StatusList = new string[2] {"Active", "Canceled", "Completed"};
ComboBox CurrentStatus = new ComboBox();
CurrentStatus.DataSource = StatusList;
Note that with a ComboBox, the List Binding is what is used to supply the list of possible values displayed when activating the control.
- Binding a ListBox to a Business Object Collection
List<Customer> CustomerList = new List<Customer>;
CustomerList.Add(new Customer("John"));
CustomerList.Add(new Customer("Mary"));
ComboBox CustomerSelection = new ComboBox();
CustomerSelection.DisplayMember = "FirstName";
CustomerSelection.ValueMember = "CustomerID";
CustomerSelection.DataSource = CustomerList;
Note that ListBox controls, like ComboBox controls, use a List Binding to supply values for the range pf possible values. They both can also use an Item Binding to connect the actual currently selected value to a data source object.
To Be Continued...
Sunday, January 07, 2007
Why would I care about Databinding? Perhaps you are just writing some server code. Maybe XML processing, web services, or even some good old-fashioned application server components. If so, then maybe you really shouldn't care about Databinding. But maybe - just maybe - you are building the User Interface for an application. Or perhaps a set of business objects that will eventually be displayed in a User Interface. And maybe, just maybe, that interface happens to live in the world we now call "Smart Clients". If so, then three paths will lay before you: - You can pretend that databinding does not exist and manually update/read data values directly from UI controls.
- You can try to ignore the intricacies inherent to databinding and hope that everything works out (might be OK if nothing in your UI is "outside of the box").
- You could embrace the beast that is .NET Databinding, study and plot against your foe, and finally prevail against that poorly documented adversary which has terrorized legions of .NET developers.
OK, well maybe it's not quite that exciting, but there is definitely some interesting (I think) stuff to be learned when you take a deeper dive into the world of .NET Databinding. In a series of topics I hope to shed some light on this dark and often cursed part of the .NET infrastructure. In my past few years of .NET experience I have had to tackle databinding from many angles, and have managed to develop a fairly good grasp of the subject (I think - ...always more to be learned). Hopefully I can share some of that with readers. So let's see where this goes...
Friday, January 05, 2007
For nearly a year I have been bogged down in what I can only describe as a quagmire of a project. But this week that all changes - I am moving on to some new work finally, and maybe - just perhaps - I will have more time to blog about the things I have learned and re-learned during that time...
As announced earlier today by Jim Wooley:  Fellow Code Campers, I hope you all had a wonderful holiday season and I want to wish everyone a Happy New Year. Registration for the 3rd annual Atlanta Code Camp is now open. Please register on the Click to Attend website to guarantee your spot at the Code Camp. Here's the link: https://www.clicktoattend.com/invitation.aspx?code=113135 Just a reminder. The 3rd annual Atlanta Code Camp will take place on January 20th. The event is completely free and lunch is included. Doors open at 7:30am at the Decatur campus of DeVry University 250 North Arcadia Ave Decatur , GA 30030 If you are coming in from out of town, we have a recommended hotel near the event. Call the Holiday Inn and ask for the DeVry University rate to get a $99/night rate. Parking is extra and costs $7/day Holiday Inn 130 Clairemont Ave Decatur, GA 30030 404-372-0204 During the Code Camp, lunch will be provided at no cost to you. After the event, we are planning on gathering in a local eatery to continue any discussions which we were not able to complete by our 5:30 pm end time. Location information will be made available at the event. The Atlanta Code Camps have historically "sold out" extremely rapidly and we don't expect this time to be any different. Please register quickly to lock in your spot as we are capping registration and attendance due to facility limitations.
Tuesday, November 21, 2006
I have been using Vista RC1 and now RC2 (havent loaded RTM yet) for a while. I have liked the interface and speed (yeah - it's actually faster than XP was on my laptop). I have also been getting used to some of the "weirdness" such as the new explorer interface and control panel wizards. Overall I think its a good O/S, but nothing has really made me say Wow. Until today.
Background: My old printer, a DeskJet 895Cse finally died on me, and my fax machine has been unreliable for years. So I decided to just get one of those "all in one" printer, fax, copier, scanner do-hickeys. I picked up an OfficeJet 6310 from Fry's. I really had low expectations for the thing. With a price under $200, I really wasnt expecting anything more than a crappy install experience.
So here I go. Power it on. Plug it into the ethernet hub. Installation works fine on my wife's XP laptop. Then for the real test - I inserted the install disc into my Vista machine. As expected, the installer freaks out and refuses to run. A quick check on the HP website confirms that there are no public drivers for Vista yet. I didnt really expect to find any, to be honest. I even fired off a quick email to support to inquire about Vista drivers. To my surprise, I got a reply within 10 minutes. And it wasnt just "so sorry, vista not supported"... they actually gave me a workaround using an older XP driver for another printer that was compatible enough to enable simple printing - if I was OK with connecting via USB. Which I didnt want to do.
But that got me thinking... I wonder if I can convince the printer to work as a regular TCP/IP print server. I have configured plenty of LPR ports in 2000/XP, so I figured maybe I could get a few of the config parameters right by guessing, and coax it into working for me.
First thing that came to mind - I remembered being surprised by the network browsing support in Vista a few weeks ago when I noticed how it detected my router, and even knew that it had an admin page (hth did it know that?). Just browsing the "Network" desktop icon had revealed that the usability team has been hard at work improving the previously horrible network browser feature. With that experience in mind, I tried a quick network browse to see if Vista would spot the new printer out there. I was amazed to see that not only did it spot the printer, but it also knew that it supported a web-based admin page (I didnt even know the printer had that feature!).
Seeing that Vista obviously was playing very well with the printer as a networking peer, I figured I might as well try my luck with adding the TCP/IP printer port. I was very surprised to discover that what used to be a tedious and easy-to-screw-up process was now very streamlined... I simply went to Add New Printer, chose Locally Attached, and then Add New TCP/IP Port. So far, pretty much what I expected. Then on the next wizard page it asks for the printer's IP address. I thought "cool, it looks like it will be smart about prompting for the port config details".
Clicked Next and totally expected to see a screen full of configuration settings and printer queue names, etc. Instead, the wizard asked if I would like to let it try and figure things out on its own. Nah, it won't work. But I try it anyways... Trying to locate printer... Found printer... detecting manufacturer... detecting model... installing drivers... finished - would you like to print a test page?
Wow. I am totally impressed with how well this worked. Network printer configuration used to be a royal pain in 2000 and XP. Sometimes it's the little things like this that make a difference.
Tuesday, November 14, 2006
Join Doug Turnure and guests on the third Monday of every month at the Microsoft regional headquarters in Alpharetta for a "Lunch and Learn" event.
These events are 1 hour in length, held from noon to 1pm. Lunch is not provided - you will need to bring your own if you wish to eat. The content itself is level 100 to 200.
This month, the topic is WPF and Cardspace. Visit Doug's weblog for more information if you are interested... Lunch and Learns at Microsoft
Saturday, November 11, 2006
I am very pleased. Today I took the second of two upgrade tests needed to convert my existing MCSD certification to the new MCPD-EAD (MS Certified Professional Developer - Enterprise Application Developer) - and passed it by a comfortable margin! I am fairly sure this makes me the first Intellinet consultant to carry this new certification.
The test itself was pretty tough - I am very lucky to have had enough exposure to deep WSE and Remoting. A good 20 of the 58 questions were directly related to WSE3 implementation details - and quite picky too. SOAP Filters, policy, addressing, referral cache, signing/encryption, etc... this test hit nearly everything. For remoting, the test covered client and server declarative as well as imperative configuration of the channels and services/clients. There were even a significant number of questions on message queueing and serviced components. In all, I am quite impressed with the depth and breadth of testing coverage.
I actually wanted to take this test a few months ago (I took part 1 while the tests were still in "beta"), but I was holding out to see if my employer was going to institute a reward policy for obtaining certifications - something that many of our competitors do. I finally just gave up on waiting and scheduled the test before my free test voucher expired. Intellinet would have paid for the test - but free is free.
Now I just need to decide whether I want to pursue updating of my MCDBA credentials...
Tuesday, September 05, 2006
Tonight is the September meeting for the Atlanta Cutting Edge .NET User Group. Jim Wooley (RSS ) will be presenting on LINQ - the new language integrated query extension technology. This is really cool stuff IMO. Normally we meet on the first Monday of every month, but with yesterday being a holiday, we moved this month's meeting to tonight. In case you don't have it yet - our new User Group's URL is http://www.atlantace.com/.
Sunday, August 20, 2006
There was about a month or two where I was offline due to a various reasons: First I was in the process of moving, and then I was waiting for Comcast to perform their installation, and lastly I have been putting in a good bit of time to keep up with my work commitments. All of that being said, I have to admit that another huge reason for my recent silence was that I bought an Xbox 360 and now have a super-sweet HD home theater system to play it on! I finally have my home system the way I want it. Media Center system is actually in another room - I only have the XBox as a video source in here (using XBMCE). I had all of the surround speakers installed into the walls and ceiling - thats the white panels on the wall. I still need to take the grills down and paint them to match the wall color, which will make them blend in much better. I also took the opportunity to run a 6 source / 6 zone structural audio system. Thats just a weird way to say that I can play any one of 6 audio sources (including the media center) to any one of 6 rooms in the house. Each room has it's own volume control and source selection keypad, and a pair of stereo speakers flush mounted in the ceiling, as well as a pair of outdoor speakers for the courtyard. I know it sounds excessive, but it wasnt terribly expensive to do while the house was still being framed, and it's a fantastic upgrade for resale value if we decide to move again in a few more years. Not only that, but it's super cool to have.
Testing out the new Windows Live Writer blog posting tool. First thoughts... - I really like the interface. Very similar to OneNote 2007 (which I have been relying on heavily lately). Perhaps this is where the "blog this" menu action in OneNote will go to in the RTM of Office 12?
- PITA to set up for my dasBlog configuration. But then again, at least it works in the end. Can't say that many of the other blogging tools were even viable (I have tried out a few like Performancing and others).
- It's Pretty quirky, definately not ready for RTM yet. First bug found: If you post an entry from Live Writer, and then delete it from within your blog, and try to repost a new copy from Live Writer,.. there is a really good chance it will fail. Second bug found: Ignore that "Date/Time" property for posts - dasBlog fails to decode it correctly and once set in Live Writer, it doesnt seem to be able to be cleared.
- I really like the way it handles inline images. It just works.
- The connection with MapPoint is pretty cool too... I wish they would support Google Maps as well.
- I thought it was interesting that the "Insert Link" dialog knows about the semi-standard rel=nofollow attribute.
- Before publishing, it really should give me a warning that no categories have been selected, or at least an option to enable such a warning.
And in case you were wondering what it looks like... Very cool... just Window-S (a screen capture hotkey from OneNote) then Ctrl-V into Live Writer. That productivity alone makes it worth using for me (for a while at least). If you want to try it out, you can find some details from this link ---> Introducing Windows Live Writer. You can also download the beta install directly from this link --> Writer.msi (direct link from MS Download site). Lastly, if you are using dasBlog then you will definately want to follow the guide from their documentation site: Posting to dasBlog with Windows Live Writer.
Wednesday, May 31, 2006
Just in case you happen to monitor this weblog, but have not registered with the group's mailing list:
------------------------------------
Please be aware that due to inability to secure a speaker for this month, the Atlanta C# User Group will NOT be meeting in June.
Also, the July meeting would fall adjacent to the Independance Day holiday, and therefore there will not be a C# Meeting in July either.
Our next scheduled meeting is currently expected for August, more details will be posted when we get nearer to the meeting date.
**** A CALL FOR SPEAKERS ****
If you have a topic that you would like to present to the group, please contact me to discuss your ideas. We have lots of available time slots in the coming months, and our group is a fantastic place to hone your public speaking skills and to contribute back to the user group community.
**** SPONSORS ****
If your company is interested in sponsoring a month (or more) of the Atlanta C# Developers Group, please contact me to discuss. Sponsorship is inexpensive and a great way to market your organization.
*****************************************
NOTE: You have received this message because your email address was registered at the Atlanta C# Developers Group website at http://www.atlantacsharp.org/ .
*****************************************
Keith Rome MCSD MCDBA MCAD
Monday, May 01, 2006
This is my first time experiencing the new home construction process, so please bear with me 

It's definately starting to look a LOT better...
Sunday, April 30, 2006
In case you haven't heard, the 2006 Atlanta Code Camp site has now begun accepting registrations. This year promises to be even more successful than last, we have nearly thirty topic submissions, so many in fact that we will not be able to accept them all due to the realities of physical meeting space and event logistics.
We are planning on 5 different topic tracks, so there should be a little bit of something for everyone.
You can now register for the Atlanta Code Camp by clicking on the registration link on http://www.atlantacodecamp.com/ or go directly to the registration site at https://www.clicktoattend.com/invitation.aspx?code=108776.
Sunday, April 16, 2006
Been a bit out of touch recently... the reason being that this is my second straight 70-hour workweek.
Not burnt out or anything - just too darn busy to do much else besides sleep, eat, and work.
Anyways, thats enough of a break, time to get back to it...
Thursday, March 30, 2006
On Sunday (5 days ago) all there was was the foundation...

And today, I just decided to swing by and check to see if they started framing yet...

Wow that was fast!
Sunday, March 26, 2006
Just finished reading CLR via C# by Jeffrey Richter - fantastic source of deep info. Highly recommended.
The Atlanta C# Developers website revision project is progressing nicely. Thanks Dan, Mitch, and Rik.
Lots of cool news coming soon from the Atlanta MS Pros team. Can't really say much about it right now - but its way cool!
Working on some other groovy local .NET community things - not sure what I can or cannot talk about yet, so thats all I am gonna say for now.
My new house starts framing tomorrow morning - wootz!
My current house still hasn't sold - egads!
And lastly, yes my current job has me busy as ever, boredom is most certainly not a problem these days...
Tuesday, February 28, 2006
Paul Lockwood gave an interesting presentation last night to the .NET UG on TDD. I will admit that haven't integrated this methodology deeply into my own development habits (yet). I do however recognize the benefits, and fully intend to incorporate it into my habits, just taking things one step at a time as I push my own skills to ever higher levels. So to me, the discussion was quite timely. Listening to audience feedback, it appears that a number of folks ( Rusty, Marcie, etc) are already leveraging this technique... and have some really positive opinions of it. When smart people are recommending something with such enthusiasm, it is generally a wise thing to pay attention. One thing I would have liked to have seen is an end-to-end example of the process itself. I have seen unit tests before, I have even used NUnit on a few projects, but never to much success. I always felt like I was "not getting it". I get the impression (mainly from Rusty's comments), that this is normal, and there is a point of critical mass, serendipity if you will, where it all just starts to "make sense", and your Unit Tests become the first-class citizens that they deserve to be. I want to reach that point, but am shooting blind right now... a slight nudge towards that light is really what I need I think. My current development habits have served me well (I have been told on more than one occasion that I am the most meticulous developer ever to pick up a keyboard), but I wish to push it to the next level. Zero defects in QA Iteration 1 is the Holy Grail. So now I at least have an idea of what I need to work towards. The next step is finding the best path to get there.
It was brought to my attention last night that I have been neglecting to update my weblog lately, at least not as much as I used to. In my defense, I have been slammed with delivery of a fairly decent size project, along with preparing my home for sale (and buying/building a new one). Once this project winds down a little, expect to see more activity here. I have finished a few more books, and will post reviews of them. We (the Atlanta MS Professionals) have some cool stuff coming, and for that matter so does the C# Developers group. Once things get moving I will post more about that. Ciao for now.
Tuesday, February 21, 2006
Last night, the Atlanta MS Professionals User Group was treated to an outstanding presentation by one of the great gurus of Windows programming - Jeffrey Richter of Wintellect. His coverage of the internals of CLR thread termination and associated concerns was extremely enlightening. I would rank this talk as easily being in the top 5 presentations I have ever had the opportunity to attend (and I have seen a LOT in recent years).
Anyways, Jeffrey has a new book coming out in March ("CLR Via C#: Applied Microsoft .Net Framework 2.0 Programming"), which he claims will be his last. I made sure to pre-order a copy ($50!) so I can divine some of his wisdom and insight.
Friday, February 10, 2006
I have a new batch of invitations available to give out... if you are still using the old MSN Messenger, then shoot me an email and I will hook you up. First come, first served.
Update: All invitations are used up now, sorry.
Monday, January 30, 2006
Rik explains how to use a Visual Studio macro to search for highlited text using Google (or alternatively from MSDN2 online) directly from within the IDE... its a pretty cool trick.
Which reminds me - Rik R has been a friend of mine for a few years now (a former coworker from 2001/2002), we were building highly interactive websites years ago using javascript, xml, and XmlHttpRequest. Today, we would call such a system a "Web 2.0 AJAX site". But back then, it was seen as heretical - since postbacks were the status quo. Anyways... I finally talked him into blogging... you can catch the feed at www.r2musings.com as he writes about his journey in the land of .NET
Speaking of new bloggers.... I also convinced Dan Attis to pick up the habit not too long ago... and as you can tell from the activity on his weblog, he is quite the prolific writer!
Sunday, January 15, 2006
Last May, I posted about how I was signing up for an internet-based file backup service. I saw it as insurance for my personal data, and an investment in my personal sanity. Today was the day I had to "cash in" on that investment.
The server that I have been using to store my personal files at home has been on its last leg for a while now. I went through the trouble of installing a RAID controller months ago and configuring for mirrored drives (faster recovery with mirrored, and besides I didnt have enough drive bays to support raid 5).
The strong winds yesterday caused the power in my home to waver on and off, which was the death blow for my ailing rackmounted UPS. And in it's final moments, as a last act, the UPS must have sent a spike into the server... because at this point, the server refuses to boot, or even to POST test. The redundant drives, while protecting me from a disk failure, are pretty useless without a server to power them up.
Thats when the internet backup came to the rescue. I was able to restore every byte of lost data (last successful backup was only the day before). Our digital photos, old emails, online banking files, corporate documents, source code repositories,... everything was salvaged!
I am very glad that I had the foresight nearly a year ago to plan for a significant data loss, and by taking the right steps managed to mitigate the risk, saving my personal digital valuables which would surely be lost today if I had not. I would definately recommend a data protection/backup service such as Storage Guardian to anyone with personal data that they consider important (which is pretty much everyone that owns a computer, isnt it?).
Sunday, January 08, 2006
I wanted to go see Serenity in the theaters, but a friend of mine insisted that I watch the Firefly series first, to get the story background. He insisted that it would be worth the time to watch the first season. So one of the things I got for xmas this year was the first season of Firefly on DVD.
Wow, this show was fantastic! I now see why people who have seen the show have become loyal fans. I popped in the first disc last night around 10pm. I figured I would watch maybe one or two episodes then call it a night. At 5:30 in the morning I finished the second DVD (episodes 4 through 7) and finally went to bed... that leaves two more DVDs to get through yet... but this show was pretty darn good. It was nothing like what I expected. I was simply told that it was a sci-fi story that I would enjoy.
This is like Tombstone plus star trek plus the dukes of hazzard (the show, not the movie) all rolled into one... I never imagined I would like a "western" flavored series, but I certainly dig this one. I just need to find 8 more hours of spare time so I can watch the other episodes....
Then I can start thinking about when I will ever have time to watch the Lost and Battlestar Galactica first seasons on DVD that I also missed during broadcast but now have on DVD...
Thursday, January 05, 2006
I came across this site tonight... it is another ajax framework with some interesting stuff going on behind the scenes. This approach really lowers the entry bar for building simple ajax-driven portlets (it can literally suck in a functional page and inject the content into a new web part / portlet)... a nice and simple approach.
Check it out at http://www.pageflakes.com/
They are also claiming to be giving away an xBox 360 in a "flake building" contest through february.
Friday, December 16, 2005
The batteries in my racked UPS decided to flake out recently, and now every time the wind blows and we get the slightest power dips, my servers go offline.
I am now rehomed to http://www.webhost4life.com/ so hopefully I get a little more uptime in the future.
Tuesday, December 06, 2005
I have been following this blog for a while now - it is quite active and has great timely information on AJAX technologies (not just .NET either - they talk about anything ajax):
http://www.ajaxian.com/
.
Sunday, December 04, 2005
I recently needed to implement an HttpHandler in a project to handle retrieval of rendered PDF reports from a database. It shouldn't have been a big deal, very few lines of code, even less than typical since my Business Logic Layer encapsulates all of the aspects of the data retrieval itself into a single line of code... my handler only had to set the ContentType, add a couple of headers (Content-Length and Content-Disposition), and then BinaryWrite() the data. Easy as pie, or so I thought.
The file streamed fine out of the database - no surprises there. Content-Length had no issue and once I remembered to install Acrobat Reader into my VPC where I was testing this, then the ContentType of "application/pdf" worked as well.
But try as I might, I could not seem to get that darn Content-Disposition to be recognized by Internet Explorer! Every time I tested it, the "Save" dialog would always display a random file name, instead of the one I supplied in the header.
I double-checked, then triple-checked my code. I had two other web developers look at the code, and give it a thumbs-up. I even resorted to tracing the HTTP protocol traffic just to be 100% certain that IE was getting the HTTP header. Sure enough, the header was being set and IE was seeing it. But it wasnt obeying it.
It turns out there seems to be a maximum length to the filename you can supply using the attachment notation of the Content-Disposition header. And my filename was in excess of that limit, causing it to be ignored by IE. While I am not sure what the exact limit is (or if it is some other kind of esoteric bug in IE), and do not have time to experiment and discover that limit, simply reducing the length of my attachment filename has resolved the issue.
By the way, the length of the filename causing a problem was only something like 40 to 50 characters, which really isn't unrealistic. I was embedding the report execution date/time (in a string format that is valid in a file name), in order to prevent saved reports from being overwritten.
Monday, November 14, 2005
"The last 10% of any project is always 90% of the overall work."
It is true all too often.
Friday, November 11, 2005
Just leave it to Mark P. to find something as useless as this...
According to the Gematriculator, my weblog is apparently only 27% evil. I really need to work on my evilness.
Thursday, November 03, 2005
The folks at Microsoft Research have been working on a "research" operating system they call Singularity.
So what's so cool about this?
Singularity turns current preconceptions of operating systems upside-down. 95% of the microkernel is written in a variant of C# called Sing# (the rest is assembly and C). They use a native compiler to turn that MSIL into real bytecode. So there isn't a "CLR", at least not in the kernel.
The concepts of Processes, Threads, Drivers, and Communications is totally up-ended as well. Everything in Singularity runs in a "SIP" (software isolated process)... applications, services, even drivers. These SIPs all run close to the metal in ring-0, cannot reference memory addresses in the kernel or any other SIP, and are required to be verifiably safe. SIPs are only allowed to communicate with each other via something called the "ExchangeHeap", and then only by tight message/protocol contracts. A side effect of the way they forced the strong-typed "owned messages" is that certain data transfers that were traditionally heavy on bitcopies are now zero-copy operations. They also defined some S# language extensions to define these message patterns - it's pretty slick stuff really.
You can read the entire project overview whitepaper to find out all the other cool stuff they managed to do in this Concept OS.
I read the paper, and was totally expecting the cost of executing everything in isolated SIPs to be a performance dog. I was shocked to see that in actuality, the performance was equivalent (or in some cases phenomenally better) than other *tweaked* modern operating systems.
Anyways, this is some cool research. I suspect parts of this work will wind up in future OS products - I recall the CLR team was reluctant to discuss the ideas of "hardware CLR" - perhaps they are further along in that regard than they are leading people to believe...
Tuesday, November 01, 2005
Who in the hell at Microsoft came up with the briliiant idea of 1-based arrays? And why oh why didn't they discard that abomination when transitioning from VB6 to VB.NET?
Of all the stupid VB quirks - THAT one has caused me unending grief.
VB is supposed to be INTUITIVE, but I am sorry... if I DIM or REDIM an array, asking for ZERO elements, I damn well expect that array to hold ZERO elements afterwards. Not one NULL element!
Arghh!!!
Friday, October 21, 2005
I saw this come across on slashdot this morning...
It seems VMWare has a new free "player" product. It appears to be the same as vmware 5 workstation, except that you cannot create new virtual machines or add hardware to existing ones - you can only use machines created using one of the full-featured versions (Wkstn/GSX/ESX). Aside from that, it's supposed to be fully-functional.
And it claims to support Virtual PC / Virtual Server images as well.
And thats pretty cool, since vmware has always been a better virtualization product than VPC. The only reason most shops use VPC right now is because it comes with MSDN subscriptions.
Monday, October 17, 2005
This was a presentation I gave earlier this month (October 2005) to the Atlanta C# Developer Group.
Code generation is one of those "cool" techniques in software development where you just don't know what you have been missing until you see it in action... and then once exposed to it, you find yourself wondering "how did I ever get along without this?".
In this presentation, I discussed the reasons and benefits of using code generation tools, and the problems they can solve (or avoid entirely). I focused on the benefits of consistent code, building upon a solid foundation, and simplification of complex application features.
We designed and built the code for a basic application foundation, supporting simple features such as lightweight enforced transactions, entity persistence, and other baseline features. Then a series of linked templates were created that take advantage of that code foundation. Finally, we built an example UI that leverages the generated middleware to dramatically simplify and streamline the actual development process. It was pretty durn cool IMO.
All templates were built using CodeSmith, which is a fantastically useful tool. I feel like I might have been giving a sales pitch for that product by showing off many of the way too cool features of the new version of CodeSmith, but it's one of those things I strongly feel is worth every penny.
The powerpoint slide deck and all relevant source code can be downloaded from the presentation archive of the Atlanta C# Developer's Group website at: http://www.atlantacsharp.org/PresentationArchive.aspx
I actually gave this short presentation to the Atlanta C# Developer Group back in September, but never got around to blogging about it...
The presentation covered why you should be using custom exception classes in your own code, and how to structure your exception class inheritance to gain the most benefit. It showed working examples of the concepts. It also touched on a few related practices such as only catching exceptions that you can deal with, and designing a meaningful exception taxonomy.
The slides and source code can be downloaded from the Atlanta C# Developer Group's presentation archive at: http://www.atlantacsharp.org/PresentationArchive.aspx
Monday, October 10, 2005
The third installation of the Sharepoint 1, 2, 3! training series is next Monday and Tuesday. This session goes deeper into the capabilities of SharePoint than our previous two sessions did. We will be covering advanced topics such as connectable web parts, Office integration, Document Library Events, Workflow Implementation, the SharePoint Object Model, and SharePoint Web Services!
We have thirteen detailed demos packed into this session, so this is definately tailored for folks who are comfortable writing code. Just like last month, attendees of the Hands-On Lab will also recieve a DVD containing the training materials loaded on a trial version of Windows Server 2003 (VPC image). This is a really cool take-away that allows you to share what you have learned with your cohorts back in the office. It also makes a great way to demonstrate the power of Sharepoint to that skeptical manager! We also expect to have Content CDs available that contain the presentation slides as well as the Hands-On Lab manual and code snippet files. All of this will be made available at the Hands-On Lab on Tuesday night (we are still debating on whether or not to offer the Content CDs after Monday night's seminar as well).
Our first two sessions were extremely popular, with fantastic positive comments from across the board. The Hands-On Lab for Tuesday night is already fully-booked, but it you show up with a laptop and are willing to be slightly inconvenienced we most likely will not turn you away (our training room is only designed to hold about 20 people, but as we proved at the first HOL session we can manage to fit up to about 40).
There is still room to sign up for the seminar on Monday night however. You can get more details and find a registration link on our main website at http://www.sharepoint123.com/. Just like the previous sessions, the coming Sharepoint sessions are FREE.
Like last month, Intellinet (our corporate sponsor) is providing refreshments and any giveaways. There will also be a number of Sharepoint experts from Intellet on hand to handle "sideline" discussions and to lend their expertise to the presentations.
Wednesday, October 05, 2005
Sunday, September 18, 2005
There is a 24-minute video On "channel 9" that discusses the upcoming Sharepoint 2006 ("v3") release...
Friday, September 16, 2005
Rik asks:
"Keith, do you have a link to the details of SP2 of Sharepoint?"
Certainly!
Mike Fitzmaurice is talking a lot about it on his blog
Maurice Prather is also talking about it on his blog
I also dug up a little more about it to satisfy my own curiousity. Man they have got some COOL stuff coming down the pipe. I wish I was at PDC to attend these talks...
SP2:
- Will support ASP 2.0, but only on WSS. SPS will not support this until v3 next year.
- Apparently there is a new version of SmartPart that allows ASP 2.0 Web Part user controls to be hosted in WSS SP2.
- Not much else being talked about that I have seen except bug fixes in SP2.
SPS/WSS "v3":
- Due after Q2 of 2006.
- Ghosting isn't such a big concern anymore. Why? Because v3 will allow you to use ASP 2.0 Master Pages, and Frontpage 12 will be able to work with it. Sweet!
- You won't be limited to windows integrated authentication anymore. Why? Because v3 will support authentication providers from ASP 2.0! Extranet developers of the world rejoice!
- All sharepoint lists can be exposed via RSS. Also some templates for Blogs and Wikis.
- Huge improvements to Workflow support.
- A document recycle bin.
- Item-level security.
- A new Business Data Catalog - you can define your line of business data and web parts can consume it. Sounds like an enterprise level data dictionary of sorts.
Thursday, September 15, 2005
I am not at PDC, but thanks to the wonders of modern technology I am still able to get the scoop on some of the things being discussed. And there is some really cool things being announced. Things related to Sharepoint.
We can look forward in the near-term future to WSS SP2, which has some cool new features. Primarily, it will support .NET 2.0 web parts! Thats like TOTALLY Awsome! The downside? Portal Server will not support 2.0 until the next major release in 2006. I wish they would reconsider that descision, but in the meantime at least we can use 2.0 with WSS.
Another cool feature coming is the "Slide Library"... you upload a powerpoint slide deck and it breaks it apart into individual slides. You can then incorporate the slides into a new deck, but the slide remains linked to the first (I guess until you extract the deck into a .ppt file). How I WISH we had that feature while building the slide decks for the Sharepoint 1, 2, 3! sessions!!!
There were other cool things mentioned as well, but those two stuck out to me as too cool to forget.
The second installation of the Sharepoint 1, 2, 3! training series is next Monday and Tuesday. This session is aimed squarely at the developer who is interested in "cutting their teeth" in developing code that targets the Sharepoint environment. We will be covering basic Web Part development, debugging, and deployment. We will also be covering things more on the customization side, such as page and template customization. Really cool stuff!
If you attended the first session last month, you will recall that there was very little code to be seen. It was almost exclusively slides. This session will be very much different - we have a healthy number of demos lined up for the Level 200 topics. Just like last month, attendees of the Hands-On Lab will also recieve a DVD containing the training materials loaded on a trial version of Windows Server 2003 (VPC image). This is a really cool take-away that allows you to share what you have learned with your cohorts back in the office. It also makes a great way to demonstrate the power of Sharepoint to that skeptical manager!
Our first session was extremely popular, with fantastic positive comments from across the board. The Hands-On Lab for Tuesday night is already fully-booked, but it you show up with a laptop and are willing to be slightly inconvenienced we most likely will not turn you away (our training room is only designed to hold 20 people, but we had 45 at last month's HOL session).
There is still room to sign up for the seminar on Monday night however. You can get more details and find a registration link on our main website at http://www.sharepoint123.com/. Just like the first session, the coming Sharepoint sessions are FREE.
Like last month, Intellinet (our corporate sponsor) is providing refreshments and any giveaways. There will also be a number of Sharepoint experts from Intellet on hand to handle "sideline" discussions and to lend their expertise to the presentations.
Sunday, September 11, 2005
Ever since Eric Marvets excellent presentation on applied security to our C# user group, I have had a renewed interest in architecture and development of [more] secure systems. So I ran across this interesting article today that I thought I would share...
(Not that it needs any more link-juice, it was slash-dotted)
The Six Dumbest Ideas in Computer Security
The main takeaway points: Secure by default is good, Rewarding those who participate in hacking activities is bad, relying on penetration tests is dumb, and user education is just not working.
White-collar Tae-Bo?
Or was I just being a tad too defensive about some of my code?...

Wednesday, September 07, 2005
I know I have not spoken much about this topic in the past week, definately not on this weblog.
My readers may or may not know that I grew up in a New Orleans suburb. I left in 1992 when I went away to college, and since relocated to Atlanta. But I still have a lot of family there. Let me rephrase that: I still *had* a lot of family there.
To put it briefly,
My mother was on a cruise in Mexico when it hit. Last I heard, her boat dumped everyone off in Galveston and left them to find their own way from there (it originally sailed from New Orleans)... and she was trying to make her way back to her house in Destrehan (about 5 miles west of the flooded airport). Her house is probably fine, but I understand there was a lot of looting and vandalism in that area. Phone calls are nearly impossible so I may not even hear from her for another week or two.
My stepfather evacuated to Baton Rouge but was ejected from the hotel there because he had Chablis (a toy poodle) with him. He then went to Houston, as no other hotels had vacancy prior to that. We are almost certain that his apartment is completely destroyed - it was on Severn Ave in Metarie, in the heart of the flooded region of Jefferson Parish. They also ran out of cash to pay for the hotel, and I believe the Red Cross is helping them now.
My aunt and her two daughters (both in school) are safely in Orlando for a few months at least. They haven't seen their house yet, and there is a good chance either everything they own has taken water damage or been looted. Their home is in central Metarie as well.
I have not heard anything at all about my grandfather or my other aunt who lives in the area. I don't think anyone in my family has heard from them either.
There are other family members and freinds of family who are still unaccounted for. Many or all might be alright, but with the communication and cash problems, it is very hard finding anything out.
One thing that is making it very hard for the evacuees is the loss of banking systems. New Orleans residents are very supportive of local companies, including banks. Most checking accounts are with local establishments such as Whitney Bank, which is effectively out of commission now. Luckily some people had blank checks when they evacuated and are able to open new accounts in their refuge region using that. Not everyone brought their checkbooks or debit cards though.
I have heard a few people speaking out that "the people who didnt evacuate dont deserve help". First of all, if you had ever been to that city you would know that many inner-city residents simply do not own vehicles. They didn't need them, and had no place to park them. They couldn't leave. Not to mention the fact that there were a million residents there... it is nearly impossible to evacuate a million people in just a few days.
I have also heard suggestions that "we shouldn't pay to rebuild that city - it's under sea level". New Orleans is one of the most historic cities in this country, there is invaluable and unreplaceable history there. Plus - we have earthquakes in California, so I guess everyone should move away from there too? And scientists predict that every few hundred years a massive earthquake strikes the tennessee valley, big enough to flatten Atlanta among other cities... I suppose we should all relocate from there too? What about the subcoastal ledge off the Atlantic coast that could collapse any day now and send a 50-foot tsunami through downtown Manhattan? Every city has it's Achille's Heel, it just happens that New Orleans' luck ran out this time.
In the meantime, I get to keep wondering which of my family will get to spend a few months as guests in my home.
Update 9/8:
My mother finally got a call through. She is back home, and amazingly little damage to her house (mostly debris damage). Her car was parked on the 1st floor of a downtown parking garage though, in an area where the water supposedly was up to the second floor... so that's probably a total loss. They won't let anyone into the city itself right now though, so she can't actually check it.
A friend of my aunt checked on her house - and by some miracle it did not take any water nor has it been looted yet. That whole neighborhood was under water according to Google, but apparently this house was on some type of ridge. They won't be able to return for a few months though, and the schools there are closed until next year, so now they will be staying temporarily in Orlando.
It turns out my grandfather and other aunt rode out the storm at home - and their homes made it through as well. I am sure this scared the heck out of them though, and maybe next time they will heed the evacuation warnings.
A few other relatives and friends of family have lost their homes, vehicles, livelyhood, or all of the above. They are all staying with relatives who have taken them in. Everyone is now accounted for though at least, which is good.
My stepfather is the only one we haven't heard from since shortly after the storm hit, but we assume he is out of harms way (most likely still in Houston). We haven't gotten any calls through yet to him, but have no reason to think he isnt doing OK now.
What a mess this situation has turned out to be.
Update 9/10:
Finally heard from my stepfather, he is currently in Baton Rouge and waiting for Jefferson Parish to re-open, but he is OK. His apartment is in bad shape, but he thinks that only the basic furniture was ruined - he managed to get the expensive stuff out or placed above the waterline.
Monday, August 22, 2005
It seems there is a code camp every other week now! I just got back from the Portal "Mini" Code Camp in Charlotte this weekend, and now I see that there are two more coming in the Southeast!
Jacksonville Code Camp on August 27th
and
Charleston Code Camp on September 17th
Both are looking pretty good.
This post is about a week late, as we kicked off the first month of the Sharepoint 1, 2, 3! training series last monday night. Feedback has been overwhelmingly positive. With hardly any promotion (we were too busy working on the material), we still managed to draw about 65 for the seminar and 35 for the Hands-On Lab on tuesday. Early indications are that we will have far more than that at our level 200 and 300 sessions. I think we are already "sold out" on some of the future sessions.
There is LOTS of buzz circulating, which is a great feeling since the four of us (Matt, Brendon, Dan, and myself) have put a tremendous amount of work into it. The Hands-On Lab "experiment" went over especially well... it's not every day that you get to attend free training and take home a DVD with a running Virtual PC of the lab materials!
Intellinet has been an extremely supportive sponsor, and we are already working hard on making the next two months' sessions even better! There are some truly awesome ideas floating around right now centered on the work we are doing with the 1, 2, 3! Training series... so keep your eyes and ears open.
Wednesday, August 10, 2005
I blogged about this new local organization a few weeks ago, and tonight was the first meeting.
I thought this was a really good meeting. It was well-managed, very professional, and lots of great content in a format that is pretty new for me. I thought the "panel" discussion was really neat, not something I have seen attempted in a user group before.
It was quite interesting to view things from a more business-oriented perspective as opposed to just worrying about the nuts and bolts of building systems. I think this is a fundamental growth step for senior developers, there is only so far into "technology expert" that a person can go before running out of room to grow... and moving vertically to systems, integration, and finally enterprise architect is just a natural extension of that growth. And the career backgrounds of the panelists strengthened this view - they all came from a strong developer background.
I see that there is much I can learn from this group. I will definately be going to these meetings in the future.
Wednesday, August 03, 2005
In my previous post, I talked about how to properly design a service. However, I did not give any real examples of it. All talk and no code. In this post, I hope to show how to actually do it.
Example: Hello, World!
Because you can never wear out an old example, and everyone already knows the Software Requirements Specification (SRS) for "Hello, World!".
Contract-First Design
Starting out, we need to first define the contract of the service that will be known as HelloWorldService. While I could demonstrate the purist's SOA approach by starting out with actual XSD schema, I will instead show what 9 out of 10 developers will be more comfortable with - a .NET interface contract.
HelloWorldService is a simple service, it's functionality is comprised of only one operation, "HelloWorld". HelloWorld accepts a single string input: "PersonName". It also returns a single string value: "GreetingText". With these requirements in mind, I will lay out the following interfaces and supporting class types:
namespace HelloWorld.Interface { public class HelloWorldRequest { public string PersonName; } public class HelloWorldResponse { public string GreetingText; } public interface IDocHelloWorldService { // This is the document-centric design method HelloWorldResponse HelloWorld(HelloWorldRequest Request); } public interface IRpcHelloWorldService { // This is the Rpc-centric design method string HelloWorld(string PersonName); } }
All of these definitions are placed in a single assembly, HelloWorld.Interface.dll. This part is important if you decide to provide a Remoting option, as this will function as the shared assembly (the equivalent to COM's type library and WebServices' WSDL).
Define Seperate Endpoints and Implementations
Here is where the rubber hits the road. The guts of the service will live in the Implementation assembly. Actual endpoints will live in their own assemblies, or web projects. I will start out by building the Implementation assembly, named HelloWorld.Implementation.dll, which contains the following code:
namespace HelloWorld.Implementation { using HelloWorld.Interface; public class DocHelloWorld: MarshalByRefObject, IDocHelloWorldService { public HelloWorldResponse HelloWorld(HelloWorldRequest Request) { HelloWorldResponse Response = new HelloWorldResponse(); Response.GreetingText = "Hello, " + Request.PersonName + "!"; return Response; } } public class RpcHelloWorld: MarshalByRefObject, IRpcHelloWorldService { public string HelloWorld(string PersonName) { return "Hello, " + PersonName + "!"; } } }
Notice the difference in the amount of code needed to support each design method. Document-centric can require more code, but the trade-off is for increased control and flexibility.
Now, we can define endpoints.
The simplest "endpoint" is to merely add a direct reference to HelloWorld.Implementation.dll, and use the service classes directly. This will result in an in-process working instance, just like any other .NET object.
The next simplest endpoint is to configure the service as a Remotable object. You might have noticed that I chose to derive my implementation classes from MarshalByRefObject. This decision allows the Remoting system to expose my implementation classes as Remoting objects - objects that run in one process/machine, but are used in another process/machine transparently [almost] to the calling code.
I will not go into details of how to set up Remoting, Ingo Rammer does a MUCH better job than I could ever hope to in his book "Advanced .NET Remoting". In essence, you will need a remoting host (an IIS web application is the easiest), and you will need to add the web.config entries to expose IDocHelloWorld and IRpcHelloWorld as "well-known services". Note that you are exposing the interfaces here, and NOT the implementation objects... an important distinction. Then you simply dump the Interface and Implementation assemblies into the web's bin folder.
On the Remoting client side, you create a similar entry in the application's config file (alternatively, you can make calls in code to Remoting.Configuration to achieve the same effect). The client-side configuration causes .NET to channel requests for the service interface to be forwarded across the network to the target server. In your client application code, you simply use Activator.GetObject(typeof(IDocHelloWorld), "remoting url....") to request the remote instance. The framework takes care of the rest.
Finally, we can define a traditional Web Service endpoint. Since asmx is the simplest way to do this, we will use that technology in this example, although you could alternatively use WSE's non-asmx transport ability. We just create a plain-vanilla Web Service asmx in a web project (named DocHelloWorldWebService), and add a reference to HelloWorld.Interface.dll and HelloWorld.Implementation.dll. We modify the web service code like so:
public class DocHelloWorldWebService : System.Web.Services.WebService, IDocHelloWorld { using HelloWorld.Interface; using HelloWorld.Implementation; /* .... IDE generated stuff .... */ [WebMethod] public HelloWorldResponse HelloWorld(HelloWorldRequest request) { DocHelloWorld = new DocHelloWorld(); return DocHelloWorld(request); } }
We can also provide an RPC-centric version by adding a RpcHelloWorldWebService like this:
public class RpcHelloWorldWebService : System.Web.Services.WebService, IRpcHelloWorld { using HelloWorld.Interface; using HelloWorld.Implementation; /* .... IDE generated stuff .... */ [WebMethod] public string HelloWorld(string personName) { RpcHelloWorld = new RpcHelloWorld(); return RpcHelloWorld(personName); } }
Obviously, you would need to also do a few other things to complete the web service, such as giving a non-default namespace, etc.
Wrap-up
So, there you have it. An example of how to properly design a service in .NET. While not terribly difficult, it certainly is a totally new way of thinking about system design for many people. Hopefully this is of some benefit to you, who knows it might save you from a costly code refactoring when you suddenly have to support a new transport or service endpoint type.
In conclusion, I would also like to point out a few excellent resource books that are relevant to the subject:
"Advanced .NET Remoting", Ingo Rammer "Expert Service-Oriented Architecture in C#", Jeffrey Hasan
Last week I hooked up with a few other smart guys after the Atlanta .NET User Group meeting. We were at the regular post-nerd-meeting hangout - Buffalo Wild Wings on Mansell Road.
We talked about a number of interesting topics, including AJAX/Atlas, Vista, and Indigo. At one point, someone questioned the validity of Remoting in light of WebServices, and wondered why anyone was using it now that is is supposedly on the way out. And my perspective was "why choose at all?". It is perfectly feasible and dare I say it "good practice" to design your system to support both. In fact, if you do things right, you will even be prepared for a smoother migration to Indigo or WSE.
So what is the secret trick to designing a service like this? Simple: it's called "contract-first design". Back in the days of COM, you might have known it as "interface-first".
Contract-First Service Design
The concept is surprisingly simple. A "service", whether it be a Web Service, system Service, or logical in-process service, can be defined as a unit of system functionality that operates independently of other units, and provides a well-known and concise interface. What this means is that no matter how complex a peice of functionality may be, it can be described in terms of some abstract interface. In Service nomenclature, this interface is called the "contract". The "contract" states the individual methods (operations) that a given service implements.
When we talk about Web Services, the "contract" is expressed as a WSDL document. When we talk about Remoting, this contract is expressed as compiled IL in a shared assembly. In COM, the contract was expressed in the Type Library. Indigo's name for this idea is by far the most explicit and clear, the "ServiceContract".
When you define a contract, you are declaring the exact functionality that a service MUST provide, and which a client MAY consume. The Service is not allowed (theoretically) to provide funtionality that exceeds or falls short of that contract, and the Client is not able to request any functionality that falls outside the scope of the contract. Furthermore, the contract also defines the specifics of HOW the functionality is to be addressed... for example, an operation requires a specific set of inputs, and will not respond (or should not) to inputs which are invalid or incomplete.
Therefore, a Service Contract ensures a consistent and predictable interaction between client and service.
So HOW do we go about designing a .NET solution in such a manner?
Plan ahead.
It is far easier to produce an adaptable architecture if you plan ahead for the adaptability. This means thinking about your interface before you think about the implementation.
At a minimum, start with defining your interface(s). You will need to define a seperate interface for each logical service. If you are a SOA purist, then this is where you bust out with the XSD editor and define your messages, operations, and portTypes. If you are not an SOA purist, then this is where you start laying out .NET interface definitions (yes, the language constructs that are defined with the "interface" keyword). Even if you are going the pure-SOA route, you will want to run the xsd.exe compiler against your schema to create some .NET stubs.... then change those from "class" to "interface" definitions. Either way, on the .NET side you want a set of interface definitions for the services, and class definitions for the complex structures.
And here you must make a choice. Do you want to (A) design a completely document-centric service, or (B) an rpc-centric service? If you want document-centric services, then you will want to create explicit types for every operation/method, one for the input and one for the output... even if the content is not complex. If you want RPC-centric services, then you can save a small amount of effort by only defining explicit types for cases where you wish to return or accept complex structures. Design Method A OperationAResponse = {complex type or simple type...} OperationARequest = {complex type or simple type...} OperationA = function(OperationARequest), returns OperationAResponse Design Method B OperationB = function(complex or simple type(s)), returns simple type or void
One word of warning: stay away from "ref" or "out" parameters if you choose to follow Design Method A.
One thing you might notice about Design Method A is that all operations will have a similar pattern, regardless of inputs and outputs. This is not coincidental. The Request and Response structures are what we call "documents" in a document-centric SOA (also called "message-centric"). There is great flexibility and power in a message-centric design.
Define Seperate Endpoints and Implementations
This is what fouls up most attempts at designing a good service. Having the contract pre-defined is not enough - you must also differentiate the service from the consumer. In the real world, your service will almost always be centralized, but the consumer(s) will be dispersed. This means that one (1) service may have multiple (N) endpoints. An endpoint is merely an identifiable address where the implemented service functionality can be found.
The problem is that most people do not distinguish between the endpoint and the implementation. They simple fire up a new asmx file and start dumping code into it. This is a BAD PRACTICE. The asmx is simply and endpoint, and should not be doing any work except passing the calls over to a real implementation. In other words, the asmx should be nothing more than a Facade.
A better approach is to implement the service itself in an external class... better yet, in an external assembly. This implementation class should implement the defined interface, just as you would implement any other .NET interface in a class. Then, you also implement that very same .NET interface in your asmx, however in the asmx you simply forward the calls to an instance of the external implementation class. Your Web Service methods become extremely simple shells that are marked up with the [WebMethod()] attribute and delegate the work to the external class. Very clean and tidy.
Once you have implemented your service like this, many more options become available. You get the flexibility to create new endpoints, possibly with differing authorization abilities (external facing ones might enforce WSE security, while internal ones might not). You also get the ability to very easily expose the service via other transports... such as Remoting. Either create a new endpoint object that derives from MarshalByRefObject, or make the service implementation itself derive from MBRO. Then you can add a entry to an application config file, and your service is now exposed via Remoting, with an identical interface to the web service! And finally, you enable the consumer of your service to simply reference it directly as an assembly, if that is desired for performance or security.
Wrap-up
That wraps it up for this (somewhat basic) discussion of how to design good services. My next post will follow up with a concrete example of this process.
In conclusion, I would also like to point out a few excellent resource books that are relevant to the subject:
"Advanced .NET Remoting", Ingo Rammer "Expert Service-Oriented Architecture in C#", Jeffrey Hasan
Tuesday, August 02, 2005
If you missed this month's c# user group meeting, you definately missed out on some good information.
Chris Wallace started out by showing us the slick new profiling capabilities in VSTS 2005 for a few minutes. This will certainly be a handy set of tools available in VSTS.
Then Eric Marvets gave the main presentation on .NET Encryption. He did not show us a single line of code (there are plenty of examples on the web), but instead he felt it was more important to teach people how and [more importantly] when to apply or not apply particular cryptographic solutions. We all learned how Electronic Code Book ciphers and Chained Block ciphers work, their attack vectors, and in what situations they work best. We learned why when using CBC, you MUST ALWAYS generate a new Initialization Vector whenever the encrypted data is modified, and just exactly how that IV is used to make certain cryptographic solutions more secure. As a final tidbit of wisdom, we learned how DPAPI, while certainly an improvement over clear-text storage, is fundamentally no more secure than a good DACL.
8 out of 10 doctor's agree - The Atlanta C# Users Group lowers cholesterol while reducing hair loss and brightening your smile!*
* These statements have not been evaluated or approved by the FDA.
Sunday, July 31, 2005
Took some time off tonight to (finally) see War of the Worlds.
It started off good, was really building up nicely...
and then it just ended.
The ending was way lame, almost as if they decided they didnt feel like putting in the final effort to complete the script.
Given the pace of the plot and buildup in momentum, they should have just made it a 2.5 or 3 hour film and actually fill in the rest of the plot.
Saturday, July 30, 2005
For the past few months myself and a few other Local Developer Event Activists (hey, I like the sound of that title!) have been secretly working on some interesting new ideas.
Well, the proverbial cat is now out of the bag as we have opened up registration to the Sharepoint 1, 2, 3! series of events. These are a totally new concept in regional developer events. Inspired by the recent popularity of the many "Code Camp" events that have been popping up all over the east coast, we wondered "well, instead of a huge swathe of topics, how about we try delivering very tightly focused training events on hot but neglected subjects?". Well, Sharepoint is definately one of those HOT topics - just ask any recruiter these days, or surf over to Monster.com or ComputerJobs.com. EVERYONE wants to hire Sharepoint experts, but NOBODY is helping developers to learn those skills. Same thing goes for BizTalk, and various other hot technologies.
With these ideas in mind, myself, Matt Ranlett, Dan Attis, and Brendon Schwartz have teamed up and formed the Atlanta MS Professionals User Group. This "User Group" is unlike any other. We plan on providing high-quality training sessions to the community, with a 3-month focus on each technology. By concentrating on specific technology areas over several consecutive months, we feel that a superior level of learning and understanding can be accomplished. And this is how the Sharepoint 1, 2, 3! series came about.
So by now if you are still reading, you probably want to know what this is all about. You want details such as topic coverage, number of events and dates, target audiences, difficulty level, and cost. You might even be wondering how to go about reserving your spot...
- Topic Coverage: Sharepoint from a user's perspective, Installing configuring and deploying, basic portal concepts, site customization, enterprise integration, and webpart development.
- Number of Events: 3 Seminars (Level 100, 200, and 300), and 3 follow-up Hands-On Labs, spread over the course of three months.
- Target Audiences: Primarily web developers who are curious about the whole "sharepoint thing". But also administrators, end users, and IT managers might find value as well from the level 100 session.
- Difficulty Level: We are trying our best to make the difficulty level progressive - this is to encourage individual attendee's growth as the series progresses. The first session is Level 100, and is intended for technically-savvy people who are just getting their feet wet with Sharepoint. Level 200 builds upon the core concepts, and adds Customization and simple Webpart Development among other things. Level 300 goes deeper into complex Webparts, and touches on more advanced issues such as deployment and recovery.
- Cost: FREE! Totally, completely FREE!! We are doing this as an INVESTMENT into the local developer community, hoping to build up a stronger skillbase here.
- How to reserve a place: Please use on of the registration links on the event's website at http://www.sharepoint123.com. PLEASE do not sign up your entire development staff! We have limited space (especially for the HOLs), so be thoughtful of your peers and only register places for folks on your team who are truly interested in learning these skills.
Please refer to the event's website via any of the above hyperlinks for even more details about this fantastic series.
We are really excited to be providing this kind of event to the Atlanta developer community. This is something we had been talking about doing for a very long time - and now we have finally gotten off our tails and put it all together!
Friday, July 29, 2005
I ran into a nice fellow, Burr Sutter from BravePoint, at last monday's .NET User Group meeting. I seems he is forming an Atlanta chapter of the International Association of Software Architects (IASA). This is a platform-agnostic group that is interested in moving this emerging field forward - and they don't care if you are J2EE, .NET, or WebSphere, or any other platform advocate. The basic concepts and issues are the same, and we can all share the many flavors of kool-aid without any name-calling. At least thats the idea...
I for one plan on attending these meetings as often as I can. The kick-off meeting announcement goes something like this:
======================
International Association of Software Architects - IASA announces the opening of the Atlanta Chapter.
IASA Atlanta has an established network of Atlanta's most elite software engineers, executives and architects. Please join us on August 10, 2005 for our first public meeting for a discussion on Enterprise Architecture.
Topic: Enterprise Architecture Speaker: Angela Yochem, Vice President, Portfolio Architecture - SunTrust Banks, Inc. Description: Angela Yochem will talk about the responsibilities, complexities and significant challenges of Enterprise Architecture in today's enterprise. A facilitated panel discussion will follow, featuring some of the industry's notably impactful enterprise architects.
Whether you consider Enterprise Architecture to be an effort, a team, a diagram of systems, a method of governance or otherwise, this event provides an excellent forum for discussion and examination of the field of Enterprise Architecture.
Panelists: Les Phillips, Enterprise Architect - UPS Supply Chain Solutions Jason Chambers, Principal Architect - Delta Air Lines Patrick McClellen, Senior Technical Architect - SunTrust Banks Andrew McSherry, Vice President of Technology Services - Fujitsu
Location: MATRIX Resources 115 Perimeter Center Place, NE Suite 250 Atlanta, GA 30346 Directions: - I-285 Exit 29 Ashford-Dunwoody Road (East of 400) - Pass Perimeter Mall on your left - Turn left at the 4th traffic light onto Perimeter Center West. - The 3rd driveway on right will be marked SOUTH TERRACES and 115 Perimeter
Center Place. - Turn right into the curving driveway and enter parking garage. - Feel free to park in any unmarked space on any floor. Visitor parking is also available on the 2nd level, but is limited to a maximum of 2 hours.
Time: 6:30 to 8:30 PM
Contact: Burr Sutter - burrsutter@gmail.com Phone: 770-714-3292 Website: www.iasarchitects.org
IASA Atlanta is open to all professional software architects regardless of development platform.
Josh pointed out this cool little Blackberry utility to me today: Berry 411. It's always the simple, elegant tools that are the best.
Well yeah, OK. So I admit I am finally getting the hang of the Blackberry interface. I always said I would never get one because they were so awkward. But I guess walking was also pretty awkward too at first.
Wednesday, July 20, 2005
Cool - in the Subscriber Downloads section of MSDN there is now a pre-built VPC of beta 2 Visual Studio, with Team System installed.
It's all trial installs (Server 2003, etc), mostly set to expire in 2006... but it's a very easy way to get some exposure to VS2005 and Team System without spending half a day loading up your own system image.
It's not that small (2.85 G) of a download, but at least you don't have to sit through 6 hours of installation prompts.
Please see the post title for details.
Tuesday, July 19, 2005
Well, I have only been with Intellinet for about 2 weeks now, but already I can tell that this will be a very enjoyable part of my career. The professionalism of everyone here, the positive attitudes, and certainly not least - the high quality of every consultant in the organization... it feels great being a part of that kind of a team.
Before I started, there was the occassional phone call from the recruiter (as well as others inside the organization), and the message was clear - not only was I excited to be joining the company, but the company was also excited that I was coming to join them. That was a great feeling, and one I had not experienced from an employer since... well, never.
And the welcoming attitude definately did not end when I arrived for my first day - a lot of folks seem to make a point to introduce themselves to new hires. Again - this was another first experience for me, having spent the majority of my career until now as an independant contractor.
I was also thrilled to be put out in a client environment literally on day 2 of my employment. Apparently, this is not normal procedure but there just happened to be an immediate need at a client where my particular industry background was of instant value - and I must say, it sure feels good to be useful!
Well, I won't spill any more beans about the hiring process for now - but I would like to point out that Intellinet is still hiring in Atlanta! Now, getting past the technical and personal screenings may not be a pushover, but it is definately worth it. We are building our practice on a solid foundation of talented people, and are most definately interested in bringing in more quality developers, BI specialists, portal specialists, and even infrastructure people. If you are interested, please email me or pull me aside during one of the many Atlanta user group meetings - I would be more than happy to get you in touch with an Intellinet recruiter.
And supposing you do join the team, please remember to write my name down in that little "referred by" section of your application 
Tuesday, July 12, 2005
This question occurred to me today as I sacked through YADAL (yet another data-access layer):
Does anyone else even understand transactional integrity these days?
It used to be that you didn't dare write a bit of code unless it supported at least some rudimentary transactional guarantees. But now it seems that the only transactionally-safe code I ever see "in the wild" anymore is the code I actually put out there. Countless data-access layers, monolithic systems, and even ingenius multi-tiered highly scalable systems.... but none even provide the most basic of consideration to transactions in their architecture.
I see tremendous effort made to encapsulate and abstract away the details of database access... O/R mappers, hand-rolled business classes, custom "code blowers", point-n-clicked typed datasets, pretty much everything under the sun. But pretty much never any love for SqlTransaction.
Come to think of it - this isn't a .NET problem either. I noticed the dreadful lack of transaction support even prior to .NET when I was a Delphi code jockey.
Perhaps nobody else builds applications that need to write to more than one table in a logical work unit? Nah, can't be.
Just please if you happen to run across this weblog one day and reading this,... please find out how (and why) you might need to be using transactions in your application architectures. I would like to one day encounter a custom developed application (other than my own) that actually implements transactions.
And on the other hand, hopefully you don't go to the other extreme and start peppering transaction locks all over your code "just in case"... cuz that can be an even worse situation...
Thanks, getting off the soapbox now...
Sunday, July 10, 2005
If so, then you try your best to make it to the FREE Portal Development mini- Code Camp in Charlotte on August 20th.
If you were in Atlanta for the May Code Camp, you might remember Maxim Karpov [you might even have been one of the many who wrote "Maxim ROCKS" in your event survey comments]. Well, Maxim is the host for this mini- Code Camp, and on his agenda are sessions for Portal Design Patterns, Sharepoint, DotNetNuke, and ASP.NET 2.0 Portal Frameworks.
This should be a pretty good event to attend if your schedule is open, and I highly encourage everyone to attend.
Attendance IS limited, so it would be a good idea to register now and reserve your place!!
Saturday, July 09, 2005
When my last cellphone died I bought a new smartphone from AT&T Wireless. I paid quite a bit for this phone, and it has worked well enough (awful reception at my home, but reasonable elsewhere). Even since Cingular acquired ATTW, I have never had any billing problems with them before... it is usually roughly $54 a month.
This week I recieved my bill for last month. It was for $257!! It seems that because the Microsoft recruiter was calling me from a land line (as opposed to a mobile line), Cingular counted every minute of those calls last month (over 400 minutes of it) as "overage", and billed me for it at $0.45 a minute.
First of all, I am almost certain that I would never have agreed to $0.45 per minute unless the carrier's policy was to allow a plan with higher limits to be applied retroactively (which is something Cingular will not do). I also do not recall signing a 3 year contract - only a 1 year contract, however I do not have paperwork to back this up so I am now at the mercy of their contract termination fee ($175 by itself). I feel like I am being robbed in broad daylight.
I am also pretty miffed that being recruited by Microsoft ended up costing me a few hundred dollars out of my own pocket.
Friday, June 24, 2005
As you can tell from my last post, I have been on the recieving end of quite a few interviews lately. But on the flip side, I have also been performing just as many interviews myself on behalf of AfterHours.
So when did I miss the big shallowing of the talent pool?
The last time I helped an employer with interviewing, there was a certain quality bar that everyone recognized. People with skills below that bar were not submitted. People above the bar were submitted for consideration - and almost always at an hourly rate that was in line with their experience level (we are talking contractors here).
This time however, I continue to be surprised - nay, astounded - at the audacity of recruiters that have been submitting resumes to us for consideration. Easily four out five have been so incredibly overinflated that once it gets to a real interview, the candidate cannot support their own resume claims. For example, I interviewed a person only a few days ago that claimed to be a "senior .NET developer" and "proficient with SQL Server". Yet this person was unable to answer correctly a single basic technical question in either subject area. I wish this were the exception, but it is seemingly the norm. I am sorry, but when a contractor is presented as "senior" with a billing rate approaching $100/hour, they had damn well be able to stand up to a basic technical interview.
I won't even talk about the cases (yes, plural) where the person being interviewed was obviously not even the same person described on the resume itself...
Now granted not all submissions have been so bad. Most from Circle Consulting and Project Solutions have been relatively solid (or at least acceptable).
Recruiters: you need to get your act together. I think you need to pass the same certifications that we (developers, architects, etc) need to pass. You need to understand the technologies so that you can adequately screen these people out before their resumes make it to us (and piss us off enough to never call on you again). I mean, isn't that YOUR JOB??
Job Seekers: Stop lying on your resumes. Dishonesty on a resume is the BEST way to ensure that you will be passed up by an employer. You might be able to bullshit your way past the recruiter's screening process, but you aren't going to make it any further than that, and you definately will not survive long once your new employer discovers that you really don't posess the skills they asked for.
OK, I have blown off enough steam for now. I know it won't make one iota of a difference, but it at least makes me feel better to shout into the \dev\null abyss...
Wednesday, June 22, 2005
You may have noticed that I have not posted anything new in approximately 3 or 4 weeks (and somewhat sparse in the couple of weeks prior to that). No, I have not grown tired of blogging (not by a long shot) - I have simply been exceptionally busy lately.
Busy with what you may ask?
Well, over the last few months I have endured what can best be described as a barrage of technical and personal interviews with various consulting firms. Most notably, about twelve interviews from Microsoft groups (MCS), most of which I suspect were designed to "break my spirit". I even flew out to Phoenix and Seattle at one point. I will give this one bit of advice to anyone currently in the MCS interview process (or considering it): Do your homework. They will expect you to know their vocabulary for project roles and stages... especially the MSF Team Model. It would be very beneficial to know beforehand the differences between Program, Project, and Product managers. And also - many interviewers will purposely drill as deeply into a subject as necessary to find your limits. This means that you will not get every question right... just be honest about what you do and do not know (self-assessment is very important, and they compare this to their own assessment).
In the end, I decided that at least for now Microsoft is not the best place for me to continue building my consulting career. I chose instead to accept an offer from Intellinet, a consulting firm based here in Atlanta. This allows me to remain in the Atlanta area, where I can continue to be very active in the user community (which I enjoy greatly). The people I have met at Intellinet seem to be very honest, personable, and technically skilled. I have no doubt that I will enjoy working with them in this next stage of my career.
Lastly, if anyone is interested in joining (as either an FTE or contract senior developer, working with .NET 2.0 and possibly SQL 2005) a great group of developers, DBA's, and analysts I would definately recommend my former employer. They were a very enjoyable group to work with.
Thursday, May 26, 2005
Over two weeks ago I bought a new HP Z552 media center system and a Linksys WMCE54AG Media Center Extender. I had such high hopes. I was going to be able to record my favorite shows for playback on my own schedule. I was going to centralize my digital photos and videos. I was looking forward to being able to play back any of this either on my main TV (rear-projection unit), or on my bedroom TV. I figured that by paying a premium price for the OEM'd system (over $1800 for both MCE and the extender), I would ensure a positive and hassle-free experience with MCE.
Today I am dismantling the whole thing and taking it back.
Here's why:
- The "IR Blaster" sucks with changing channels on my cable set-top box. Half the time it does not work at all, and often attempting to change the channel will trigger the set-top box to enter "program guide" mode, where it is impossible to change channels (without pressing the "exit" button on the original cable remote). This is certainly a nuisance when watching TV in the main room, but it is downright unacceptable when it happens while using the Extender (I have to walk down to my TV room in the basement to press that "exit" button before regaining control).
- Wireless is Useless. The Extender unit has integrated wireless, as does the MCE system itself. Installation manual recommends against connecting both to a WiFi access point (due to double hops). However, the Extender simply would not associate with the MCE if I attach the Extender to my access point while the MCE is directly attached via wired Ethernet. The only way to get the Extender functioning is to enable "access point mode" on the MCE system itself, so that Over-The-Air traffic goes directly from MCE to Extender. The catch here is that while the wireless connection is in Access Point Mode, the wired ethernet connection fails to operate, preventing access to/from any other networked computers including the internet (so the program schedule etc will not download).
- The tuner configuration is a nightmare. I have Comcast cable with a Motorola set-top box that is used rather widespread among their customers. Yet the MCE tuner configuration could not recognize it. My only two options were to guess the model number (it's not printed anywheres on the set-top box) from a list of about 20 Motorola devices, or to "train" the MCE to understand the IR codes used by that remote. It takes forever to get this configured correctly, and setting up more than one tuner is incrementally more difficult.
- The MCE system is nowhere near silent. HP chose to not use silent fans in the housing, and they also chose to not provide sufficient dampening on the hard drive.
- The MCE system is rather slow. I expected more performance out of a machine with these specs. It's really not much faster than my 3 year old laptop. I suspect the hard drive is a very cheap unit, and this impacts performance the most.
- The Extender is not very stable. While the video quality is good most of the time, it encounters "network congestion" often enough to be annoying (once an hour or so). There is nothing else attached to the network that connects the MCE to the Extender, so this must be related to some other issue. The Extender also has a habit of freezing up for as long as a minute at a time for no apparent reason... which is especially annoying if you are attempting to channel surf.
- Which brings up another problem - channel surfing is nearly impossible with the instability of the IR Blaster link. Changing channels quickly (quicker than once every 15 seconds) is a sure way to get the cable box to go into that dreaded guide mode.
Basically, the MCE platform has a lot of promise, that's for sure. I will almost definately try to return to it once these issues are addressed in future versions, but for now I just do not have the patience for these kinds of problems. Perhaps if the hardware did not cost me nearly $2000 I would be a little more forgiving - but for now I am going back to a primitive non-digital entertainment architecture.
And to be fair, my experience is due moreso to the abysmally poor products from Linksys and HP than to the core MCE operating system. But in order to achieve an adequate "wife acceptance factor" in my home, the MCE unit MUST look like it belongs next to a television... and very few vendors offer a system in that form factor (as opposed to the standard tower/desktop PC form factor). So for now, as far as I am concerned, this hardware is fairly representative of all MCE systems, since it's the only one I would accept in my living room.
Friday, May 13, 2005
Publisher: Sams Publishing
Author(s): Scott Woodgate, Stephen Mohr, Brian Loesgen, et al.
Categories: .NET, EAI, Web Services, BPEL
Published: 2004
ISBN: 0-672-32598-5
Online Order Links: Amazon, BN.Com, Buy.Com
Summary:
BizTalk Server 2004 Unleashed is a deep exploration into Microsoft's flagship orchestration and integration product.
This book covers a lot of ground. In 680 pages it covers everything from the basics of building schemas and maps all the way up to Business Activity Services and Human Workflow Services. In between, it spends time on Pipelines, Orchestrations, Adapters, the Business Rule Engine, and even Single Sign-On. For the developer, it goes into detail on debugging as well as the creation of all BizTalk elements. For the Architect, it outlines the various messaging and orchestration patterns, and how they are normally handled in a BizTalk implementation. For the Administrator, it explains deployment as well as ongoing monitoring, instrumentation and management. It takes an especially deep look at scaling up/out of BizTalk deployments at all four tiers of the product's architecture.
In all, this book does a good job of dealing with the details of BizTalk development and administration. It caters to those who already have a grasp of the product, definately not a beginner's book. In fact, even for those familiar with BizTalk, the chapters on HWS, BAS, and BAM might be a little too difficult. One thing the book does an outstanding job of is describing the scale-out strategies available in large deployment situations.
This book is most useful to:
- Messaging Architects
- Messaging Developers
- Messaging Administrators
Recommendation:
4 out of 5 stars
I am holding back on a 5-star rating on this one. While it does a great job at handling the details, and leaves no stone unturned in many areas, the treatment of the advanced services such as BAS, BAM, HWS, and HAT is a bit too dry - even for a reader like myself who normally can make it through such material. Unless you are actually using these features in your day-to-day work, these chapters will likely not make much sense. They come off more as a "user manual" than as a reference-class book. In other words, lots of "how" and "when", but rarely does it answer the more important question of "why".
The remainder (and bulk) of the book however is top-notch. And since it is effectively the only book available today for BizTalk 2004, it would not be right to give this one any less than a 4 out of 5.
Fantastic!
Microsoft finally remembered that the majority of their MSDN subscribers are not huge enterprise customers, but rather the smaller one to five developer teams that permeate the industry.
In response to heavy feedback, they are introducing a five-seat version of Team Foundation Server with the version of MSDN that replaces Universal.
In less than 24 hours the festivities will begin.
Towards the end of the day, my presentation will be a deep look into asynchronous programming, with particular emphasis on multithreading. This is more or less the same presentation I gave a few months ago to the C# User Group, but with information about the new Semaphore support in 2.0 (with a corresponding example project).
The other major difference is that with the C# UG version of this presentation, it took me an hour and 20 minutes to cover it... moving through it all very quickly. However at Code Camp, we are limited to under an hour! More slides, more demos, and less time to do it!
I am also posting the Slide Deck and Sample Code here, for anyone who misses the presentation or that just wants to see what the session is covering before deciding which one they want to attend.
Friday, May 06, 2005
Picture this:
Scenario 1 - You are a consultant. You write software for various clients, often remotely. Your clients pay you a lot of money, and you keep them very happy with the exceptional work you perform for them. Because you are a meticulous developer, and understand the value of versioning, you have been using Visual Sourcesafe for 6 years to store every code revision you have ever made for your clients. You also keep every one of your important emails for the last 10 years. Your Outlook .pst file contains every significant conversation you have ever had with your clients - and it also contains personal knowledge such as your complete contacts list and website registration confirmations for dozens of sites, including your 401K portfolio on Ameritrade.
Scenario 2 - You know nothing about code. You drive trucks for a living. However, you DO like to have gadgets and gizmos, and you really love your new Media Center Edition machine. In fact - it's so great that you have digitized ALL of your CD collection and even bought a portable media center for while out on the road. At this point you have over 5 gigs of music digitized, as well as the last season of stargate and family guy to watch as you have time. You never use your CDs anymore, and honestly have no clue where many of them are - since many have been "loaned" or misplaced.
Both of these fictional situations is missing something extremely important. Even though your digitized data is extremely valuable to you, and difficult if not impossible to recreate, you have no backup and recovery strategy!
How to correct this oversight?
There are several options. You could always purchase a simple external drive or tape system and perform regular backups. This is fairly easy, but is really only slightly better than having no backup at all... your backups are still in the same location as the protected systems. A house fire (not as uncommon as you might think) would wipe you out. If you are a consultant supporting a client with deep pockets (who would be forced to sue for negligence if you lost their source code), you cannot afford such a risk.
A better solution is off-site backup services. With off-site services, your valuable data is stored in a remote facility (usually encrypted). For a monthly fee, you can configure your systems to regulary upload changes. Fees tend to be quite small - especially for the individual consumer who often only needs a few Gig of storage. Setup and maintenance also tend to be fairly simple - about on par with traditional tape or disk based backup systems.
I have recently been evaluating two vendors in this space: NetCentric Solutions and Storage Guardian. NetCentric's offering is very easy to install and configure, but has fewer features and a slightly higher price tag. Storage Guardian's offering on the other hand is more difficult to install and configure (due to being more complex) but is much more flexible in deployment.
NetCentric supports File-system backups only, and is quite simple to get running. They also have a nice feature that allows you to access your backup sets from any internet location, essentially using your backup set as a file-sharing mechanism. The NetCentric product costs about $40 a month for up to 5G of compressed data.
Storage Guardian is a more "network aware" product. Rather than a simple single-install program like NetCentric, this product follows a client/server design, with a server process that performs the actual backups (oddly called "ds-client") and a client program that performs set management and inspection (called "ds-user"). This product has the ability to perform direct backups of SQL Server and Exchange databases, as well as NT/2K/XP/2K3 System State, permissions and registries. The installation is slightly complicated, and it is recommended that the installation guide actually be read carefully prior to attempted install. The Storage Guardian product costs about $30 a month for up to 10G of compressed data.
I ended up going with the Storage Guardian product for my personal needs. I really liked the ability to directly back up my Exchange and SQL databases. If you don't need those two things however, the NetCentric solution may be a better fit - since it's considerably easier to configure. My current volume needs are about 5G, so the Storage Guardian solution also allows me a little more room to grow.
In the end, $30 a month for peace of mind is a great bargain.
Sunday, May 01, 2005
Publisher: Barnes & Noble, Inc.
Author(s): Stanley D. Frank
Categories: Personal Improvement
Published: 1990
ISBN: 1-56619-402-4
Online Order Links: Amazon, BN.Com, Buy.Com
Summary:
Speed Reading is a no-nonsense educational trip that sets out to teach the reader how to vastly improve their reading speed and comprehension.
I normally would not pick up a book of this nature. I always thought my reading speed was adequate, and the claims made by the author seemed pretty far-fetched. However, I have been having trouble keeping up with the level of reading I feel is necessary to keep ahead in my industry (about 2 major IT books a month seems about what is needed). I figured it couldn't hurt, so I gave this one a shot.
While I was extremely skeptical of the author's claims, I must say that I am now a true believer. In the second chapter, you go through a "baseline" test to establish your starting speed. I came in right at 300 words per minute, which is actually slightly above the average person's speed of 250 WPM. The author's first claim was that your speed will increase by 50% by simply incorporating the first set of reading techniques that he presents. This first set of techniques is referred to as "linear subvocal", a method of reading that overall tops out at 900 WPM or so. After being introduced to these first techniques, my speed jumped instantly to 550 WPM!! That was with absolutely NO practice... a dead-on 50% improvement.... amazing.
But it gets even better. After introducing the linear subvocal techniques, the author then moves on to explain the more advanced "layering" methods. These are essentially a way to better organize your reading time, and then apply a turbocharged reading pattern where your mind is actually able to comprehend groups of words at once - instead of relying on the steady verbalized stream that most of us are used to.
After learning the faster layering techniques, and then applying them to the remainder of the book (which covers note-taking, test-taking, and essay-writing skills), I went back and revisited the original test where I scored 300 WPM. I was quite amazed to find that this time my reading speed was right at 1400 WPM. Wow.
The remainder of the book is focused on the high school or college student, so it was not of much use to me, except as practicing fodder for my newfound skills. The note-taking techniques could come in handy though during heavy instructor-led training, or while pulling together research for presentations.
This book is most useful to:
- Anyone who is having a tough time keeping up with the reading they would like to be doing
- Students
- Educators
Recommendation:
5 out of 5 stars
This book delivers on it's promises of a minimal 50% improvement in reading speed along with greater comprehension through increased mental focus. The book is also very short - only 200 pages in total. But don't be fooled, those 200 pages are packed solid with incredibly useful techniques and tips.
Another huge plus - this book is phenomenally cheap. I paid only $3.00 from the "used and new" alternate sellers on BN.Com. The shipping costed more than the book.
The only downside to these methods is that they do not translate all too well to online reading. Well - I suppose it could be done - but there will be an awful lot of finger smudges on the screen afterwards!
Tuesday, April 26, 2005
Publisher: Apress (via Friends of Ed)
Author(s): Owen Briggs, Steven Champeon, Eric Costello, Matt Patterson
Categories: Web Design
Published: 2004
ISBN: 1-59059-231-X
Online Order Links: Amazon, BN.Com, Buy.Com
Summary:
Cascading Style Sheets is targetted at the web designer / developer who is looking to break the chains that bind them to old "browser hacks" and to the experienced designers who want to simply take their web presentation designs up to the next level.
The book is very down-to-earth and begins by discussing the history of web browsers, and explains why we have the wide range of presentation behaviors (aka, quirks) that we see today across the various platforms. It discusses important concepts such as document semantics, typography, layout, and application of visual styling. These concepts will seem elementary to anyone who has had a formal education in Art Design or Publishing, but the vast majority of web designers and developers are lacking in such a background - and should derive great value from the material.
After explaining CSS's role in the web, the book then dives in to cover the gritty details. A very good explanation of class selectors is followed by discussions on Typography Control, the Box Model, Relative Sizing, and Layouts. Attention is given to various flaws in the different browsers that must be considered in the CSS design, and in nearly all cases, workarounds are presented in order to deal with the flaws. Finally, the book covers a nice set of "example" sites, and how to go about designing the layout and CSS for them. Some of the example sites are fairly simple, but the last few are indeed quite complex visually. It is also worth noting that all example markup is presented as XHTML.
Some immediately useful information that this books covers clearly and concisely:
- How to center using CSS.
- How to plan and organize CSS styles into linked stylesheets to make maintenance easier.
- What "float" and "clear" do, and how to use them.
- The difference between "inline" and "block" elements.
- How to use the Box Model effectively.
- How to use relative sizing of text to make global changes much simpler.
- How to effectively use CSS selectors.
- How to structure content so that it will "degrade gracefully" on downlevel browsers.
This book is most useful to:
- Web Designers / Developers who still (mis)use the TABLE tag to control layout or the FONT tag to control typography.
- Web Designers that wish to make their layouts more accessible to readers.
- Web Designers that wish to make their layouts appear correctly in modern browsers as well as downlevel browsers.
- Anyone that simply wishes to learn more about CSS and how to properly implement it.
Recommendation:
5 out of 5 stars
If you are using TABLE tags for positioning/centering, transparent GIFS to occupy whitespace, or the FONT tag for typography, then you NEED this book - ESPECIALLY if you build web sites or applications in your day-to-day employment.
The concepts covered will do wonders for your website design skills - you will wonder how you ever managed to get a site layout done before!
At last night's Atlanta .NET User Group meeting, Alan Griver showed us the new Refactoring tool that is free for VB.NET 2005.
In a nutshell - this tool is amazing!
And the first question posed was "how do we get this in c#?"
It turns out that if all you need is VB.NET 2005, you can use the free version. But there is also a "pro" version for $99. This pro version supports C# as well as VB, but not only that - it supports both languages in all versions of Visual Studio!
PLUS, there is a 30-day free trial available for this pro version. After downloading it and playing around for less than 5 minutes I can safely say this tool is a MUST HAVE for anyone involved in writing code!
You can find out more about the Pro version at this URL:
http://www.devexpress.com/Products/NET/Refactor/
And you can find the trial installation download at this URL:
http://www.devexpress.com/Downloads/NET/Refactor/
Friday, April 22, 2005
I do a fair amount of reading these days... averaging about one to two books per month ("computer" books). Most of the time, I actually do read them... I don't just skim through. I have gotten through a number of books in the past two years, including but not limited to:
- Introducing ASP.NET 2.0
- Crystal Reports for Visual Studio .NET
- Advanced .NET Remoting
- Service-Oriented Architecture in C#
- Professional SQL Server Reporting Services
- The Rational Guide to SQL Server Reporting Services
- UML with Visual Studio .NET
- Expert C# Business Objects
- Inside C#
- Writing Secure Code 2nd Edition
- Pragmatic ADO.NET
- Design Patterns (GoF)
- + a half dozen MSPRESS books on ASP.NET, Windows Forms, etc while studying for MCSD tests
I also read through about a half dozen "liesure reading" books, mostly science fiction.
So I am going to start blogging a short review of books as I finish them. I will tag all of these entries with the RSS Category of "Book Review" to ease later searching (or ignoring, I suppose).
Sunday, April 17, 2005
This is sorta cool... CellTrack, a Smartphone app that pings back a server regularly to update your nearest cell tower data... effectively tracking your movement from tower to tower.
They hope to start collecting GPS data as well, and couple that with the "timing advance" data (roughly determines the round-trip time of your OTA connection) to triangulate cell tower positions.
It's pretty cool, runs on Audiovox SMT5600 phones (what I have), and is open-source should you feel like tinkering.
Right now there is not a whole lot of features, but some of the applications could be automatically turning on call-forwarding when you arrive at work or home, etc. Currently, there at least is a dynamic image generator that outputs your last 4 position/tower changes:

This really shows how bloody awful my cell coverage is here (drops signal every few minutes).
It does use GPRS to transmit updates though... Hopefully it doesnt kill my data plan limits (I rarely use the data plan from my phone anyways - too slowwww).
Saturday, April 16, 2005
Seems to be the "cool" thing to do right now, so here is how my profile came out:
Your Linguistic Profile: |
| 60% General American English |
| 25% Dixie |
| 10% Upper Midwestern |
| 5% Yankee |
| 0% Midwestern |
A couple things they left out:
How do you pronounce the word "river"?
- "ree-vur"
- "ri-vah"
- "ri-vur"
How do you pronounce the word "picture"?
- Exactly as it is spelled.
- The same as "pitcher".
- The same as "pitcha".
Which do you tend to say more often"
- "Eh?"
- "Huh?"
- I do not say either word very often.
In a normal conversation, how would you refer to a Nissan XTerra vehicle?
- A "truck".
- An "SUV".
- A "rice-burner".
- Just a "Nissan XTerra".
How about a Ford F-150 Pickup?
- A "truck".
- A "Pickup".
- A "Pick-Em-Up".
- A "Ford".
- Just a "Ford F-150".
Thursday, April 14, 2005
Today we got the word from our "man inside", Doug Turnure, that the arrangements have now been made to have the CLR Team deliver some in-depth talks to our user group on Monday, May 2nd. (That's under 3 weeks away for the procrastinators out there!)
Brad Abrams, Kit George, and Claudio Caldato will talk about CLR Internals for about 45 minutes or so, then after a short break they will cover CLR Performance. At the end of the presentations there will be time for Q&A, so be sure to bring your questions!
This will be a fantastic chance to pick the brains of some very sharp people who not only know an awful lot about the CLR - but that actually helped to design and build it.
So send your pets to a boarding house, put your spouse on a plane to visit his/her parents, and make sure to block out Monday, May 2nd on your calendar for this awesome night of complete .NET geekness!
Monday, April 11, 2005
I can't decide which to do. PDC 2005 or Tech-Ed 2005. Both will be well worth attending, but it's hard justifying both (from a cost perspective as well as time).
I suspect PDC will have more "practical" coverage of Framework 2.0, since it will be after the release (fingers crossed). At best, any information picked up at TechEd will be based on Beta 2. However, TechEd is much sooner, and to honest I can use a vacation (even if I spend it at a conference).
But I don't want to learn just about the framework. I also want solid exposure to SQL 2005, Biztalk, Indigo, and the other peices that are important to me (no - avalon is not all that important to me at this point).
I am mostly interested in Architecture (SO and Application) and Advanced Developer topics. I am looking for sessions weighted towards those topics.
Given a choice, which would you choose? And why?
Just in case you might be reading this blog, and didn't already know, next month a few folks from the .NET CLR Team will be the center of attention at the Atlanta C# User Group meeting!
Brad Abrams and krewe will enlighten us with answers to those burning questions like "When is it going to really ship?" and "So, when do you think it will ship?".
There is always some guy that skips the really good user group meetings (usually to watch some mindless sitcom episode that happens to be playing at the time...), and inevitably he regrets it. He ends up hearing from his buddies again and again about how cool the event was, and that it's too bad he missed out. Don't be that guy.
This will be a great meeting - probably our best to date. Even Bill Gates will be here to talk about the impact of the CLR on our industry.
OK, maybe Bill won't be here. But the CLR team will be - and I would rather hear them anyways.
Monday, April 04, 2005
First of all, thank you to everyone who came out tonight to the C# User Group meeting in Atlanta. Paul and I are very pleased with how this group continues to grow.
I am posting the slides and source code from my presentation ".NET Async Programming Demystified" here for download.
This is essentially the same presentation I intent to deliver to the .NET Code Camp next month, although I will need to strip out about a quarter of the slides to keep myself within the alloted time budgets there. I chose to present it to the C# group first, since a large number of our attendees were not able to register for the Code Camp (due to it selling out in only 5 days).
I did make two corrections to my material before posting the slides:
- I incorrectly stated that each AppDomain has it's own thread pool. This should have been "each Process has it's own thread pool".
- I forgot to include the third type of Timer object - the System.Timers.Timer. Chalk that one up to lack of sleep, I simply forgot to include it in my outline.
Both of these corrections are reflected in the downloadable files.
Tomorrow night I have a presentation to make for the local C# group. So today, I was touching up the slide deck for it.
And without thinking, I noticed a few extra files cluttering my desktop.
Not being the kind of person that keeps a cluttered desktop, I quickly selected the extra items and deleted. And since I find it so annoying to have to go clear my Recycle Bin all the time, I used "shift-delete" to really nuke em good.
Then it dawned on me.
One of those files was my powerpoint deck for tomorrow. And no, no backup of it anywheres.
Luckily, I found a free delete recovery tool on the internet. Unluckily, the simple act of downloading said tool to my hard disk actually overwrote a few of the sectors where my deleted file once resided. I was able to recover it - but powerpoint could not read it since it was mangled with bits of my IE cache.
After trying everything I could think of (even commercial recovery tools), I eventually was able to get powerpoint to open it up so that I could at least read about 75% of the text. Formatting, images, and anything else was lost to the ether, and there were about 200 extra slides of gibberish... but I could at least see what I had typed previously (or most of it).
So, 4 hours of transcribing later, I have a presentation on my hands again. What sucks though is that its now 2am and I have to be up in like 4 hours to make it to work on time...
Saturday, April 02, 2005
There goes daylight savings time screwin up my RSS reader with double posts on nearly every feed!
Then go vote on this bug report. Right now, in Visual Studio 2005, you can easily create a chain of hierarchical masters (child->master->master). This works great, however you cannot edit the child page in the designer in this situation. You can only edit the child page if there is only one level of master above it.
It should be obvious that anything beyond the simplest of website applications will need more than one level of master page linking. But as it stands now, we won't be able to edit the pages in the WYSIWYG editor... all html will have to be edited by hand.
Michael proposes that they not even try to show the master/master/etc content around the child container (like they do in the simple scenario that works). He is simply asking that they allow us to edit the child page in the designer - even if the inherited masterpage content is not visible.
So go vote on that bug!
Thursday, March 31, 2005
I have used CSS for years now, but I never knew about this. Sure, it's sort of implied by the documentation, but I have never seen anyone come out and say "hey, this is how you organize it". So here is what I learned this weekend.
1. You can define specific hierarchies of nested tags to apply a style to. For example "DIV.outerdiv DIV.innerdiv {color:red;}" will set the font color of a div with a class attribute of "innerdiv" to red, but only if it is contained within another div with a class of "outerdiv". Thats super handy for complex layouts.
2. You can define a style more than once. The styles are then merged at runtime in the order which they are encountered (last writer of a style property wins). This means that you can seperate layout CSS from colors CSS and from text, or whatever. You can have a "colors.css" file that only contains color definitions, making it MUCH easier to update later. Super SUPER handy!
3. You can assign styles based on element IDs, not just Classes. Everyone using CSS knows you can use a style selector of ".somestyle" to apply a style to all elements with a class= "somestyle"... but most don't know that you can use a selector of "#element_id" to apply the style only to the element with id= "element_id". This is SUPERB for layout style properties. Generally, the colors/text/etc styles are used on many elements in a page, which is easily done using class="somestyle". But id values are supposed to be unique in a page, and they are all at different positions, with different layout rules (even though they share the same color/font/etc). Assigning layout style properties based on element id and other properties based on class allows you to have your cake and eat it too!
These are very simple concepts to pick up, but they have done wonders for my web design/layout abilities.
And I guess I should also give the disclaimer that I didn't know these things until I customized my dasBlog theme, and saw how it's CSS was designed. Very impressive work there.
Sunday, March 27, 2005
Michael Earls is the man.
This afternoon I asked him a simple question: How do I get Master Pages type functionality without upgrading to Fx2.0 beta?
I am building a small administration application for a client, and I am tired of using "copy & paste templates" or "UserControl chunks" to build a reusable/consistent site design. I know he has done this type of thing a few times in the past, which is why I asked him.
He gave me some very concise and (most importantly) correct insights into the ASP.NET rendering engine, and where to place hooks to do what I wanted. He gave me just enough information to get it working, without giving me too much. The essentials: override the AddParsedSubobjects() method in a server control to re-parent the child page's contents to a placeholder.
While there are a few tricks and snags to overcome, that is essentially exactly what I had to do. I created a new server control, changed it to inherit from Web.UI.Page, instantiated LiteralControls for my static content, as well as a number of server controls that I needed in my base class (for example, the Coalesys PanelBar for navigation) in the new class's constructor. I did some footwork in the AddParsedSubobjects() method to relocate the child page's Form contents into a new HtmlForm that I maintain within my new class. I also had to copy the properties of the child form (enctype, name, method, etc)... so that should the child page developer decide to change any of it, their changes would carry over.
I did do a few things my own way. One of the ideas Michael gave me was to use regular expressions to construct the master page's LiteralControls (he used string constants for each Literal, which I am sure was probably a bit tedious when a change needed to be made). So instead of that approach, I added some well-known comment tags to my master page's source to demarcate the literal sections. I then used my NVEdit tool to store the entire master page as a single template resource. A simple regular expression was used to extract out all the literal sections (this was not hard at all since I used well-known comments to mark the sections). As a result, I can modify the master page layout without too much trouble (yes, it still requires a recompile). Perhaps a future exercise could be to make it fully dynamic, with the ability to use multiple master layouts on the fly. Hmm.
Anyways, the other features I added was a simple way to link external CSS (a new AddStylesheetReference(string url) method), as well as the obligatory Title property that alters the header tag appropriately. A side bonus is that the AddParsedSubobjects code is smart enough to read in existing Title and linked stylesheets from the child pages, and automatically set them with no developer code required. I will likely also extend this mechanism to support themes via CSS at a later time too. That would work nicely along with dynamic master page sourcing...
So I am now very happy. I effectively have master pages development in VS 2003. I don't have the ability to see the master while editing a child page in the designer, but I don't really care about that little bit. I can still link my child page to the site's CSS and get the right "look and feel". This is great.
Thanks again Michael!
As much as I like to gripe about AS/400's and mainframes, I gotta hand it to them. There are just some business-level tasks that a dumbed-down interface such as a 3270 or 5250 terminal provides.
It's really a grounding lesson in worker efficiency to watch a factory line worker scanning barcodes into a terminal every couple seconds, or punching the keys to enter an order - faster than you can even read the screen contents. I have never seen a web application capable of approaching that kind of worker efficiency.
Maybe this whole "rich design" craze will fade away... much like the idea of always-connected "client/server" database systems. Sometimes while I am busy building a "swiss army knife" website (is there *any* other kind that management ever asks for?), I just sit back and wonder what people will think of us in 20 years.
Will they think "man, those web applications are super-efficient"?
Or will they think "what a hunk of manure"?
My money is on the latter. There is a lot to be said for thinking through your actual processes and requirements before sitting down and banging out code. People need to start thinking about what they really need and why before jumping into development.
And choosing "web" applications over other forms as a default is crazy. The design should start simple (dumb terminal level), and then graduate to complex (windows forms), and finally to distributed (web). These are all increasing flexibility/coolness, but also greatly increasing development effort. Interestingly, they are all decreasingly efficient in terms of worker productivity when applied to real-world business processes.
Web apps belong on 1) the internet, and 2) intranet collaboration. 99% of the time they have no place in back-end businesses. It boggles me as to why people keep trying to fit this square peg in a hole it was not intended to fill.
Thursday, March 24, 2005
You may or may not have noticed, my server was offline for most of today. My ISP decided to reassign my IP address, and I was left to figure it out on my own.
No big deal though.
I use DynDNS.org to manage my DNS addressing, so it took all of about 2 minutes to make the change, and for the change to take effect. I also use Inbox Genius to intercept my incoming email. Inbox Genius does two things for me - first, they filter out 95% of all spam before it ever hits my network. Second, they store-and-forward all inbound email, which means that when my server goes offline (like today), it just queues up the messages until my server is back online. So I didn't even lose any messages.
Cool stuff.
I griped about IBM's DB2 drivers once already, but after uncovering this little gem I felt it warranted more complaining.
I discovered that the OleDB drivers for DB2/400 cannot handle the tab character.
With nearly every editor on the face of the planet supporting tabs ("\t"), and most SQL editors even reformatting with them for readability, IBM can't seem to make their driver handle them. It doesn't raise an error message indicating "hey, I dont do tabs". Nope, that would be too developer-friendly. Instead, when it recieves a tab character, it just bombs the connection. The pooled connection. And so your application is screwed until that pooled connection times out.
And this is not some "freebie" driver. This is the one that ships with iSeries Access... which you need to *own* an as/400 to obtain (it was a pain in the ass getting it as an independant developer without an as/400 here in my basement...). This bug has existed in at least the most recent 3 driver releases, according to my testing.
I can't imagine that I would be the only person ever afflicted by this bug - yet the IBM support information pretends their drivers are perfect. I hope that at least Google indexes this post and that it might help some other unfortunate soul later on.
IBM truly does suck.
Monday, March 21, 2005
This weekend I got to write a data access layer. Again.
I think this is around the 10th time I have had to reinvent this wheel. Sure, every time I do it the result gets slightly better (more features, more robust, better performance, etc). But at this point I am splitting hairs. Most of the heavy lifting is done with code generation techniques, I just tweak some of the template code to add the features needed for a given client/project.... but it's still a pain in the ass.
This time around, I wrote the access layer templates in VB (normally would use c#, but VB was a requirement this time) with async query execution baked-in. But aside from that, it's all the SOS.
I just wish some kind of standard would get defined for database schemas. I am tired of every DBA having their own naming conventions and data model idiosyncrasies. For heaven's sake, you prefer INTs over GUIDs for PK's (or vice versa), yes, you want an extra "@UserID" parameter passed to every DML procedure. Yes, you follow some naming convention that makes sense to you. Guess what, ALL DBA's do this. But because there is no consistency from one database or DBA to the next, we have to reinvent this silly DAL for every project. And it costs us precious time that we could be spending on actual business code.
Even if we had to resort to something like ISO standardization for schema definitions, would it really be so bad when compared to this insanity we have today?
We have Patterns and Practices defined for nearly every other aspect of software system design. Why not have some for database design? Simple normalization categories are not good enough - they are too vauge.
Data Access code should be a commodity - but because of unpredictable schemas it isn't. Why do we allow such an intrinsic component of software to NOT be a commodity? It's far too important of a cornerstone for us to just re-invent every time!
Sunday, March 06, 2005
Natty Gur is hoping to start up an online focus group (fancy words for "mailing list" I think) for architecture discussions.
I for one support his idea, as I get the impression that a local architecture group just wouldn't work out due to a range of unfortunate reasons.
While developers and businessmen have long had "support groups" to lean on for knowledge, advice, and networking, it seems that architects have mostly been reclusive and seldom interact with others in their industry. And since architecture is all about having the "big picture" and keeping your options open, I can't help but see a community (even if it's online-only) as being a big benefit.
Part of my new job is making sure our applications meet scalability, reliability, and performance requirements once we deploy to "the wild". Damn near anything will work in a development or even QA environment (assuming you are like 95% of all shops and don't bother doing load analysis until a problem comes up). But just because something works on a development machine is no guarantee it will continue to work once it is placed under pressure. "But it works on my machine" has ended many a developer's career and/or project's budget.
Anyways, I am rambling, so on to the point of this post...
I am truly appalled at this "webservice.htc" IE behavior component. True enough, I can visualize the thought process at Microsoft that eventually arrived at creating this thing. But I do not agree with it at all.
First, what it does:
If you are unfamiliar with webservice.htc, essentially it is a chunk of javascript code that wraps calls to web services (via the XmlHttp IE COM component). It knows all about SOAP and WSDL. In fact, in order to use a SOAP web service, you simply point it to a WSDL document (it expects something along the lines of "BlahBlah.asmx?WSDL", in other words - always late-bound service discovery). It then allows you to interact with the web service using the SOAP operations ("methods"), not too unlike the "developer experience" of using a web service proxy class in managed .NET code.
It is very easy to use in fact.
All you need to do is attach the behavior to any DHTML tag... for example a DIV like this:
<div id="MyService" style="display:none;behavior:url(webservice.htc);" />
Then in your page somewhere (anywhere, but most often done in the onLoad event of the body tag), you load the WSDL:
<body onload="MyService.useService('BlahBlah.asmx?WSDL', 'svcBlahBlah');">....</body>
Then calling the operations ("methods" for OO-heads) is as simple as this code which can be used anywheres in your page javascript:
<script language=javascript> var param = "some parameter..."; MyService.svcBlahBlah.callService(DisplayResult, "SomeOperationOnBlahBlah", param); function DisplayResult(result) { alert("Result: " + result.value); } </script>
Now that I have explained how it works in a nutshell, let me explain why I think its a really bad idea...
Second, my beef with it:
Each time useService() is called, the WSDL is downloaded to the browser. Chances are, a complete WSDL is massive overkill for the data a web application is wanting to pull via OOB (out of band). In the web service I am looking at right now, there are four operations supported. Each returns a simple string, and accepts one to three string parameters. However, the WSDL is over 8k! Since each page transition in the browser tosses all previously loaded script, this "wsdl setup" must happen at least once every time a page is loaded that needs to make web service calls.
On top of the WSDL cost, there is the cost of the HTC code itself. The webservice.htc file is 50K by itself! And since it is just linked javascript, it too must be reloaded every time a page transition or postback occurs.
So far, those costs are fairly hidden from view of the web developer. Not many will think adding the behavior style and calling a single method just once on a page will incur from 50k upwards to 100k or more bandwidth (the size of that WSDL can grow quite quickly as your web service becomes more complex). For reference, a page that is 100k *in total size* is considered effectively unusable in low-bandwidth settings, such as 56k dial-up or dedicated circuits. Not to mention if you ever hope to handle more than say three users or so....
On top of those hidden costs is the actual cost of the SOAP payload itself. Most developers are at least aware of this aspect, since there has been a great deal of discussion/ranting over the years about SOAP message bloat. In my test case here, this actually turned out to be the lesser cost when compared to the setup overhead. Each SOAP conversation is costing me roughly 2k for the request and 1k for the response, which honestly is not too bad. It's worth mentioning though that these tiny costs are exacerbated by the latency costs of the connections themselves, and if your design is inherently "chatty", these costs will add up very quickly.
Real Numbers:
So you might be rolling your eyes, thinking "so what. this guy is griping about a few extra bytes, he has too much spare time to dig this crap up". I would be skeptical as well. So I did some real analysis of this application using the simple ACT tool that comes with Visual Studio. This examined application uses Infragistics controls heavily, and I was expecting them them to be the worst offender, but measurements proved otherwise:
In ten minutes, my test ran 431 iterations of a simple "browsing" script, which logs in, does a few searches, and pokes around most of the application pages without modifying any data. In each test iteration, a total of 105 unique URLs were requested, though obviously many were hit multiple times. Between the pages themselves, images, and linked css and javascript files, a total of 82,224 requests were issued. 5,000 of those ended as "socket error", which indicates that I was hitting right up against the limits of my testing machine (Win XP) which was starting to have trouble handling the requests and thus dropped a few. 4,294 requests resulted in a 403 http error, which indicates also that the server was becoming saturated.
While only 441 calls were made to the web service in actual method calls (essentially once per iteration), 5,485 calls were made to retrieve the WSDL! In fact, this works out to roughly 12 times per iteration. No other resource was requested so often from the server... the next highest were about three aspx pages each requested roughly 3,500 times (they are reused in IFrames a lot, so this is somewhat understandable). The webservice.htc was also requested a total of 859 times, or roughly twice per iteration. So essentially, 8% of the total # requests, and 10% of the bandwidth of this application (even factoring in image files) was being expended simply to read a few strings of data without forcing a server postback.
In comparison, the notoriously bandwidth-heavy Infragistics grid, datetimepicker, and outlookbar controls had a combined impact significantly lower than the web service calls.
So, how to fix this?
The best approach is to just not do this. Chances are, an application that relies on OOB tricks probably should have been a Windows Forms application to begin with. But assuming you are 99% through the development (nobody ever thinks about load tests until then...), I assume a rewrite is out of the question. So, the question is "how to minimize the problem?".
There are three approaches I can think of to remedy this situation without resorting to drastic re-architecture.
- Roll-Your-Own. It is rather painless in my opinion to simply define your own (or go with "standard" XML-RPC) out of band mechanism. XmlHttp is quite easy to use, and writing the XML DOM code to construct requests and extract results/errors is not at all difficult. On the server end, its also not very hard to produce XML to match your needs manually, and simply write it out to the response. Using an HttpHandler would make it pretty lightweight too. This approach eliminates the huge webservice.htc downloads, and also eliminates the WSDL calls, since well... there wouldn't be any WSDL. Of course, the result is 100% proprietary, which may be considered a drawback.
- Use SOAP without WSDL. An extension to approach #1, you would interact with XmlHttp directly using your own javascript. However, you continue to use an ASMX web service on the server. As long as the parameters are simple datatypes, you can use the HTTP GET method and pass the parameters in the query string. Then, its just a matter of dealing with the (relatively clean) SOAP response. No WSDL to contend with in this approach, and no webservice.htc. You also get to use the strong tools support server-side for the ASMX web service. The downside is that you have to keep to simple parameters, and you have to code the response handling in javascript.
- Relocate the behavior code to a parent frame. By making an outer-level frameset with a single contained frame panel, you can link the behavior and associated WSDL calls in that one place, and call it from within nested frames. This has the benefits of retaining the SOAP conformance (allowing you to continue using ASMX), while reducing the WSDL and HTC requests to once per browser session. The downside is that now you have to pay more attention while coding. Calls to the webservice proxy have to be made by traversing the frameset (iterating through parent frames).
These are all decent ways to place a band-aid on the problem. But the problem itself is, to me, indicative of a much larger problem that I see widespread in the industry today...
Misuse of SOA tools and components
Web Services are a component of SOA (Service Oriented Architecture). WSDL and associated discovery/description technologies are tools of SOA. More and more, I keep seeing people attempt to use, or more accurately "misuse", these things. Web Services are implemented as if there was zero cost in performance/latency/reliability. WSDL is fetched at run-time to configure service proxies on the fly. This is NOT how these technologies were intended to be used, and they perform and scale miserably when used like that.
The purpose of WSDL is to define service contracts. This is for the purpose of being able to understand and properly interface with a service. You interpret the WSDL ONCE and ONLY ONCE (preferably at design time!). Your code will obviously depend on the semantics of the contract declared in the WSDL, and so it makes zero sense to interrogate for WSDL at run-time! In fact, once you go to production, its a pretty good idea to completely disable the WSDL handler in ASMX web services, if nothing else than to lower your DoS vulnerability profile (after all, generating WSDL in asmx isn't free).
And the invocation of Web Service operations themselves is not intended for such scenarios as OOB web browser activity. Web Services are a way of enabling applications to communicate via messages, which is useful in Enterprise Architecture (ESB's) and Integration (EAI), but of little value in a contained web browser application.
Microsoft really should be more responsible and put a warning on this thing. The documentation on MSDN reeks like a marketing brochure. It discusses all the wonderful benefits, but makes no mention whatsoever about the potential problems. Nor does it even mention the fact that accessing web services from a browser is a dubious idea from the outset.
Sunday, February 27, 2005
Don't read this if you don't like to read rambling griping...
-------------------------
For the longest time, Oracle was my least favorite database platform billed as "enterprise level". Now, I ceremoniously pass that gold belt to DB2. And here is why:
- If you let connections pool, you get nasty "Cursor C1 already open" errors. Well, guess what the default behavior of their OleDb driver is? Yep, pooled connections. Of course,... pooled connections in an "enterprise" setting wouldnt be a very important feature to make work. Nah.
- You want to only select rows from a table using OleDb where a certain field value is null? Tough luck, NULL support is unpredictable at best. Most times if you attempt to filter or join on a field that has null values, you wont get a resultset back. Period. No error, no warnings. Just no resultset (not even an empty one with field metadata but no rows).
- Multiple statements in one batch? nope. Create a NEW connection every time and issue your query (no pooling, remember).
- So you just want the database driver installed? Too bad, you must install the WHOLE ClientAccess/400 product to talk to an AS/400. (not small)
- Oh yeah, this is talking about DB2/400, not the other flavors. I have no idea how bad they are, but I can imagine.
- Speaking of DB2/400, if you want to pull data from a table (really maps down to os/400 "file members") then most likely you will need to specify system name and library in order for the object to resolve. If you haven't seen AS/400 system names, they are remarkably easy to remember and type. "S3059863" is an example. And of course AS/400's are still living in the 1980's and all objects are limited to 8 characters uppercase. This includes files and file members (a.k.a. tables and fields in SQL). Yeah. So to issue a SQL query it looks something like this "select GSDOCO, GSORG, GSCHGN1, GSHHYT from S3059863.SOMELIB.F59603 where GSJDMT > 105058". Why, of course that means "select the ID, sales rep, charge amount, and sales tax from the sales table that were updated after 2/27/2005". Or does it.
- Oh, and half the time when you install a os/400 "service release" update, it breaks untold other things... with the DB2 interface being one of the common victims. Then, to fix your application you get a ClientAccess/400 service release. Which, invariably breaks yet something else. Fun stuff. This is why most as/400 systems operate a year or two (at least) behind current patching levels. It's just too scary to update your machine!
And whats the saddest thing about dealing with DB2 in this kind of environment? The cost of that hunk of iron is two orders of magnitude above even a significantly overarchitected system built using nearly any other architecture which would give comparable reliability and performance.
Sometimes, it feels like interoperability with an AS/400 via DB2 isn't worth the headaches.
Friday, February 25, 2005
I have two potential topics I wish to cover. Can't do both though. Both can get pretty deep, and I will have a tough time fitting it into a single session as it is. So even after concluding a topic, I will need to whittle down the details. But first on to the topics.
Leave a comment, send me a message, whatever. Just let me know which of these two topics interests you most for a Code Camp session. I will probably save the other one for a possible Fall code camp, or another user group presentation. The subjects are both just too interesting to me for me to totally ignore either one.
- Topic #1: Asynchronous Programming
"Fully Baked" CLR support: Async Delegates, Thread Pools, System.Timer, and Queued Work Items. "Partially Baked" CLR support: Thread/ThreadStart, interthread communication, monitoring, signaling, and syncronization. Also would touch on important topics such as debugging, concurrency, Control.Invoke, lock(this), and deadlocking/performance implications. The end of the presentation would also talk about some exciting new async support in Whidbey for event-based async processing. In other words: "This ain't your daddy's multithreading presentation"
- Topic #2: Performance Planning, Design, and Tuning
In my opinion, a really important topic, but also really big. I would cover results-based performance programming, memory management (yes, its still important!), algorithm selection, profiling, and evaluating trade-offs. Would also touch on other aspects of performance, such as choosing your battles and managing the user experience/expectations. Lastly would talk a little about impact of Whidbey (generics/boxing, etc).
Let me know what you want to hear about!
Thanks everyone that posted comments or sent messages and stuff over the past week.
I seem to have passed the thing yesterday, and just as fast as it started, it's now over. It is difficult explaining just how incredibly painful this was, but others who have gone through it before will understand. You guys who have been through it before have my complete and total respect. And to others who have not had this before: I hope you never get it. I was lucky my wife happened to be home when it hit me.
Saturday, February 19, 2005
This is how I spent mine:

Doped up on Morphine and a few other things I do not have memory of.
Started out with incredible abdominal pain, getting progressibly worse. We finally called an ambulance when my hands and feet started going numb, and I couldn't control the shuddering.
Turns out I have four kidney stones, the largest (4mm) of which was trying to pass down to my bladder. The other three are still partying in my kidneys. Guess I am in for a really fun week ahead.
Wednesday, February 16, 2005
In addition to learning how to screw up database schema manipulation in SQL 2005, I also picked up a few nifty tidbits in today's ISV event (all subject to change before RTM, and always the chance I misunderstood the material presented):
- SQL 2005 supports synonyms. Well, it always supported them within a query, but now it supports them as permanent object aliases too.
- DDL triggers. You can setup triggers for most DDL operations, such as CREATE TABLE, DROP PROCEDURE, ALTER LOGIN, etc.
- "text" and related BLOB types are being depricated. "varchar" now supports unlimited size, which is defined using the MAX keyword. In other words, use "varchar(MAX)" instead of "text".
- DML statements now support an OUTPUT clause where you can dump the contents of the "inserted" and/or "deleted" special virtual tables out to a table-valued variable.
- Native encryption and signing support. Built-in functions that accept a text value and a passphrase (symmetric encrypt) or x509 certificates (asymm encrypt). SQL Server can also store certs internally for these purposes.
- XML support is pretty cool, but jeez using .insert() or .update() can get really nasty in a hurry if the XPath strings get complex.
- Kinda neet that you can create a CONSTRAINT based on an XPath expression. You can also create an index based on an XPath expression.
- SQL Notification Services shows some promise. But aside from old-school client/server scenarios, the SqlDependency class seems to be of limited usefulness. Not very viable for smart-client or n-tier deployments without a lot of extra plumbing code (CAO's or sponsored SAO's and such). However, if you ARE doing client/server, SqlDependency is a nice way to watch for changed query results.
- Service Broker is rather pimp. It's a message queueing engine that operates within SQL Server. It's contract/schema based, and lets you enqueue/dequeue messages within DML transactions. New MESSAGE, CONTRACT, QUEUE, and SERVICE objects in T-SQL are used to support this.
- CLR integration looks pretty useful (as long as applied correctly). UDT's and Aggregate UDF's look most promising here.
- You can use Service Broker to perform long-running transactions, as long as the requester does not need to be notified of completion/failure, or you can use Notification Services to send a message back to them.
- Microsoft decided to not supply Query Analyzer tool with SQL 2005. Bad move IMO. QA was nice because it was very lightweight, and it also didnt give developers a whole lot of chance to screw up with the "right-click database drop" stuff.
- ADO.NET 2.0 has a few new handy features...
- SNAC - Sql Native Client, no longer need MDAC. I am guessing this is a full native .NET implementation of SqlClient, but not clear on that point.
- MARS - Multiple Active Result Sets. You can essentially have more than one DataReader open on a single connection (useful when doing nested loops) (of course, nested loops are probably bad in your middle tier anyways, but who am *I* to judge this feature?).
- New Async versions of operations. BeginConnect()/EndConnect(), BeginExecute*()/EndExecute*(), etc.
- You can now load a DataTable directly from an existing DataReader. No longer need a DataAdapter... MyTable.Load(MyReader).
- New DataTableReader is an IDataReader implementation that sits on top of a DataTable. MyReader = MyTable.GetReader().
- In order to enable MARS and async operations, you need to specify "Asynchronous Processing=true" in your connection string. This might end up unnecessary when SQL 2005 is released.
This will work in SQL 2005...
Create trigger trgHmm1 on DATABASE for CREATE_TABLE, DROP_TABLE, ALTER_TABLE
AS
ROLLBACK;
GO
Create trigger trgHmm2 on DATABASE for CREATE_TRIGGER, DROP_TRIGGER
AS
ROLLBACK;
GO
not sure about this one though:
Create trigger trgHmm3 on DATABASE for CREATE_TRIGGER, DROP_TRIGGER, DISABLE_TRIGGER
AS
ROLLBACK;
GO
Kinda makes a strong case for really keeping tight control over who has db_ddladmin in a database doesn't it?
Thursday, February 10, 2005
OK so I am really late on the heads-up, but tonight is our monthly Atlanta geek dinner. Hey there! Yes, you reading this, you are coming right? You did RSVP to Shawn right? Thought so.
The Powerpoint Presentation and Source Code I used in monday's Visual Studio Integration topic can now be downloaded from this link.
If you just want to install the NVEdit Add-In (with Core Library and Help File), you can download it from this link.
If you have no idea what I am talking about:
NVEdit is a simple Visual Studio 2003 Add-In that I created as a working example for my presentation to the Atlanta C# Users Group. This Add-In allows you to store large "non-volatile" textual data (SQL queries, XML/XSD documents, etc) as an embedded resource in your assemblies. The NVEditor keeps seperate name/value collections (Dictionaries) for SQL, XML, XSL, XSD, and HTML. The values are accessible in a very easy manner at runtime using static members, not too unlike the ConfigurationSettings class of the .NET Framework. Unlike the ConfigurationSettings class however, the NVData values are not stored in the .config file (which is succeptible to tampering).
The whole idea is that this gives you a very viable alternative to cramming stuff that doesn't belong into .config files or into hard-coded string constants.
Here you can see a screen capture of the simple NVEditor UI:

I apologize for the delay in getting this uploaded. I tried (again) to get the RichTextBox to perform colorizing the way I wanted it, and it just wasn't working out (jeez that control really sucks). All of that stuff is ripped out now, and I cleaned up a few other bits since my presentation.
And I also compiled a help file that gets installed as well now (Hooray for NDoc!). Even though it really didn't need a help file. I mean, come on, this is a pretty darn simple tool!
Wednesday, February 09, 2005
Anyone else dig motorcycles?
The 2005 Great American Motorcycle Show is being held in Norcross this weekend. I went last year, and some of the bikes really kicked ass! So I am thinking about going this year too. Anyone else into hogs and choppers and all that, and wanna go check it out too?
Tattoos and grizzly beards are optional!
And yeah, I know my VTX has been sitting in the garage for a year now (undriven), but one day... one day.. I will get to take it out again on the road :/
My VTX (well, mine also has saddlebags and stuff):
_Metallic_Silver.jpg)
(yeah, it's not a Harley... can't afford a HD or a custom bike just yet...)
Sunday, February 06, 2005
Shawn Burke is attempting to get the Windows Forms framework source code and PDBs released with the FX 2.0 SDK.
First Post
Second Post
Sweet.
Sounds like it will be stripped of comments and such if it happens (at first deployment at least), but who cares. We can at least see the original variable names and step through it in the debugger.
Back in my years of working with the Delphi platform, I always saw the inclusion of core library source code as invaluable. Just being able to clearly see how the framework is implemented internally provides immense insights into how you *should* be interacting with it.
It was also a very good learning tool. I spent many hours (days) just browsing through the VCL source, finding little nuggets here and there - useful techniques, undocumented features, and internal implementation details that can make all the difference in a production application.
I sure wish I had access to that source code when I found an anomaly with animated GIF's in the PictureBox control. Instead of debugging and troubleshooting that issue for weeks (at my own expense I should add), I most likely would have uncovered the culprit far sooner if I had the source code in my hands.
I hope this goes through, and further hope that even more of the framework gets opened up like this in the future.
Thursday, February 03, 2005
This coming monday, I expect to be doing a presentation to the local C# group. The last time I presented to the group, it was a hastily prepared practical examination of WSE2 programming (without ASMX), schema-oriented messaging, service agents, and other basics of using WSE2 in a SOA environment.
The presentation this month is completely different.
This time, I will define a common issue/concern with application design: the handling of non-volatile textual data. Stuff like SQL queries, HTML fragments, template XML documents, and so forth that often pepper the codebase of our projects, making maintenance difficult.
I will present a solution to this issue in two parts: A simple core library to provide an extremely friendly "developer experience", and also a Visual Studio Add-In that works hand-in-hand with the core library to make the solution very simple to use.
We will talk about the issues I encountered while building the core library, the process of building and deploying a VS Add-In, and also the issues that may arise during construction of an Add-In.
At the conclusion, we will end up with a functional and useful tool that can be employed in our code projects, along with a better understanding of how sometimes extending the Visual Studio environment can provide a good return on investment.
So, if this subject interests you at all (I find it extremely interesting - but I am truly a geek), or if you simply want to get your hands on this useful project tool, then make sure to attend this months Atlanta C# User Group meeting!
I have been watching a fair number of live webcasts lately... from Systems Builder events (OEM info for MCE configurations), to Visual Studio integration, to Web Services topics, to... well... pretty much almost everything. I love free seminars and presentations, I guess its why I go to so many user group events.
Well, two days ago I got an email from Microsoft...
"Congratulations, Keith, you have been randomly selected as a winner in the Windows Mobility Marvels Sweepstakes! You became eligible for this sweepstakes by attending the MSDN Webcast: .NET Compact Framework 2.0 (Level 100) on January 19, 2005 and by submitting a completed webcast evaluation."
After confirming my mailing address, the following day they overnighted a new Pocket PC to me!
It arrived today, as promised. I didn't know anything about it (mfg, model, etc) until it arrived... but it turned out to be an HP iPaq h2200. Not the fastest or most feature-rich PPC, but definately good enough for what I want (something to bang code against). Honestly, the only downsides to it are the (relatively) slower CPU (intel pxa255), not a huge amount of onboard memory, and lack of WiFi. However, it has CompactFlash2 and SDIO/MMC slots, so the memory and networking can easily be addressed.
I have been wanting a PPC for a long time now, just never worked up enough "impulse shopping" momentum to actually click the "buy now" button on any merchant sites. And now I don't have to!
I love this - not only do I get FREE great-quality education, I now also get great gizmos!
Monday, January 31, 2005
OK, so I stirred up a few bees in the last post :)
I would have VERY much preferred if it (captcha as implemented in major blogging engines) were more solid. But it *cant* be. Blogs are made to be open and accessible. Thats the whole point, the ability to post comments is a big part of that. Like you say, blogs without comments enabled are highly inconvenient.. they are nothing more than traditional "programming" - one way communication. So, we *want* them to be accessible. Obviously, captcha throws a speedbump in that, the whole idea of captcha is to be a speedbump.
And that would be OK *if* it actually WERE a speedbump. As soon as I saw the implementation (always 6 letters, easy contrast, fixed character set - actually it's plainly just 3 hex values, background always a fixed pattern) I knew instinctively that it would be incredibly easy to circumvent. I don't even think you need an AI engine to do it... I can think of a few algorithms that have zero Neural Network components that could achieve a 50% success rate. My point is this is just a very brief escalation in an arms race, which buys us very little time but throws up a significant deterrent to valid comment posters.
I would also point out that as far as I can tell, the Web Service comment APIs do not even support it. And these are the most visible and obvious spammer attack vector. After all, they are using automated tools... its easier to just call a web service than scrape a web page exchange. And of all the blogs I read, only two that I can think of right now (Shawn's and Daily WTF) have proprietary comment submission API (or no WS API) that is not exposed here.
This guy's work is not going to give spammers any kind of leg-up. You can bet they were well on the case long before... it's just too enticing for them. They are fully willing to send out email spam just to get the one in 10,000 who will click the links... blogs are a gold mine compared to that... even the comment links. As far as I know, they still havent breached it yet (en masse), but it's only a matter of time.
The reason I say I think this guy did a good thing here is that he is making it very clear to his peers (he only spammed MVP's) that they do not have as much security as they think they do with this. It's easy to get mad at him for "opening the pandoras box", but he didn't really open it so much as he said "hey, everyone open your eyes, the box is already open!".
I would personally like to see a real solution to the spam problem (I hate it as much as anyone else). But this wasn't it. This was too easy to circumvent in an automatable way... and once a spambot is made for ONE dasBlog site, it works for ALL of them, same goes for the other platforms.
The only way to give yourself real relief is to implement your own captcha (or other confirmation process) so that you won't become vulnerable by virtue of your platform. It's one situation where "roll your own" security may actually be better - since we dont have a "standard" that is solid enough. Thats too much work for me though (maybe for others it is not), I just dont have the time for it. It's less hassle to just delete the garbage as it comes in at this point.
Sunday, January 30, 2005
As soon as I heard dasBlog and other blog engines had implemented CAPTCHA tests on the comment forms, I knew it was only a matter of time before it was shown to be irrelevant. But Casey Chesnut has defeated it even quicker than I thought would happen.
He simply spent a few minutes studying the implementation, figuring out it's limits and patterns, then wrote a bit of AI to decypher the images. His routine only has a success rate of 50%, but thats more than sufficient to perform comment spam. To prove his point, he ran it against over 90 blogs on msmvps.com.
This is the precise reason I never even considered enabling this feature of dasBlog. It is easily circumventable, and really does nothing more than interfere with your real readers' ability to contribute.
This emperor has no clothes.
Hats off to you Casey, this false security needed to be called out.
Saturday, January 29, 2005
It's just not threaded properly. It can't be.
I noticed long ago that it uses worker threads to update feeds, and often when a feed fails to update, that worker thread (most likely a pool thread) becomes a zombie. Over time, this further degrades performance until the pool just runs out of available threads (not to mention the memory consumption is just insane by then). The only remedy is to shut down the program completely and restart it... giving you a day or two before having to kill it again.
And now this - I have noticed what can only be described as "anomalies" in my downloaded feeds before... things like seeing comments attached to the wrong posts, and so on. I always assumed this was just due to bugs in the RSS feed producer I was subscribed to. But today, on a pair of blogs, both had a post with a title of "{...}". Each had a jumble of intermixed text from recent posts in the other blog. In order to get the feeds sorted out properly, I had to delete them from my opml, restart RSS Bandit, and add them back. And of course, there are no posts on either blog titled "{...}".
I suppose the corrupted posts could be due to buggy local storage code, but it sure looks a whole lot like the updater threads are just poorly monitored and synchronized.
I guess it's time to try NewsGator. I am not thrilled about packing my RSS feeds into Outlook, but guess I will get used to it.
At least they have a free trial period though. I hate paying for something and tossing it out shortly after.
Friday, January 28, 2005
Three new specs were released as W3C recommendations today...XML-binary Optimized Packaging (XOP), SOAP Message Transmission Optimization Mechanism (MTOM), and Resource Representation SOAP Header Block (RRSHB).
They are all interrelated... XOP is the XML mechanism that is the building block for MTOM (SOAP implementation of XOP which does not dictate wire protocol binding), and RRSHB is an expansion of the SOAP HTTP binding to support MTOM/XOP.
In a nutshell, all of this stuff has one essential purpose: Freeing you from having to encode binary data into base64 when you serialize a SOAP message. Basically, base64 is a really heavyweight encoding scheme, that adds a TON of fat. By allowing binary octet data to actually be transmitted unencoded (and under certain circumstances, relayed across SOAP processors unencoded) instead of taking the serious encoding hit, the bandwith requirements of moving large messages around is reduced significantly. Not only that, but the CPU overhead of doing the base64 encoding/decoding is also alleviated. And yet another, though smaller, benefit is that less buffer resources are required on both ends of the pipe (assuming both ends can deal with the data in it's raw format). Of course, some operations may require access to the data in base64, so a SOAP sender or reciever may have to encode/decode it anyways (I think XML-Signature requires binary data to be addressable in base64?)... but it still gets the bandwidth reduction when it is transmitted over the wire.
I can see a lot of benefit to this.
For example, this makes digital media transmission over web services a whole lot more appealing (as opposed to scrapping together a proprietary protocol). SOAP-routed media could turn out to be quite interesting. I know folks have tried to do it with Web Services, and gave up in frustration due to the bandwidth hit... but now the hit isnt there... it's now basically raw media data wrapped in some dandy XML metadata... fascinating...
Another use I can see is just around the corner when ADO.NET 2.0 datasets support REAL binary serialization instead of the "serialize to pseudo-xml, and call it 'binary'" serialization of ADO.NET 1.x. In a purist sense, we know it's bad form (argue it here, here, and here) to send datasets over web services "Data on the Inside vs. Data on the Outside" and all that. But I tend to agree with the opinion that in most cases once we commit to sending a dataset in a message, it becomes "opaque" like an image or any other binary data would be... and doesn't really break the purist view (come on, squint real hard with me). So passing a large dataset in binary format is perfectly acceptable to me, and these new specs will make it significantly more viable. One of the major debate points against datasets over webservices has been the bloat it causes... but with binary serialization and XOP/MTOM, that arguement fades fast.
Of course like anything else, I am sure someone somewhere will find a way to abuse the specs and I will be griping about it later.
Thursday, January 27, 2005
The word this week is that on Friday there should be a set of new application blocks released on the MSDN patterns and practices site. We can expect a new Data Access and Logging block, as well as a Cryptography block, and a few other treats. Sounds like a pretty good pack of reusable blocks, so I for one will be keeping my eye on MSDN tomorrow.
[update:] The new blocks are now online at this url: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/entlib.asp
Monday, January 24, 2005
What a stupid and obscure bug in VS.NET 2003. Thankfully someone figured it out and posted the fix on their blog (which didn't take all that long to find in Google). Making a note of it here in case it happens again. Who would have ever thought a DLL from the Visual C++ directory tree in Visual Studio would get unregistered simply by running a VS add-in deployment package install/uninstall a few times... and then would keep C# project wizards from working??
At least the fix is very simple and quick:
regsvr32 "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\vcpackages\csproj.dll"
Yes, thats cSproj.dll in the VC7 folder.
Thursday, January 20, 2005
Brendon and Matt, The Atlanta .NET Regular Guys are going to resume this monthly event. It was put on hold for the last two months mainly due to holidays. It's a pretty laid-back meeting, often with very few attendees. In fact, it would be a record if some more folks swung by and raised our attendance to, say, 5.
In any case, tonight is the meeting for January. At 6:30 PM, you can find us at the 5 Seasons Brewery (Roswell Rd, just inside 285, in the back of the "Prado" complex). I am told they actually have a free WiFi access point there, so if you get bored with the discussion then you can always just surf some p0rn.
Swing by and join us!
Tuesday, January 18, 2005
Thanks Michael for pointing out the new dasBlog release 1.7.
So far it appears to run much smoother and faster, and the referrer blacklist looks promising as well.
My favorite feature though has got to be the new "Internet Searches" section in the Referrer Log admin page. Now I can see (more easily) what kind of google searches are finding me, and therefore what post topics draw the most interest.
Monday, January 17, 2005
Just bookmarking this so I don't lose the URL again... Florida Code Camp
Tuesday, January 11, 2005
I couple weeks ago, I recounted some trouble I was experiencing with the .NET garbage collector. My efforts to dispose and clean up objects, and eliminate unnecessary allocations (essentially, to be miserly with resources) brought a great deal of stability, performance, and peace of mind.
However, while much more rare, I still continued to experience random crashes in the application. This time, however, I was able to get Windbg to trap the TerminateProcess, allowing me to perform post-mortem. Here is what I discovered:
In one screen of my application, there is a PictureBox. This screen is displayed while the application is performing lengthy operations, the PictureBox contained an animated GIF. The purpose of this was to keep the user preoccupied while waiting (just like the waving flag at the top right of your browser while pulling down a page). Sounds pretty innocuous.
Well, as it turns out... behind the scenes, either the framework or Windows itself (I did not dig into the PictureBox MSIL to check) actually spins up a thread to pump the frame changes of the animation. Yes, this is a recipe for trouble. A rogue thread running in the system, whose obvious task is to update the GUI (it is pumping the animation). Hard Application crashes are a well-known side-effect of a background thread that does not synchronize all shared (UI) resource access with the owning thread.
So what was happening (confirmed by the smattering of PictureBox and lots of native WinAPI calls over the thread that triggered the crash) is that the animation pump thread was not properly coordinating with the UI thread that actually owned the PictureBox. Or perhaps it was behaving well under normal circumstances, but it was not observing the Garbage Collector's request to pause while the GC does it's thing. You see... the crashes all also happened to occur while the GC was performing a heap walk. While the GC thread is active, all other threads are *supposed* to be paused. But the animation thread was not. And thereby the waking of that animation thread to pump another animation frame, if it happened to wake while the GC was still walking the heap, would cause a very nasty crash.
Simply replacing the graphical content of the PictureBox with a static image (such as a JPG) eliminated the problem by virtue of the offending thread never being created in the first place (it is only created if you have an animated image loaded).
So my primary lesson from this is to simply not use an animated GIF in a PictureBox control. My secondary lesson is that it is still a very wise thing to explicitly clean up after yourself using Dispose() and Clear() on objects that support those semantics, and setting references to null for all non-value types as soon as they are no longer needed. Work *with* the garbage collector, not against it!
Apple just announced this really slick looking machine... the Mac Mini. I love the form factor, it reminds me of the old SPARC stations we used in college.

I sure would love to see a similar form factor MCE machine, priced around the same ($499). Right now, the best we can do with Media Center is the HP z540/z545 or a “build your own” using something like a D.Vine case from Ahanix.
Perhaps, like me, you are contemplating building your own Media Center PC. Perhaps the HP set-top boxes are just too expensive. And the other products from Dell, Viewsonic, etc just look ugly or are too noisy. Well, Microsoft held a live Webcast session a couple days ago, covering the entire build process for putting together an OEM MCE system. Pretty much all you need to know about hardware selection, common issues, and configuration is covered. I tuned in, and found it to be quite informative to someone (like me) who has yet to attempt the building of one. And now, the recorded webcast has been made available for viewing. This link will take you to the registration page if you are interested (60 minute duration webcast).
Thursday, January 06, 2005
I just saw that there is already a linux-based offering in the PMC space. A company called ARCHOS is releasing the Pocket Media Assistant PMA400 this month (product specification page here). The feature list is very impressive, and it even claims to be capable of dealing with DRM-locked Windows Media files. And for under $800, it's quite an interesting device... especially considering it supports PDA functionality (touch screen!), wifi, wired ethernet, and even can record direct from cable/satellite.
This kind of competition is great, it will help push the envelope in the portable media and media center arenas.
Bill Gates did the keynote for CES in Las Vegas, where he demo'd Windows Media Center Edition. Of course, like any Microsoft demo he ever does, it crashes at some point (I think they stage the crashes on purpose, to get media interest higher). The entire keynote is taped and can be viewed online at:
http://metahost.savvislive.com/microsoft/20050105/ms_ces_20050105_300.asx
***This link has been slashdotted, so the playback is a little rough right now. I recommend setting your media player to a 64k stream max with a sixty second network buffer before trying to view this...
Tuesday, January 04, 2005
A lot of lip service has been given to the “new media” lately, and I am as guilty of this as anyone. We like to talk about our MP3's, our DivX's, DVDs, media centers, iPods, blah blah blah....
But what about what is arguably the best media to be found? I am of course talking about the printed word: Books. They have been around far longer than any other communication device. And even in this era of eBooks, podcasts, and pay-per-view, they are still the absolutely best form of storytelling there is.
A perfect example: Rent “Starship Troopers” (~1997) and watch it with all of its special effects, cheesy lines, and ridiculous plots. If you make it through that (or at least far enough to follow my point), then go pick up Robert Heinlein's Starship Troopers (~1959) from a bookstore or your local library. There is no comparison. The original story is a masterpiece, especially considering that it was written in the 1950's. The movie is at best a mediocre mentally-void shoot-em-up special effects flick. I could list more examples (Lord of the Rings Trilogy) if I really wanted. Not in another hundred years will electronic story delivery be able to beat the tactile realness of a good printed book.
I had almost forgotten this, having been literally overwhelmed with all of the “new media technology” in the last few years. But today I happened to glance over at a bookshelf I had not payed attention to in four years. There, among the rows of books I had read, were six of them I had not. I had purchased and forgotten them. Such a waste (not of the money for the books - but of my time in the last four years). One book authored by Charles Sheffield, another by Robert L Forward, and the other four by my favorite author of all time, Greg Bear (I am so envious of Scoble).
I think it's also of no coincidence that for 4 years I have been having trouble keeping focused and motivated. Reading is a very healthy activity for the mind, and I have been neglecting this for too long now. I have recently taken the steps to rejuvenate my health (diet and exercises), but I have been forgetting to take care of my mind.
So as my first resolution for the New Year, I am going to read these six books. The 10 or so DVDs I was given for the holidays will just sit unused while I take this time to dust off the creative side of my brain.
I still cannot believe I ever allowed one of my favorite intellectual pastimes (hard sci-fi reading) fall away unnoticed like that...
Here is a link to some very interesting smartphone concept devices that were leaked from Samsung. I am especially intrigued by the third one:
“Samsung "Thor" Processor unknown, 3GB hard drive for memory, Bluetooth, GSM/GPRS, 18-bit Color 240x320 display, 4.45" x 1.89" x 0.83", and "MS Smartphone Magneto"”
Yes, this is a phone. With bluetooth and a 3G drive. No idea what “Magneto” is, but my guess is its a Smartphone version of Portable Media Center Edition. Wow, phone + camera + PDA + bluetooth + streaming media. This is really approaching the “all-in-one” personal device. I also notice it lists “Stereo BT Streaming” as a feature, and also “OTA / Online Music Service”... I don't suppose these will accept arbitrary sources. This could lead to *realtime* mediacasting if so.
Very promising direction here...
Saturday, January 01, 2005
In my recent pilgrimage through the .NET memory model, the garbage collection process, and the fine art of improving performance through runtime profiling and heap inspection, I came across this little piece of knowledge that may one day (maybe today?) benefit you as well. This is a short discussion of the subtle and rarely mentioned static function:
String.Intern()
From the MSDN documentation, this method is explained as such:
“The Intern method uses the intern pool to search for a string equal to the value of str. If such a string exists, its reference in the intern pool is returned. If the string does not exist, a reference to str is added to the intern pool, then that reference is returned.”
Sounds innocuous, but this little core feature may end up having great impact on your applications. Essentially, when you use String.Intern(), instead of making a copy of the string data on the managed heap, you instead are returned a reference to a shared copy of that same literal string. When you embed literal string values (string myString = “some value”) in your program code, the compiler automatically does this for you. Embedded literal strings will be “interned” for you without any additional effort.
So you might be wondering, “OK so now why do I care about this, if the compiler already does this for me?”. The answer is that the compiler only handles hard-coded string values. Consider this snippet of code:
public string[] BurnBabyBurn(string Input) { string[] MyHugeArrayOfJunk = new string[2000]; for (int Index = 0; Index < 2000; Index++) { MyHugeArrayOfJunk[Index] = Input; } return MyHugeArrayOfJunk; } [...] string[] test = BurnBabyBurn("0123456789");
As you have probably guessed, this will make 2000 copies of the same literal string “0123456789“. Not very friendly to your memory footprint. So let us alter the previous code sample to make use of String.Intern():
public string[] ByNiceToMe(string Input) { string[] MySmallerArrayOfJunk = new string[2000]; for (int Index = 0; Index < 2000; Index++) { MySmallerArrayOfJunk[Index] = String.Intern(Input); } return MySmallerArrayOfJunk; } [...] string[] test = BeNiceToMe("0123456789");
The difference is significant. This second version of the same logic will now make 2000 references to the same string value, rather than 2000 copies of it. This is a huge difference in terms of memory allocation on the managed heap (don't believe me? Try both routines and use CLR Profiler to see how much String data is sitting on your heap!).
Now sure, this example is simple and contrived (you really wouldnt ever build a 2000 element string array with the same values would you?). However, it illustrates a very useful way to reduce your memory churn in an application (and therefore reduced footprint, GC time, etc). Supposing you had a DataSet filled with values. Suppose there were 10 string columns, and 500 rows. Assume much of those 5000 string values were duplicates (result of enumeration domains, looked up values, etc)... I wonder what the memory savings (and GC savings when you Dispose() it!) would be? A hint: big enough to pay attention to.
Friday, December 31, 2004
Wow, just look at the “roll call” from last night's geek dinner in San Francisco. Thats fourty-nine people. Well, sure they had some well-known names there, but then again we also have some well-known names at our own Atlanta events (at least as far as I am concerned).
I am quite envious. We only had what, five people at this month's event? We can do better. Is it just a matter of “getting the word out”? I know it cannot be because of the holidays... the SF dinner was held between xmas and new years. Southerners are noted for their sociability and accomodation - such a recurring event should fit right in with culture here.
Tuesday, December 28, 2004
I have been battling a pretty strange stability problem with a particular .NET application for about a month now. The end-user(s) first reported it around the thanksgiving holiday... but my gut feeling (and previous experience) tells me that it really surfaced earlier, and they just waited a while to inform me about it.
In a nutshell, the application just “disappears” randomly. No trappable exceptions. No warning signs. It just vanishes as if the main form had been closed (it is a Windows Forms app). There is no “reproducible” pattern of actions that lead up to a crash, sometimes the user can work for hours before getting a crash (from a seemingly benign activity), other times it crashes every ten minutes.
My first suspicion was a threading problem. I know this is a classic symptom of a background thread trampling the UI thread's GUI objects. However, I removed the (very little) threaded code from the application, and the problem persists. There are now absolutely no references to the thread pool, nothing attempts to create a manual thread, and nothing makes use of BeginInvoke/EndInvoke with delegates or web service proxies.
My second suspicion was that perhaps my cache refreshing mechanism was to blame. At application startup, immediately after login, the client program downloads “lookup tables” from the server. These are things like basic customer/brand/etc information that is often referenced, but for performance I choose to cache these lists locally. They are just simply classes (not datatables/datarows) to keep the overhead as low as possible. On a regular basis, there is a timer (was originally a System.Threading.Timer, but replaced with a Windows.Forms.Timer when I removed all possible multi-threading) that fires, and any new/modified cached items are retrieved from the server and merged back into the local cache (uses an audit time-stamp to determine what to pull down, if anything). I didn't think this mechanism was to blame, but just in case, I have completely disabled the cache refresh timer. The crashing bug still persists.
After that did not work, I started looking into “nonstandard” things that I might have been doing in my code for clues to this elusive bug. The biggest thing was that I was using CallContext.SetHeaders() to pass along security principal/identity information as out-of-band data along with every Remoting call back to my remote app server. This was used to enforce call-level role based security. I gutted this code from my application on both client and server ends. The bug persisted.
Now I am at the point where I begin to grab at straws.
I created a new TextWriterTraceListener during application startup. This gets pointed to a unique filename every time the application starts up. I basically went through nearly every method of every class/form in my client codebase, and added tracing information that gets flushed through this new TraceListener. We are talking LOTS of tracing information (I ended up going back later and commenting some of it... the trace files were just getting too big to work with). This tracing data showed that sure enough, the application was just terminating hard on an unpredictable basis. One thing I did notice however, is that 1 in 3 crashes were during a Remoting call return... as the response was being deserialized.
Hmmm. I cranked up CLR Profiler to gain some insight. I also used Windbg and Vadump as described in this article to peek into what was really going on in my application. It seems to me that the BinaryFormatter used in Remoting serialization is allocating some significantly large byte[] structures (really big... like tens of megabytes). This shouldn't be a problem really, given its only temporary allocation. However, what was also happening is that these large allocations were surviving into Generation 1 and 2 of the garbage collector... meaning they were not getting cleaned up until a Gen-2 Collection was triggered.
My hunch was that a Gen-2 GC Collection would become inevitable eventually... and this collection was in turn somehow causing my crashes. To test this, I decided to begin applying a call to the following method liberally throughout my application... mostly in places that I know were high-traffic (such as just prior to Remoting calls): public static void GCCollect() { CrashTracing.Trace(4, "GC", "Forcing a gen-2 GC.Collect() operation"); GC.Collect(2); // force a FULL collection CrashTracing.Trace(5, "GC", "GC.Collect() finished, now waiting for pending finalizers"); GC.WaitForPendingFinalizers(); CrashTracing.Trace(5, "GC", "GC.WaitForPendingFinalizers() finished"); }
The idea is that if the garbage collection was causing the crash, this would surely draw it out faster. And sure enough - three out of four crashes since this change occurred on the line GC.Collect(2);. All the other crashes were during a period of activity where it could be reasonably assumed that an automatic GC collection was triggered (loops with data allocation, etc).
So - now here I am. I am pretty darn sure I have a problem that is causing the garbage collector to crash on either the collection process, or I suppose possibly during the finalization process (since that runs on a background thread, and begins running before Collect() returns). My problem now is that I am at somewhat of a dead end with debugging this. There is no way to step through the GC processes, and there is no event I can attach to that either traps GC errors or that notifies when an automatic Collect is triggered. My best guess is that either a .Dispose() or a finalizer is raising an exception, which is bringing down the whole CLR. But I can't figure out a way to identify the culprit object... which may very well be out of my control (could be a 3rd party or CLR class). The only 3rd party controls being used are a few NetAdvantage UI controls, and the Acrobat Viewer activeX control (the interop assemblies are often not even loaded into memory yet when it crashes - so very doubtful my problem is related to this one).
Has anyone encountered a similar problem, and lived to tell about it?? Has anyone read a post or article by someone else that may have tackled this beast?
Michael lays out a position of why DRM is not evil. To be fair, he makes the disclaimer that these aren't necessarily his views, but he is just presenting an extreme view to drum up discussion. So here is my extreme view on the subject (since I didn't get to participate in Michael and Paul's discussion):
DRM is evil.
It was NOT the will of Bon Jovi that decided the music my wife downloaded from Napster last night should ONLY be played from the EXACT directory it was downloaded to (I got her a iPod clone and a gift card to Napster to get her used to music downloading). It wasn't the actors, director, or camera crew that wanted to force-feed 10 minutes of freaking commercials and trailers in the "unskippable" track of the Riddick DVD I watched the night before last. These things were done by the DISTRIBUTORS of the media. And thats where the problem lies. The distributors hold all the cards, they control all the (realistic) distribution channels. If you want exposure as an artist, you must go through a distributor. Just publishing your own material through the internet is not a substitute for this.
The “just don't buy it if its too restrictive” is not a valid argument. For it to be valid, you would have to be offered a choice. There is not choice here. There is no alternate (legal) channel for me to obtain a Chronicles of Riddick DVD that does not include ten minutes of unskippable commercials.
Not to mention DRM as currently implemented is blatantly illegal according to current copyright law. Why?
- The restrictions placed by all current DRM schemes never expires. Copyright law expressly states that after a period of time, all protected work becomes part of the Public Domain. You cannot buy a DRM-protected media format today that will become “unprotected” and usable in 15 years.
- As an author or artist or publisher, you do NOT have the right to dictate HOW or WHERE media is consumed once you sell it to a consumer... no matter how much you would like to have that control. You only have the right to Sell or to Not Sell it, and to Prevent Unauthorized Redistribution. DRM currently does not really address Unauthorized Redistribution, all it does is hinder the ability of the consumer to use the media as they see fit.
- “fair use” law states that the consumer of published media has the express right to “first sale”. In other words, you can buy a music Album from the original distribution channel and sell it to someone else later... as long as you do not retain any copies of it yourself. Think of “garage sale” here. DRM restrictions do not allow for this.
- “fair use“ also says that the consumer should be allowed to consume the content in private however they wish. Napster preventing my wife from playing a song from her MP3 player, DVD encoding that prevents me from playing a ripped movie on another machine in my home, a PDF that is marked to disable text-to-speech reading,... all of these things fly in the face of “fair use“.
Another problem I have with DRM is the fact that it is really just a tool to prop up market prices. It doesn't really address intellectual/artistic copyrights, but what it does do is prevent individual redistribution. Therefore, the exact same movie can be offered in two countries/markets, for wildly different prices at different introduction dates. A consumer in one market cannot resell (under “first use”) the content to another consumer - simply because of the region locking mechanisms that are a part of DRM. This is definitely not fair market-based capitalism at work.
Monday, December 27, 2004
Posting this entry as more of a “bookmark” reminder to myself than anything... but this information is downright useful.
I have also added Rico Mariani's blog to my reader (the person who authored the above article). Now to go have fun dissecting some troublesome (i.e. “unstable”) code which appears to be going belly-up during GC collections....
Saturday, December 18, 2004
It's almost the beginning of a new year, and I know many corporate budgets are about to get replenished. Projects will be kicking off, and employers will be hiring.
It's also a coincidence that my current contract work is coming to an end. Well, sort of. It's winding down enough to where I can only really call it “part-time”, and therefore I need a more significant source of [steady] work soon.
I am posting this on my blog, as I really do not like going through the job/contract boards, and would prefer to not have to place my resume on them. Besides, “word of mouth” references are almost always better for everyone.
So if you, your employer, or an employer you are familiar with is in need of a solid .NET developer/architect/dba who can hit the ground running and exceed expectations, then please get in touch with me (keith@mindfusioncorp.com). I am always open to contract as well as “w-2” employment, although most of my work in the past six years has been contract consulting. Something in North Atlanta (Cobb or Fulton) would work out best, and yes I am open to infrequent travel. I would even consider relocation if the work sounded really cool.
I am out of town visiting relatives for the holidays, and will not be back until the 27th of December. So if I do not respond quickly, it's because I am stuck in the middle of nowhere (a farm in the center of South Dakota) and do not have access to my email :) I will get back to you once I return to civilization though!
Friday, December 17, 2004
I have been putting it off for a while now, but today I went and took my final certification test needed for MCSD (70-300), and passed. So now thats MCAD, MCDBA, and MCSD. I suppose if I go take one more test I could also get MCSA, but I am not sure if that would be of any benefit given my profession (architect/developer).
Thanks to Eric Engler for sending me the discount voucher number, which saved me 25% of the testing fee. He also took the test today, and passed! So congratulations to Eric as well!
Wednesday, December 15, 2004
I sorta forgot about this until Shawn posted a reminder on his own blog. The next Atlanta Geek / Nerd Dinner is tomorrow night (dec 16). Same place as the last one (Al Azteca on Roswell Rd). See everyone there!
Tuesday, December 14, 2004
Kirk noticed my WSE3 wishlist, and points out that some of the things I ask for actually have already been included in .NET Framework 2.0. Cool beans. I was not aware of these new features before, given that my exposure to VS2005 has been extremely limited so far (not enough hours in the day). I also like that new /serverinterface command-line switch for wsdl.exe... very handy.
So scratch off a few of my requests!
However, I still hope to find serializable SoapExceptions, WSE3 on Compact Framework, message payload schema validation, and automatic resource searching for schemas.
With the new “extendable” wsdl.exe, I hope that the WSE folks can package some prebuilt example SchemaImporterExtension assemblies that are capable of generating SoapClient/SoapServer stubs from an existing WSDL contract. That would go a LONG way towards assisting contract-first development.
Kinda cool. If anyone in Atlanta is playing with one of these, I would love to see some functional demo(s) at our monthly .NET Mobility User Group meetings (yes, I realize the forums are down a lot... just keep trying).
It's a bit too far out of my realm to dig into personally, but I still would like to see what others are doing with this platform. The applications seem limitless really.
Thursday, December 09, 2004
Unless you are living in a cave, you probably already know that Robert Scoble and Shel Israel are doing a book about the impact of blogging in the world of business. This book is currently title “The Red Couch”, after the couch in Scoble's living room where he and Israel hatched this book idea.
I think this is a really cool idea, and I expect to be following along with every step of the book's creation. You see - they aren't just writing a book about blogging... they are writing a book by using blogging. They hope to keep as much in the open as possible, relying on reader comments for a portion of the content. In some ways, it will have more “authors” than any other literature publication. The blog for the book's collaboration is currently being hosted at MSN Spaces, but they might be moving it to a private hosting site in order to enable a few more customizations.
I suppose one could call this “Open-Source Authoring“.
Kirk points out that there is a wish list being collected for WSE3. I had almost forgot about this.
Some things Kirk mentions, which I agree would be a HUGE boon to WSE3:
- Better documentation (just try finding a complete listing of the valid transport strings in WSE2...)
- Whidbey support
- Integrated UI for contract-first development (OMG this would be sweet!)
- SoapService templates in the IDE (similar to current ASMX templates)
But here are some other things I also thing are really worthwhile:
- WSDL generation support in SoapService (I realize this is probably too hard, but I have faith in the WSE team's mo-jo)
- wsdl.exe or similar to support creation of SoapClient proxies!
- Might as well give us an extensible xsd.exe compiler that actually allows us to control the xsd->class mappings (properties versus fields, COLLECTIONS versus arrays, etc). I say this because I doubt the asmx team is going to do this for us.
- Make SoapException support ISerialize! You may ask “why on earth would that be useful?”... well in one specific example, I have a business object that a client application interacts with via Remoting. The business object itself is a proxy to a soap service (Sql Reporting Services to be exact). Guess what happens when the service proxy fails and I dont wrap the SoapException.Message into a generic Exception? Yeah, serializable SoapException would be nice. *maybe this one is not really relevant to WSE team, its more a part of the core framework I think
- WSE3 ON COMPACT FRAMEWORK!!! Most importantly, WS-Security and WS-SecureConversation! I don't care if you have to roll the entire System.Security.Cryptography from OpenCF.org into WSE3 to make this happen. SOA that incorporates mobility devices is just plain GIMPED without this.
- An attribute valid on SoapClient/SoapServer methods marked with [SoapMethod()] to enable xsd schema validation.
- Another cool thing would be if the schema cache locator stuff would automatically search embedded resources while validating a schema. Right now, this must be coded by hand (which really isn't hard, it's just something that would be “handy“).
That's about all I can think of for now..
Wednesday, December 08, 2004
I had already seen a small demo of this at Best Buy recently. I wasn't convinced to buy one by what I saw. But I was certainly still greatly interested.
Then Michael Earls posted about the Digital Joy exhibit over at Perimeter Mall... and I just had to go check it out (again). The folks operating the exhibit really knew how to show it off. I also learned that for how I want to use it, I don't need the more expensive z545... the slightly cheaper z540 will do just fine. Either way, I also would need to buy an x5400 Media Center Extender for each bedroom where I have a TV. I am not even considering the “desktop” variants from HP, nor the offerings from any other manufacturer. I want this to “seem” like a “VCR” type device to visitors in my home (the simpler, the better).
To make a long story short... now I WANT one of these. I want to download movies instead of renting DVDs. I want to download music from iTunes and AllOfMp3.com. I want to pipe streaming internet radio through my stereo. I want my wife to be able to show our wedding video (currently on VHS). I want to have all the features of TiVo throughout my home. I want to be able to store a DVD I own to disk and play it back on any TV and any computer of my choosing. I want to be able to download playlists from the media center to a portable music player / iPod. And other things I want to do with this as well.
Originally, I had planned on replacing my nearly 3 year old “gaming” workstation at the end of this year. However, now I am leaning towards getting a media center machine instead. No, I don't think the media center is capable of playing the stuff I would throw at it well enough (regardless of what the manufacturer claims). Maybe I will just push back the gaming machine purchase to later in the year.
Anyways, this is way cool stuff. And it reminds me... I REALLY need to replace my 10 year old 27” television we keep in the bedroom with a new flat-panel. That purchase is just gonna have to wait though I am afraid.
Tuesday, December 07, 2004
Hopefully Scoble (who knows people at google) or someone who works with Google (such as Adam Bosworth or Joe Beda) will take note of my beef with the new groups site and get something done about it. Apparently scumbag end-users like me just don't have the clout to be heard. Now sure, I could have come across as being less abrasive, but it was 6am after an all-nighter, and cordiality was taking a back seat:
Hi Keith,
Thank you for taking the time to write. Your input is extremely important to us.
As you know, the Google Groups site has been updated with new functionality, notably the ability to create your own group about any topic and invite people to join your discussion group. You can still search and interact with the Usenet newsgroups with which you're familiar, and you can continue to log in with the same email address and password.
While we no longer offer the previous version of Groups, we want to make our new version as user-friendly as possible. If you have specific suggestions or requests, we encourage you to submit a 'Suggestion/Feature Request' at http://groups-beta.google.com/support/bin/request.py. This allows us to easily track which features are most important to Google Groups users. After you click the 'Continue' button, you'll see a screen where you can tell us exactly what improvements you'd like us to make to Google Groups Beta.
We appreciate your assistance.
Regards,
The Google Team
Original Message Follows:
------------------------
From: keith@mindfusioncorp.com
Subject: Please revert back to the old groups site!
Date: Mon, 06 Dec 2004 17:58:23 -0000
This new beta site is horrid! What used to take me minutes to locate now takes hours!
I was up at 6am this morning fixing a bug for a down customer, and I NEEDED the google usenet search to work for me... and it failed me! The discussion thread outline is nowhere to be found. The general format/layout of the posts is extremely confusing... was the designer colorblind?? The higlighting of every other word is painful. The seperation between posts is very hard to make out. It also irks me that I cant see a "# of posts in this thread" link on the main search results...
now I have to click a hundred posts that never got a reply before I find one with useful information!
PLEASE PLEASE PLEASE PUT IT BACK!!!
At least make this version of your groups search site OPTIONAL!! I can't stand it!
This site WAS the most valuable research tool I had. Now it just plain SUCKS!!!
Language: en
Name: Keith Rome
topic: bug
My loose interpretation of the canned reply is “Suck it up loser, we changed it and we dont really care about whether you, the user, approves or disapproves of our arbitrary changes.”.
BTW, The link the reply refers to is the same place I originally submitted my complaint to. “Here, we didn't care what you had to say the first time, but go ahead and submit it again and maybe someone will actually care the second time.”.
Sheesh
Monday, December 06, 2004
We have a C# meeting tonight in Atlanta. However, the two primary facilitators for the group (Michael and Rusty) don't appear to be available lately (Michael is on assignment in SF, Rusty was MIA last month).
I don't see a topic posted on the website, so I am wondering if there even is one planned?
Microsoft is moving within days, are we sure the meeting will be able to be held as scheduled at the concourse building?
Any of you other folks know anything?
Is this thing on? Hello?...
Why on earth would the folks over at google start redirecting users to the beta groups site when you issue a search from the normal one? Perhaps I am overly annoyed given that it is 6am on a monday, and I have not even gotten to bed yet thanks to troubleshooting a bug. And right now, more than ever, I *NEED* the search for groups.google.com to work correctly. But here they have gone and redirected me to a “beta” site which is incredibly confusing and useless.
What on earth are you thinking??!?
[edit:]
45 minutes later and I solved my problem in spite of google. What should have taken me only minutes to find on the usenet search ended up taking hours.
Change it BACK Google. This “new” version is awful!! Why even change it in the first place? It worked great before this.
Friday, December 03, 2004
The real one this time, not a beta, can be downloaded from Microsoft here.
Wednesday, December 01, 2004
I just read a news report that says Microsoft is announcing today “New Communication Service That Enables Blogging, Picture Sharing and More”. MSN Spaces is what they are calling this new service.
“The MSN Spaces beta version is a free service available in 14 languages and 26 markets worldwide. MSN Spaces was designed to make it easy for consumers to create and maintain a personal Web site, bringing the power and benefits of blogging to millions of Internet users, regardless of their level of technical expertise. More than a blogging tool, MSN Spaces is a dynamic online scrapbook where consumers can share photo albums, personal music lists and more. And more than an ordinary personal Web site, through seamless integration with MSN Messenger and MSN Hotmail, MSN Spaces will automatically notify online contacts when a person's Space has been updated so his or her online community knows when it is time to pay a visit. People can sign up for MSN Spaces through MSN Messenger or by going to http://spaces.msn.com. Key features of the service include the following:
- Control your Space. Consumers can choose the people who visit their
Space through three levels of permissions: public, MSN Messenger contacts only or private.
- Use pictures and music to say more. MSN Spaces enable consumers to
easily display their pictures via a photo album slide show. Consumers can easily share playlists through their Space with Microsoft(R) Windows Media(R) technologies. With just two clicks, people can sample or purchase a song on someone's playlist through MSN Music**.
- Create an extension of yourself. Contact Cards - a new addition to MSN
Messenger and Hotmail - are windows into a consumer's Space, mirroring its look and the most recent information posted. MSN Spaces also supports RSS, so consumers can publish their Space to others by way of RSS viewers and aggregators -- including My MSN, coming soon.
- Post remote updates. Consumers can post updates to their Space remotely
via e-mail or a mobile phone.
- Make it your own. Fifteen custom backgrounds and five layout templates
give consumers a way to quickly customize and personalize their Space.“
COOL!
Monday, November 22, 2004
[note: this is WSE2 SP2 *pre-release*... not sure if this is “supported“ or not]
Looks like Web Services Enhancements 2.0, Service Pack 2 is now available. The full download can be reached directly at this link.
Some of the things I find most intersting in this service pack:
“A new implementation of the Kerberos token based on SSPI interfaces is included in this release.“ I know some people were having trouble with Kerberos tokens, hopefully this fixes it.
“The inclusion of unencrypted Username tokens in a message may represent a security vulnerability. The SecurityTokenServiceClient class will now automatically encrypt any Username tokens included in a request. Similarly, the SecurityTokenService class will automatically encrypt any username tokens included in a response.“ One word: NEATO.
“SoapService will now send back an empty SoapEnvelope back if the soap method it is invoking returns null for a request/response scenario.“ This would certainly explain a few weird things.
“The Security Settings Wizard can support creating Policy files for remote service.” Oh gotta try this one out next time I am playing around with policy files.
Hopefully I get the time soon to play with some of this, especially the encryption of UserName tokens. That improvement was sorely needed.
It's 6am and I am still awake, writing a blog entry no doubt. That part is perfectly normal.
Whats not normal is that today is now a monday. And I do not have a User Group meeting of some sort marked on my calender for tonight. I can't recall the last monday night where there wasn't a meeting or event to attend. So I am assuming I missed something important.
Please, clue me in!! What meeting/event did I forget to put on my calender??
I know this cannot be right....
Tuesday, November 16, 2004
Last night was a dual event. We had our first-ever Windows Mobile SIG meeting, and following that many meeting attendees headed to join the “geek dinner” being hosted by Kirk Evans of Microsoft.
I thought the meeting went fairly well, we had roughly 15-20 folks show up. Which isn't bad for a niche group (our C# group is often only half this size, for example). While I was late and missed the introduction talk by Paul Lockwood, I did get to see nearly all of Matt Ranlett's presentation which “covered the bases” of the Compact Framework pretty well. I even snapped a photo using my sweet new Audiovox phone:

Not the clearest picture I know... but come on, it was dark in there!
Saturday, November 13, 2004
No, we do not draw straws to see who will be thrown into the stew. We just get together a bunch of true nerds, and we talk for hours about the stuff geeks care about. Mostly computer-related stuff. And since nerds tend to be rather sedentary creatures, we do this while also feeding our faces!
So if you are in or near Atlanta, enjoy playing the “I know more jargon than you” game, and aren't a complete introvert, then make sure you come to this month's Atlanta Geek Dinner.
Unfortunately, it is being held at the same time as another important event, the first meeting of the Atlanta .NET Mobility Group. This meeting will be over at 8pm and is 5 minutes or less from the geek dinner, so I imagine many people (like me) will just be 2 hours late for the dinner.
Thursday, November 04, 2004
I am finally getting around to conversion of this project to SQL Reporting Services from Crystal Reports 10. I cannot believe I am EXCITED to be working with a reporting engine!
Sure it's still a little rough in some places. But it JUST PLAIN WORKS. I admit I was skeptical once about the ability to integrate with a windows forms application since SRS does not currently provide a winforms viewer control (Crystal has this). Well I am a skeptic no more. In just a few hours tonight I managed to gut and replace nearly all of the “plumbing” I had in place for Crystal Reports, and instead I now just host an ActiveX Acrobat Reader control (which looks IMMENSELY more polished to the end user).
Now I get to convert the handful of reports in this application. I wonder if my enthusiasm will survive that part.
Once this phase is done, I am really looking forward to weening their intranet reporting portal from that abomination known as the Crystal Web Viewer Control. It sure will be nice to be able to view reports on their web site without waiting 5 minutes per view and suffering an outright server crash every hour or so.
Crystal Reports: You deserve to die a merciless death.
Wednesday, November 03, 2004
On monday, November 1, I gave a very hastily prepared presentation on using WSE2 to build service interfaces. I covered contract-first design (using the Visual Studio XSD editor) and alternate protocol support in WSE (SoapServer/SoapClient). I also showed how to divide the code into realistic application layers, including a Service Facade, Service Host(s), Chicken Nuggets (the “pre-existing“ application components), a Client Agent, a Client UI, and a shared service contract (via a shared assembly and XSD). In this presentation, I demonstrated use of both forms of exposing Soap methods, including message-signature based and raw soapenvelope based variations.
In this process, I showed how to build such a design from the ground up, and I tried to touch on most of the common issues that tend to come up. I pointed out the shortcomings of the current XSD compiler, but we also talked about how some of these problems are being addressed in Visual Studio 2005.
Since the presentation, I have done a slight amount of “clean up“ work on the solution's projects. I also incorporated a couple additional topics that were brought up during the presentation.
- During the presentation, the Service Host was demonstrated only as a Console application. I have now added a native Windows Service application to show the benefit of keeping the Service Facade in a seperate assembly.
- During the presentation, the question was posed about Schema validation, and could it be done in this context? To demonstrate how to achieve this easily, I have included new code that embeds the XSD into the shared assembly, and uses it at runtime to validate incoming messages.
The complete code (and binaries) for all projects in this solution can be found here:
SOA.zip (180.45 KB)
A couple notes before running these samples:
- The service implementation reads data from the “pubs” database on a local SQL Server instance. The connection string for this is hardcoded, and will need to be modified if you do not have SQL Server installed locally. You will need to ensure that the account running the ServiceConsole and/or the WindowsService (SYSTEM by default) has read access to this database. (Yes, I know this is bad but this part of the project was out of the scope of the presentation)
- To install the WindowsService (which allows you to see it in the “Services” control panel applet), you will need to run “installutil” to register it properly. From the Visual Studio Command Prompt, type “installutil -?” to see how to use this utility.
Saturday, October 30, 2004
Sometimes the simplest things can be the coolest. I just stumbled onto this today, I cannot believe I did not know about it before (or if I did, I had forgotten).
In C#, in addition to simply importing a namespace into a code file (“using” directive), you can also define an alias for it. Why is this cool?
A hypothetical project uses assemblies from two vendors. For argument's sake lets say the two vendors are just seperate departments in your organization. Both departments maintain their own business object classes, in their own namespaces:
namespace MyCompany.Accounting.BusinessClasses {...}
and
namespace MyCompany.Shipping.GlobalDataClasses.Core {...}
Now, it doesn't really matter what the actual namespaces are for this discussion, just that they are a pain in the ass to type, and they both contain a class of the same name (”Company” in this example).
Now, supposing we work for the Accounting department and we are asked to write a peice of code that can find and update a corresponding Shipping account record when someone in Accounting saves a change on our side. We would likely end up with something like this...
using MyCompany.Accounting.BusinessClasses; using MyCompany.Shipping.GlobalDataClasses.Core; <...> MyCompany.Accounting.BusinessClasses.Company Destination = MyCompany.Accounting.BusinessClasses.Company.FindCompany(company_id);
MyCompany.Shipping.GlobalDataClasses.Core.Company Source = new MyCompany.Shipping.GlobalDataClasses.Core.Company(company_id); <... do some stuff with both objects ...>
Now that's enough verbosity to make the baby Jesus cry! Having to inline those namespaces in the code makes it VERY painful to read, and the only reason we have to do it is because otherwise the type name “Company” would be too ambiguous.
Well, Namespace Aliases gives us a way to “pretty up” this code. We can assign an alias to each namespace import, which can then be used in the code as an abbreviation:
using Acct=MyCompany.Accounting.BusinessClasses; using Ship=MyCompany.Shipping.GlobalDataClasses.Core; <...> Acct.Company Destination = Acct.Company.FindCompany(company_id); Ship.Company Source = new Ship.Company(company_id); <... do some stuff with both objects ...>
Fantastic!
One other thing to mention is that when you alias a namespace like this, you can no longer directly reference classes from that namespace without a qualifier. For example:
using Data=System.Data; <...> DataSet MyDataSet1 = new DataSet(); // <-- this will not work when System.Data is aliased! Data.DataSet MyDataSet2 = new Data.DataSet(); // <-- this will work
What you can do to fix this is to import the namespace twice. Once using the alias, and once without an alias. This gives us the best of both worlds:
using Data=System.Data; using System.Data; <...> DataSet MyDataSet1 = new DataSet(); // <-- this will work now! Data.DataSet MyDataSet2 = new Data.DataSet(); // <-- this will still work
Cool stuff!!! I love learning new simple language features I should have known about 2 years ago!!
Friday, October 22, 2004
OK, I will most likely regret this post at a later time, but oh well...
Is it just me, or do others become more productive with coding after a few brewskies? Here it is 1:15 AM, I just polished off over half a bottle of wine, and I feel like I could knock out a ream of bugs/changes. I have already done more work in the last 2 hours while drinking than all of the previous day while sober. And I feel like I am just getting started.
What's up with that?
Too bad most employers wouldn't agree to supplying a few beers during work hours to boost productivity.
Thursday, October 21, 2004
I usually do not get excited about reporting engines. In fact, I generally detest them.
But today I got a call from my last active client who is still using Crystal Reports, and they just approved the migration over to SQL Reporting Services. I am thrilled. I cannot wait to get that Crystal garbage out of their applications.
I never thought I would be happy to be rebuilding reports, but here I am... eager to get started on that process. Just have to wait until I get a couple other minor modifications completed first...
FAQ: When do I use Remoting and when do I use WSE/ASMX?
Rockford Lhotka does a great job explaining how to go about making this decision. The only thing I would add is that in large enterprise systems, the boundaries bewteen subsystems should also be considered as a good candidate for message-based interfacing like WSE.
Tuesday, October 19, 2004
I had an email exchange today on the topic of O/R mappers and model-driven code-blowers and related discussion. The topic seems to resurface often enough at user groups (and the “pub meetings” that often follow) to merit jotting down my personal position on it here. While I am certainly not the definative expert here, I feel I have “been there, done that“ enough to formulate a fairly defensible and reasonable opinion of the matter.
This discussion in particular was triggered when a friend of mine sent me a link to this free code-blower engine from a Microsoftie in France: http://www.microsoft.com/france/msdn/olymars
***Please note that I in no way endorse or discredit any way of designing a DAL, or any product (free or otherwise) that may be used to such an end...
-------------------
My observations:
There are 4 basic camps of folks, each sure they are right and all others are wrong.
Camp 1) O/R Mapping is better than sliced bread. Everyone needs to use it. There is nothing wrong with basing business processing components on ORM-aware components.
Camp 2) O/R Mapping is the devil. Code-blowing is the answer. Kill all the ORM people. Business components should be based on the metadata-driven basic entity components, extending their raw data storage capability (the generated part) with program logic (generally using OOP inheritance).
Camp 3) ORM and Code-blowing are both silly wastes of time. Just slam all your data access code together with your business processing and be done with it. If it's a web site, then just pack it all into the page code too if you are “smart“ enough to be able to work with it.
Camp 4) Use ORM -or- Code-blowing to build a “problem domain-specific” data-access interface. Keep it seperate from your business processing, making calls back from the business code through the data-access interface.
O/R Mapping is sometimes referred to as "object-driven database design". Code-blowing is often referred to as "model-driven object design". Each having their own merits and shortcomings.
Camps 1 and 2 are quite similar, they focus too much on the fine-grained detail in lieue of the greater picture. They can't see the forest for the trees, and end up re-inventing the forest for nearly every project.
Camp 3 folks tend to also strongly support the "Agile/extreme Development" way of building systems. They like to fly by the seat of their pants.
Camp 4 tends to be where people eventually gravitate towards, given enough experience with the other 3 methods. I myself started out in Camp 3, briefly tried Camp 1, and recently spent a good bit of time in Camp 2. I now feel Camp 4 offers the best flexibility and meets business needs better.
I really don't want to give a hoot whether my DAL is using ORM or metadata-driven semantics. All I care about is that -something- is taking care of sending the data to the correct place in the database, and as long as my interface to that mechanism meets the business needs at hand, its irrelevant what technology handles it from there.
In the end, I currently favor using ORM or Code-blowing (or some other form of automation) to assist in construction of a strongly-typed per-application/service data interface, and then making calls to this interface from the business components. They should not care about the intricacies of database manipulation, nor should they care how such manipulation is being performed (ORM, etc). As long as the business component can request “field A“ in “table B“ be assigned a “value X“, it does not matter if the work is being done with O/R mapping, standardized stored procedures, ad-hoc SQL, or any other mechanism. All those concerns have zero business value in the end, and only serve to get in the way of solving business problems.
Michael Zalewski started feeding randomly malformed HTML into Microsoft Internet Explorer, Mozilla, Opera, Lynx, and Links and watching what happened. Bottom line: 'All browsers but Microsoft Internet Explorer kept crashing on a regular basis due to NULL pointer references, memory corruption, buffer overflows, sometimes memory exhaustion; taking several minutes on average to encounter a tag they couldn't parse.'
http://slashdot.org/article.pl?sid=04/10/19/0236213
Saturday, October 09, 2004
I get asked this question a lot, although sometimes what people are really asking is "What does it mean to be a contractor".
Tuesday, October 05, 2004
I read a recent post from Ted Neward that implied perhaps we are taking the Ws-* suite of specifications too far. Specifically, the question of: “at the end of the day, are we really just reinventing TCP/IP?“
I thought about this question today, and my conclusion is that Yes, in a way, we are. But it is not over the top. We are reinventing the routability nature of TCP/IP addressing. We are also reinventing the addressibility of DNS (which is essentially a redirection layer on top of tcp/ip).
However, this reinvention is indeed necessary in the new scheme of things. You see, TCP/IP and DNS were designed for a world in which always-connected and seldom-rerouted data channels were the norm. Everything was point-to-point, the network infrastructure was expected to maintain this for us. We have since learned through trial-and-error that 1) we cannot depend on the infrastucture, and 2) we need adaptability in the infrastructure. Basic Tcp/Ip and DNS do not accomodate those very well. And this is why we need the additional layers of WS-Addressing, and other related WS-* in a SO world.
I should also point out that the new “infrastructure“ WS specs (routing, addressing, etc) are not necessarily tied to hardware tcp/ip stacks. Sure, right now this is our standard mode of transport, but it does not have to be. This is a good thing as it does not force us to rely on tcp/ip networking forever. What if the next generation networking platform does not even use tcp/ip? It's not that far-fetched... after all, tcp/ip was not always the king of networking protocols.. and many network systems do not do tcp/ip natively (they just imitate it). ATM, wireless, cellular, these all use cell-based protocols which are better suited for larger payloads than tcp/ip, and they just let tcp/ip piggyback on top in order to provide interoperability with the internet at large. Hmm... high efficiency/speed ATM SOAP routing... thats an interesting possibility...
It seems a lot of folks have been questioning these particular peices of the WS specs lately. I hope they start to realize that these are very important in the grand scheme of what it means to build SOA systems.
The days of being able to segment a data packet into chunks and only sending along the destination IP in the header (which in a nutshell is all tcp/ip does) are over. System interfaces have matured beyond that simplistic model, and now its about time our messaging infrastructure matured beyond it as well.
Viva la WS stack.
At least until the next great layer of data routing is invented...
Thursday, September 30, 2004
reading between the lines, I can take an educated guess about when we can see a first tangible beta.
Wednesday, September 29, 2004
The security vulnerability I blogged about on 9/14 is finally becoming widespread on the internet.
Tuesday, September 14, 2004
Essentially, a buffer overrun has been found that allows a malformed JPEG image to execute code.
Friday, September 10, 2004
Shame on you SP2 for blocking port 80 on my development machine ninja-style!
SP1 seems to disable the StateServer service.
Thursday, September 09, 2004
We have MCAD, MCDBA, MCSE, MCSD... where is the MCA certification?
Friday, September 03, 2004
After procrastinating for over a year, I finally got around to setting up a weblog...
|
On this page....
| Asynchronous UI in WPF and Silverlight (and Windows Forms too) |
| Excellent Free Sound Effects Resource |
| A Simple Sound Effects Engine for Silverlight 2 |
| Gem Blaster entered into "RIA Run" contest |
| Gem Blaster updated and enhanced for Silverlight 2 |
| Awesome tool for Media Center - Lifextender |
| Atlanta Code Camp 2008 |
| Speaking at the Atlanta Cutting Edge / Atlanta MS Professionals Tomorrow |
| Heading to MIX this year |
| Slides and Code from Alabama Code Camp 6 |
| Source Code for Gem Blaster finally published to CodePlex |
| PolyGraph3D: Making 3D happen with Silverlight 1.0! |
| Rest In Peace, 99x |
| Attached Properties in Silverlight |
| Performing Seek operations in Silverlight on a MediaElement |
| Silverlight Bug: MediaElements will restart if their containment lineage changes |
| Silverlight Bug: Using a packaged image source for multiple Image elements |
| The Atlanta .NET Doubleheader: Visual Studio 2008 Loadfest and XBox Gaming Night |
| Multi-selection of files in Explorer (Vista) |
| 10 interview tips that will help you land a better job |
| How to Botch an Interview and Ensure that you will Never get an offer |
| Expression Design Service Pack 1 |
| Win a free pass to Devscovery 2008! |
| Where have I been? |
| No user group meeting Monday night |
| Speaking in Charlotte tonight |
| Blend 2 August CTP Refresh |
| AirportWait (Silverlight Demo) |
| SilverLife (Silverlight Demo) posted |
| MVP Award - C# |
| Popper! |
| Quick Tip - Input Controls in Silverlight |
| Atlanta Geek Dinner |
| Atlanta Cutting Edge .NET - May 2007 |
| A storm is brewing |
| Expression tools for MSDN Subscribers and Partners |
| Alabama .NET Code Camp |
| Longest Posts EVAR |
| Atlanta Cutting Edge .NET User Group Meeting - Monday March 5th |
| New Job |
| Windows Live Search for Mobile |
| Project Planning Basics |
| Tagged by Brendon |
| Team Leadership |
| Adventures in Databinding ~ Part 2 ~ Simple versus Complex Binding |
| Adventures in Databinding |
| Crawling back out of my cave |
| 2007 Atlanta Code Camp - Registration is OPEN |
| Fun with Vista |
| Microsoft Lunch and Learn |
| MCPD - EAD |
| Atlanta Cutting Edge .NET - September 2006 |
| Back Online |
| Windows Live Writer |
| CANCELLED: Atlanta C# User Group Meeting for June 2006 |
| More progress on my new house |
| 2006 Atlanta Code Camp |
| Underwater |
| Amazing how fast a house can be built nowadays... |
| Quick catch up... |
| Unit testing and Test Driven Development |
| Neglect |
| Atlanta MS Professionals UG |
| Messenger Live Beta Invitations |
| Adding a Google or MSDN2 search to VS2005 |
| Planning pays off |
| Diggin Firefly |
| PageFlakes |
| New Hosting Provider |
| Interested in AJAX? |
| Weird HTTP header issue in Internet Explorer 6 |
| Developer Wisdom |
| Gematriculated |
| A peek into the future of managed OS's |
| Much h8 for VB |
| VMWare Player |
| C# UG Presentation: Engineering an Application Foundation using Code Generation |
| C# UG Presentation: Custom Exceptions |
| More FREE Sharepoint Training! |
| Nerd Dinners |
| WSS SP2 available now |
| SharePoint v3 video |
| More on Sharepoint SP2 |
| Cool Sharepoint News |
| FREE Sharepoint Training |
| Good security article |
| What is going on here?? |
| Katrina |
| Code Camps are everywhere! |
| First Sharepoint 123! training session a resounding success! |
| IASA Atlanta Chapter Impressions |
| Designing a Service, Part 2 |
| Designing a Service, Part 1 |
| 8/1 C# Users Group Meeting |
| War of the Worlds |
| FREE Sharepoint training - coming to Atlanta |
| Atlanta Enterprise Architecture Group |
| Cool Blackberry Download |
| VS 2005 b2 VPC |
| VB's default 1-based arrays are stoopid |
| A Pig in Slop |
| Eh, does anyone else bother with transactional integrity these days? |
| Interested in SharePoint and other portal technologies? |
| Furious with Cingular / AT&T Wireless |
| The shallowing |
| A Minor Change |
| The Media Center (in)Experience |
| Book Review: "Microsoft BizTalk Server 2004 Unleashed" |
| Team System Licensing finally recognizes the Big Little Company |
| Atlanta Code Camp is upon us! |
| Protecting Assets |
| Book Review: "The Evelyn Wood Seven-Day Speed Reading and Learning Program" |
| Book Review: "Cascading Style Sheets: Separating Content From Presentation" |
| Refactor! |
| Book Reviews |
| Cell-phone location tracking |
| Linguistic Profile |
| An Update on our next C# meeting |
| Decisions, Decisions... |
| CLR Team visiting Atlanta in May! |
| Async Programming Presentation Slides and Source Code |
| Talk about a brain fart! |
| Gah! |
| If you want Master Pages to be useful in ASP.NET 2.0 |
| Getting a better handle on CSS |
| Thanks Michael! |
| Green Screens |
| Brief outage |
| IBM, why must thou suck so much? |
| How many times? |
| Enterprise Architecture Focus Group |
| SOA Misunderstanding and Misuse |
| DB2 - what a peice of work |
| Help me choose a topic for Code Camp |
| Back in action |
| So how did YOU spend your Friday night? |
| Cool stuff in SQL 2005 |
| Oh dear.... |
| Geek Dinner tonight |
| NVEdit Downloads available now |
| Atlanta Motorcycle Show |
| Framework source code |
| Upcoming Atlanta C# User Group presentation |
| I have much <3 for microsoft |
| More on CAPTCHA |
| That didn't take long: CAPTCHA is irrelevant |
| OK RSS Bandit is starting to grate on my nerves |
| Add three more WS acronyms to your vocabulary |
| New application blocks coming |
| Volkswagon parody ad |
| "library not registered" when creating new c# project item or project |
| Atlanta .NET Book Club |
| Cool amateur-processed Titan images |
| dasBlog version 1.7 |
| Florida Code Camp |
| More garbage collector woes |
| The new Mac Mini |
| Interested in building your own Media Center Edition machine? |
| Portable Media Center competition |
| Wanna see what Bill G has to say about Media Center PCs? |
| Old Media |
| New phone devices coming from Samsung |
| Tips and Tricks: String.Intern() |
| Geek dinner attendance |
| Taking the trash out... |
| DRM *IS* evil |
| Finding (and fixing) memory leaks in .NET code |
| Solicitation for work |
| MCSD finally |
| December Atlanta Nerd Dinner |
| My WSE3 wishlist Revisited |
| Dot Net on a Stick? |
| The Red Couch |
| WSE wish list |
| Windows Media Center Edition |
| Google replies to my "bug report" on their new craptacular version of groups.google.com |
| C# meeting tonight |
| Google, you suck |
| WSE2 SP2 released |
| MSN to start offering a hosted blogging service |
| WSE2 SP2 is out today |
| Something's wrong |
| Windows Mobile SIG First Meeting |
| Local Atlanta "geek dinner" |
| SRS is FANTASTIC |
| WSE2 Presentation Files |
| The power of blogging |
| Namespace Aliases in C# |
| CWI (coding while intoxicated)? |
| Woohoo! Kiss my fanny, Crystal Reports! |
| When to use Remoting? When to use WSE? |
| O/R Mapping and all that jazz |
| IE is not as bad as some folks would have you believe |
| What it means to be a consultant (or a contractor) |
| On WS-* and is the industry really going overboard? |
| Indigo beta 1 |
| Exploits of the recent JPEG exploit now spreading. |
| Pretty important security patch for 2003 server, XP, and basically all other microsoft products |
| Damn you XP SP2!! |
| WARNING: Microsoft .NET Framework 1.1 Service Pack 1 and session StateServer |
| MS Certification for Architects? |
| It is alive! |
Archives
| April, 2009 (1) |
| June, 2008 (3) |
| May, 2008 (1) |
| April, 2008 (1) |
| March, 2008 (2) |
| February, 2008 (3) |
| January, 2008 (6) |
| December, 2007 (2) |
| November, 2007 (2) |
| October, 2007 (5) |
| September, 2007 (1) |
| August, 2007 (4) |
| July, 2007 (3) |
| June, 2007 (1) |
| May, 2007 (3) |
| April, 2007 (3) |
| March, 2007 (3) |
| February, 2007 (3) |
| January, 2007 (6) |
| November, 2006 (3) |
| September, 2006 (1) |
| August, 2006 (2) |
| May, 2006 (2) |
| April, 2006 (2) |
| March, 2006 (2) |
| February, 2006 (4) |
| January, 2006 (4) |
| December, 2005 (3) |
| November, 2005 (4) |
| October, 2005 (5) |
| September, 2005 (8) |
| August, 2005 (6) |
| July, 2005 (10) |
| June, 2005 (2) |
| May, 2005 (6) |
| April, 2005 (12) |
| March, 2005 (8) |
| February, 2005 (12) |
| January, 2005 (19) |
| December, 2004 (17) |
| November, 2004 (9) |
| October, 2004 (8) |
| September, 2004 (9) |
| |
Navigation
Categories
About
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Sign In
|