Holiday Greetings:

I recently received the below Holiday Greeting from a compatriot, and decided to post it. No explanation should be needed:

Dear XXX:

With the holidays fast approaching and EULAs pretty much a fact of life, please accept -- with no obligation, implied or implicit, on behalf of the wisher or wishee -- my best wishes for an environmentally-conscious, socially-responsible, low-stress, non-addictive, gender-neutral celebration of the winter solstice, practiced within the traditions and/or within the religious or secular belief(s) of your choice and with respect for the traditions and/or religious or secular beliefs of others or for their choice to not practice traditions and/or religious or secular beliefs at all; and for a fiscally-successful, personally-fulfilling, medically-uncomplicated recognition of the onset of what is generally accepted as the new Gregorian calendar year, but with due respect for calendars of other cultures whose contributions to society have helped make America great*, and without regard to the race, creed, color, age, physical ability, sexual orientation, political affiliation, or choice of computer operating system of the wisher.


By accepting this greeting you are accepting the terms of the greeting and all responsibility associated with it. This greeting is subject to clarification and/or revocation at any time at the discretion of the wisher. This greeting is non-transferable without the express written consent of the wisher. It implies no promise by the wisher to actually implement any of the wishes for him/herself or for others. This greeting is warranted to perform as expected within the usual application of good tidings for a period of one year or until the issuance of a subsequent holiday greeting, whichever comes first. Warranty is limited to replacement of this greeting or issuance of a new greeting at the sole discretion of the wisher, who assumes no responsibility for any unintended emotional stress this greeting may bring to those not caught up in the holiday spirit.

By accepting this greeting you agree to subscribe to annual updates at a cost completely arbitrary to the wisher at the time of renewal. Failure to subscribe - in effect, failure to renew this greeting - will result in forfeiture of the original greeting, loss of your parents' homes, euthanasia for your and your neighbors' pets, and prosecution in a kangaroo court of law comprised of the wisher's closest friends and paid business associates, convened by the wisher at a location deemed most inconvenient to you. Reading of this disclaimer constitutes your acceptance of the greeting. Oh, and I almost forgot...this disclaimer supersedes all local, state and federal laws previously enacted to prevent such disclaimers from superseding all local, state and federal laws.

* -- This does not imply that the United States of America is necessarily greater than any other country, or that it is the only America in the western and/or eastern hemispheres.


ASP.NET v1.1 Member Management Component Prototype




Server 2003 SP1 Release Candidate available NOW!

Here it is!


Need to Get A HEAD?

This nice little piece was recently posted by David Kline on his blog:

Have you ever wanted to know what type of file was being pointed to by a given url before clicking the link?  Maybe you are writing an application that needs to filter out certain types of links.  A web crawler is a good example of an application which needs to do such link filtering (skip links to graphics, audio, zip files, etc).

In order to check the type of data pointed to by a url, you are going to need to issue a request to the server.  Normally, this involves receiving the entire page or file at that location.  This can be a time consuming proposition, especially over slow network connections, and defeats the purpose of allowing your application to filter out undesired links.

The solution is to issue a request to the server, asking only for the HTTP headers.  This "HEAD" request is small, fast (does not transfer file contents) and provides you with exactly the data your application needs.  While there are plenty of interesting headers, the header we are interested in today is "Content-type".

Below is a simple console application that takes a url path and displays the value of the content-type header.  Please note: To keep this example as small as possible, only minimal error checking is performed - any real-world implementation would need to do much more than what I show here.

using System;
using System.Net;

class ContentType
    public static void Main(String[] args)
        if(args.Length != 1)
            Console.WriteLine("Please specify a url path.");

        // display the content type for the url
        String url = args[0]; 
        Console.WriteLine(String.Format("Url : {0}", url));
        Console.WriteLine(String.Format("Type: {0}", GetContentType(url)));

    private static String GetContentType(String url)
        HttpWebResponse response = null;
        String contentType = "";

            // create the request
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            // instruct the server to return headers only
            request.Method = "HEAD";

            // make the connection
            response = request.GetResponse() as HttpWebResponse;

            // read the headers
            WebHeaderCollection headers = response.Headers;

            // get the content type
            contentType = headers["Content-type"];
        catch(WebException e)
            // we encountered a problem making the request
            //  (server unavailable (404), unauthorized (401), etc)
            response = e.Response as HttpWebResponse;

            // return the message from the exception
            contentType = e.Message;
            // this will be caught if WebRequest.Create encounters a uri
            //  that it does not support (ex: mailto)

            // return a friendly error message
            contentType = "Unsupported Uri";
            // the url is not a valid uri
            // return a friendly error message
            contentType = "Malformed Uri";
            // make sure the response gets closed
            //  this avoids leaking connections
            if(response != null)

        return contentType;

The above code can be compiled and run on either the .NET Framework or the .NET Compact Framework.

Here's a sampling of the content types I received when running the above application against a handful of urls:

text/html; charset=utf-8

-- DK

This posting is provided "AS IS" with no warranties, and confers no rights.

[Microsoft WebBlogs]


Web Services Enhancements 2.0 SP2 (WSE 2.0 SP2) Released today

This release fixes some top customer issues and provide a new security token, KerberosToken2, which supports impersonation, windows constrained delegation.  The new token also works well with the web farm scenario.

Download WSE2 SP2 from


IsNumeric in C#? Not!

Recently we had another "go around" at the office regarding IsNumeric in C#. We had a forum discussion on this at eggheadcafe.com some time ago, I suggested to use the Microsoft.VisualBasic.Information.IsNumeric method, which can certainly be called from C# or any other .NET language.

Two other developers, both of whom I highly respect, have gone quite a bit deeper into this; J. Ambrose Little here and Justin Rogers here. Only Rogers actually made reference to the fact that the VisualBasic method does a significant amount of type-checking under the hood; type-checking that was not included in either of their test suites. The bottom line is this:
If I put "$1,079.51" into Ambrose's VisualBasic method, it returns true, because that string, indeed, "IS" numeric. Other methods tried will either incorrectly return false, or will actually hang and not return at all. According to the Microsoft definition of "Numeric", depending on the CultureInfo, any valid Currency sign or thousands / decimal delimiter in the correct position in a string of numbers
should be able to be handled by the method.

My point is, comparative test suites designed to illustrate performance are only valid when comparing apples to apples. If the test methodology or assumptions are initially flawed, their validity goes down the toilet, IMHO. Developers who aren't aware of all these little nuances may very well read one of these blogs/articles and proceed to create their own "IsNumeric" method in C# that uses char.IsDigit and other techniques for speed. And when they ship a French version of their app to a client, it may very well blow up. So, the question is, if you are a C# purist, you could spend a very long time writing your own method and never calling into the Microsoft.VisualBasic.dll assembly. But, since you would have to do all the very same things done in the decompiled code below in order for it to be "right", it might end up not being any faster at all!

ISNUMERIC - decompiled to C# (Not all methods used are shown):

public static bool IsNumeric(object Expression)


bool flag1;
IConvertible convertible1 = null;
if (Expression is IConvertible)
convertible1 = (IConvertible) Expression;

if (convertible1 == null)
if (Expression is char[])
Expression = new string((char[]) Expression);
return false;

TypeCode code1 = convertible1.GetTypeCode();

if ((code1 != TypeCode.String) && (code1 != TypeCode.Char))
return Utils.IsNumericTypeCode(code1);

string text1 = convertible1.ToString(null);

long num2;
if (!StringType.IsHexOrOctValue(text1, ref num2))
double num1;
return DoubleType.TryParse(text1, ref num1);
flag1 = true;
catch (Exception)
flag1 = false;
return flag1;

internal static bool IsNumericTypeCode(TypeCode TypCode)
switch (TypCode)
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
return false;

internal static bool TryParse(string Value, ref double Result)
bool flag1;
CultureInfo info1 = Utils.GetCultureInfo();
NumberFormatInfo info3 = info1.NumberFormat;
NumberFormatInfo info2 = DecimalType.GetNormalizedNumberFormat(info3);
Value = StringType.ToHalfwidthNumbers(Value, info1);
if (info3 == info2)
return double.TryParse(Value, NumberStyles.Any, info2, out Result);

Result = double.Parse(Value, NumberStyles.Any, info2);
flag1 = true;

catch (FormatException)
flag1 = double.TryParse(Value, NumberStyles.Any, info3, out Result);
catch (Exception)
flag1 = false;
return flag1;

internal static CultureInfo GetCultureInfo()
return Thread.CurrentThread.CurrentCulture;

internal static NumberFormatInfo GetNormalizedNumberFormat(NumberFormatInfo InNumberFormat)
NumberFormatInfo info2;
NumberFormatInfo info5 = InNumberFormat;
if (((((info5.CurrencyDecimalSeparator != null) && (info5.NumberDecimalSeparator != null)) && ((info5.CurrencyGroupSeparator != null) && (info5.NumberGroupSeparator != null))) && (((info5.CurrencyDecimalSeparator.Length == 1) && (info5.NumberDecimalSeparator.Length == 1)) && ((info5.CurrencyGroupSeparator.Length == 1) && (info5.NumberGroupSeparator.Length == 1)))) && (((info5.CurrencyDecimalSeparator[0] == info5.NumberDecimalSeparator[0]) && (info5.CurrencyGroupSeparator[0] == info5.NumberGroupSeparator[0])) && (info5.CurrencyDecimalDigits == info5.NumberDecimalDigits)))
return InNumberFormat;
info5 = null;
NumberFormatInfo info4 = InNumberFormat;
if ((((info4.CurrencyDecimalSeparator != null) && (info4.NumberDecimalSeparator != null)) && ((info4.CurrencyDecimalSeparator.Length == info4.NumberDecimalSeparator.Length) && (info4.CurrencyGroupSeparator != null))) && ((info4.NumberGroupSeparator != null) && (info4.CurrencyGroupSeparator.Length == info4.NumberGroupSeparator.Length)))
int num3 = info4.CurrencyDecimalSeparator.Length - 1;
int num1 = 0;
while (num1 <= num3)
if (info4.CurrencyDecimalSeparator[num1] != info4.NumberDecimalSeparator[num1])
goto Label_019D;
int num2 = info4.CurrencyGroupSeparator.Length - 1;
for (num1 = 0; num1 <= num2; num1++)
if (info4.CurrencyGroupSeparator[num1] != info4.NumberGroupSeparator[num1])
goto Label_019D;
return InNumberFormat;
info4 = null;
info2 = (NumberFormatInfo) InNumberFormat.Clone();
NumberFormatInfo info3 = info2;
info3.CurrencyDecimalSeparator = info3.NumberDecimalSeparator;
info3.CurrencyGroupSeparator = info3.NumberGroupSeparator;
info3.CurrencyDecimalDigits = info3.NumberDecimalDigits;
info3 = null;
return info2;


MSMQ 3.0 and Multicast

Amazing what you can learn when you RTFM, ya know? From the Message Queueing in Windowx XP: New Features:

MSMQ 3.0 in Windows XP extends the regular MSMQ programming model from one-to-one to one-to-many. The traditional MSMQ model allows a single message to be sent to a single queue. However, the one-to-many messaging model enables clients to send the same message to multiple recipient queues. MSMQ 3.0 offers multiple ways to implement this model:
" Real-time messaging multicast
" Distribution lists and multiple-element format names

In MSMQ 3.0, one-to-many mechanisms provide the application developer with the fundamental tools required to build sophisticated publish and subscribe systems. These kinds of systems are useful for addressing reliable information dissemination scenarios.
Real-Time Messaging Multicast
MSMQ 3.0 provides a mechanism to send messages on top of IP multicast.
Specifically, MSMQ 3.0 uses the Pragmatic General Multicast (PGM) protocol (see http://www.ietf.org/internet-drafts/draft-speakman-pgm-spec-06.txt), which is becoming the de facto enterprise standard for obtaining a degree of reliability on top of IP multicast.

In MSMQ 3.0, when an application sends a real-time multicast message, a single copy of the message is sent on the network, but this message can then be received and processed by numerous destination applications. This method is extremely efficient if the same message has to be delivered to a huge number of receiving applications.

Real-time multicast messaging supports only an "at-most-once" quality of service. In particular, it does not support transactional sending. To send a real-time multicast message, the existing Send API has been extended so that the sender can specify a target IP multicast address. The receiver's programming model is not affected at all. An IP multicast address property can be attached to a queue, and subsequently every message sent to that multicast address will be inserted into the queue by MSMQ 3.0. Applications continue to read messages from the queue using standard MSMQ APIs and methods.

From a security point of view, standard MSMQ authorization and authentication continue to be available, but MSMQ 3.0 does not provide specific encryption or decryption for real-time multicast message.

Sounds like the Spammer's Full Employment Act to me!

And here is a performance issue I didn't know before:

Use Windows Security Sparingly

MSMQ uses the standard Windows security model. You can configure queues to permit only senders and receivers with appropriate security privileges. The tradeoff for including Windows security in messaging is that it takes about 2.5 times as long to send the same messages. By configuring MSMQ not to send the security descriptors associated with the sending application, you can obtain significant performance gains. To configure MSMQ not to send a security descriptor with the message, set the message property AttachSenderID to False (the default is True):



Another Believer! (EXEC sp_name param, 'param') -Not!

Vis-a-vis my last number on why not to use "Exec spname paramvalue" etc. -- my friend figured out that all the places he was doing new SqlDataAdapter("exec mysp 1,5 'hello'"); are open to SQL injection attack (he thought they were immune to it). Why? Simple- if an attacker can get access to the SQL string they can just add ";DELETE TABLENAME". DOH!

So now he is happily rewriting everything to use SqlHelper and turning all those inline text strings into object[] parms={1,5,'hello'}; object arrays.

You see that? You are only dumb when you think you know everything....


ADO.NET and SQL Server Optimization

Recently a compatriot and I got into this diatribe over the use of CommandType.Text and "EXEC spName param, param, ..." to make SQL Server stored procedure calls.
I had chimed in on his answer to a poster who was having difficulty with a sproc call, and he suggested "you don't need to use the Command Object" and proceeded to show an illustration like the above.

Even after I had provided some pretty good background material on why this is not a good idea, he continued to hammer on little pieces of the subject, in effect missing the big picture. There have been many times I've been corrected. As I've grown older (and hopefully wiser) I've learned to put my ego in my back pocket and thank the person for the education. And you? I guess what I am trying to say is this; you have two MVPs who didn't know about this. The only reason I found out about it is because I was lucky enough to attend Tech-Ed 2004 and sit in Gert Drapers' presentation. So if two C# MVP's weren't aware of it, how many other people do you suppose are writing whole applications using Language Event processing instead of RPC Event processing as they should?

The bottom line is, you should never use CommandType.Text and concatenated "EXEC SPNAME PARM PARM" convention. In fact, even if you are not using stored procedures at all - you should parameterize your text queries - because the SQL Server engine is smart enough to "Template-ize" them - and cache the compiled execution path for re-use. What I posted was Gert Drapers' PowerPoint Presentation to illustrate. Gert Drapers, for those who don't know, is a Software Architect in the SQL Server Development group at Microsoft. He is involved in the architecture design and performance tuning of the most challenging applications and large-scale database deployments around the world; worked on both SQL Server 7.0 and 2000; first as Software Design Engineer in the SQL Server Storage Engine and later as the Product Unit Manager of the SQL Server Management Tools team and as Architect of SQL Server DTS. So, he certainly has the credentials, IMHO.

CommandType.Text = Language Event
You should not execute stored procs using CommandType.Text , that's what your "EXEC spName param param" example is doing.

You should use RPC Event for All procedure invocations
"CommandType.StoredProcedure" and add the correct SqlParameter objects to the Command.

There are numerous reasons to do this, many are illustrated in the downloadable Powerpoint Presentation, which you are welcome (and encouraged) to view.

Here are some of the notes (slightly edited) that I took of Mr. Drapers' presentation at Tech-Ed 2004:

First, we need to make a decision which command type to use. It is NOT a convenience issue. From a server persepective, there is a significant difference.:

IN SQL Server you have language events, and RPC events, This is a split code path. In other words, If you want to run a stored procedure, you want to be sure that you both start and end inside the RPC Event source code path. You do this by explicitly setting commandType.StoredProcedure in the ADO.NET SQLClient class. You don't want to execute it as a Language Event, because that is not going to trigger the most optimal code path inside SQL Server.

If SQL Profiler shows you a SQL Statement starting event and then you see anything else than INSERT, UPDATE, DELETE, or if you see "EXECUTE " you are probably dealing with a stored procedure. That means that your program is actually choosing the wrong code path.

Parameter re-use: If you send in a "EXEC" - type select concatenated text vs Parameterized Command, the execution plan gets recompiled. But , when you use named parameters in ADO.NET, you are actually creating a Template. This Template is how SQL Server achieves plan re-use and does not have to recompile the execution plan for the query.

You can actually see this plan re-use and optimization by querying select * from master.dbo.syscacheobjects . In SyscacheObjects, there is a Sql column and a usecounts column. Sql holds the sql fragment, and usecounts shows how many times the SQL Engine has been able to re-use the code path without having to recompile, resulting in more optimized code and lower CPU utilization.

So, for example if you run 10,000 stored proc invocations with different (or even the same) parameter values using CommandType.Text and "EXEC SPNAME param1 param2" etc., these will be usually recompiled every single time (depending on whether autoparameterization is used by SQL Server). This burns up CPU cycles. Event though the performance difference may not be readily apparent, you can bet that this is an inefficient way to do it. When you use CommandType.StoreProcedure with SqlParameters, it gets compiled ONCE - and re-used by the Sql Server engine every subsequent time. This ain't rocket science!

Parameterized select statements are normally significantly faster than "text - only" select statements.

And of course, with Stored Procedures and selects / inserts, using fully parameterized execution results in significant performance increases.

Client - side Parameter Caching

You can also use a Client-side caching mechanism for SqlParameters. The MS Data Application Blocks "SqlHelper" class already has a very nice one built in. By caching the parameter set for each stored procedure, I've seen performance increases ; it seems that the creation of ADO.NET SqlParameter objects is expensive, and if we can cache and re-use them , there are substantial economies of throughput to be obtained.

If a multi-insert operation is bracketed within a transaction, the deferred writing to the transaction log creates much enhanced throughput. Drapers illustrated this in real time in his Tech-Ed presentation and I was, well - trust me, its hugely faster! Also client side Parameter Caching (a.k.a. SqlHelper) can increase performance.

What others have to say about the subject:

Kirk Allen Evans (Excerpts):

Databases create a query plan or "internal road map" to determine the quickest and most efficient route to deliver the requested data. The database's cache manager compiles the query plan and stores it in its cache when you execute a query for the first time. If you execute the same query text again, the database retrieves the query plan from the cache and uses it to retrieve the data. But if the query differs by even one character, such as the data in a WHERE clause, the database must compile the query again, generate a new query plan, and store the query and plan in its cache.

If an application searches for a customer by name, many different cache listings will appear in syscacheobjects for essentially the same query.

A more efficient approach than forcing the cache manager to recompile queries each time is to reuse the same query multiple times using parameters. This saves CPU cycles because it avoids recreating cache entries. SQL Server provides an excellent mechanism for doing this through its implementation of stored procedures. Create a stored procedure that accepts a variable and use the variable in the SQL WHERE clause.

The real performance difference occurs with complex SQL statements that are inlined, where the WHERE clause varies only by its values. This causes discrete cache entries into the cache plan, meaning the query is parsed for execution plan each time the query is run.

The Prepare statement caches the statement and indicates to the provider that the same statement will be run many times. The provider may or may not perform optimimizations to support this, which SQL Server does. By executing this each time within the loop, you cause extra processing. Move this out of the loop, because you only have to prepare it once.

Second, you will get better performance by using a parameterized SQL statement by replacing the literal values with question marks and using parameters in place of the literal values. The parameters can then be reused as well, where you simply set the values during each iteration.

Third, you can enhance performance a little more if your provider supports the .Prepared property for the Command object. The .Prepared property pre-compiles the SQL statement and caches it, avoiding parses for invaalid SQL statements.

One more comment: you are not going to see a noticeable time difference between using parameterized SQL queries that simply call a stored proc over using a CommandType of StoredProc. The real difference occurs back on the server, where the procedure is parsed and cached.

Jesse Ezell:

In any case, ALWAYS use parameterized queries. Anything else is a rediculously [sic] lame decision.

Barry Gervin:

In terms of SQLServer and Oracle, there are no implicit performance improvements between a stored proc and a parameterized inline sql statement. Both of them have their execution plans compiled at first execution - and then reused.

In SqlServer - with non-parameterized sql - the syntax will be parsed and auto-parameterized - so 2nd & nth executions on similar sql (different hard coded values) should exhibit performance on scale with parameterized sql (or stored procs).

Sometimes the auto-parming doing by Sql isn't as efficient as a developer could manually parm it. Think of a case when you have a constant in the query that neverchanges: where inactive="n" and state="CA". SqlServer will auto-parm the "n" and the "CA" but you know that "n" will never change. That would lead to not as efficient parameterization.

And Finally, an example of using the Prepare Statement--

public void SqlCommandPrepareEx() {
int id = 20;
string desc = "myFirstRegion" ;
SqlConnection rConn = new SqlConnection("Persist Security Info=False;Integrated Security=SSPI;database=northwind;server=mySQLServer");
SqlCommand command = new SqlCommand(null, rConn);

// Create and prepare an SQL statement.
command.CommandText = "insert into Region (RegionID, RegionDescription) values (@id, @desc)" ;
command.Parameters.Add ( "@id", id) ;
command.Parameters.Add ( "@desc", desc) ;
command.Prepare() ; // Calling Prepare after having set the Commandtext and parameters.
// Note- this command is now "Templatized- if you change parameter values and call it again,
// SQL Server will re-use the execution path without needing to recompile.

// Change parameter values and call ExecuteNonQuery.
command.Parameters[0].Value = 21;
command.Parameters[1].Value = "mySecondRegion";

Some useful links about all this:

SyscacheObjects( MSDN):

Kimberly Tripp:

Kalen Delaney ("Inside SQL Server 2000"):

Andrew Novick:

SQL Server 2005:

The Bottom Line!
The lesson from all this is that just because something "works" and you have gotten used to doing it doesn't mean you automatically have the right to become a self-proclaimed "guru" and recommend it to everybody else in the face of facts, figures and arithmetic that explain why what you are doing is NOT "best practices code". And if you are obstinate and refuse to accept the facts, digging in to protect your already indefensible position, shame on you! Don't use CommandType.Text to execute stored procedures. If you are lazy and you don't like to type, use the SqlHelper class with (connectionstring,spname,object[] parmvalues) and your SqlParameters will be automatically CACHED for you! Finally, ALWAYS parameterize your text sql queries with parameter placeholders and REAL SqlParameters!

Obstinacy is the result of the will forcing itself into the place of the intellect.

--Arthur Schopenhauer 1788-1860, German Philosopher .


SWIG - Creating Managed Wrappers

Today I discovered SWIG - which makes writing managed C# wrappers for unmanaged C++ libraries and DLLs hugely easier. I am in the process of studying managed C++ wrapper code, "It Just Works" and P/Invoke to handle some needs related to exporting methods from telephony board APIs.

Although I haven't gotten very deep into it, one look at all the C# code SWIG generated from a single imported *.h header file has me convinced!


To Deficit - or Not To Deficit? (Don't believe everything you hear):

One of the biggest Bush-bashers during the 2004 Presidential Campaign was the "Huge Deficits" that Pres Dubya recklessly ran up, right? Not!

Drops in revenues and increases in outlays occur automatically during a cyclical downturn and then reverse themselves during a cyclical upturn. There is also a "cyclically adjusted deficit". The cyclically adjusted surplus or deficit is calculated to show the underlying outcome of the federal budget when those automatic movements are removed.

Policy actions by the Congress and the President, such as tax or spending legislation, create changes in the total budget surplus or deficit that are distinct from the automatic cyclical movements. The cyclically adjusted surplus or deficit includes the effects of those legislated changes.

The CBO calculates a different measure, the standardized-budget surplus or deficit, that attempts to remove those factors as well as the effects of the business cycle. As a result, the standardized-budget surplus or deficit is the more speculative. That is the one the Democrats were screaming about, trying to scare the pants off the average American, who really doesn't know much about economics.

Calculations of cyclically adjusted budget measures attempt to remove the effects of the business cycle on revenues and outlays (that is, the cyclical part of the budget). For example, cyclically adjusted revenues exclude the loss of revenues that automatically occurs during recessions. Likewise, cyclically adjusted outlays exclude the additional spending that follows automatically from a rise in unemployment. The difference between those two measures is the cyclically adjusted surplus or deficit.

CBO estimates that the cyclically adjusted deficit will increase from 2.6 percent of potential GDP in 2003 to 3.2 percent in 2004 and then decrease to 2.8 percent in 2005 --an increase of 0.2 percent. A good look at the chart of the Cyclically adjusted deficit below shows that we are quite clearly well within the historical range, and given the fact that we are still emerging from the nasty stock market bubble and recession that Dubya inherited, along with the effects of 9/11, it isn't reckless at all.

CBO Cyclically Adjusted Deficit Chart
CBO Historical Chart of Adjusted Surplus/Deficit


Did the Republicans have a Gamma Ray Burst?

or was it just crappy exit polling?

At any rate, the popular vote was representative of the largest voter turnout in American history, and George Soros is probably looking for a monastery he can move into.

If I sound partisan, it's because I have become so, with America becoming so incredibly polarized. Now maybe the Bush-hating left wing elite media establishment will shut up for the next four years and we can get on with business! These people have become so arrogant over the years, they have really become out of touch with mainstream America, as the election has proven. And the exit polls - boy that's just a whole 'nuther issue entirely!

Q: What is 50,000 Liberals at the Canadian Border?
A: A good start....


Telephone Pet Peeve

Don't you just LOVE these people that leave answering machine messages like they are gonna give you the history of the world, or something? I do most of my business work with my cell phone, leaving the main phone free for the Significant Other. Calls come in all the time when she's out, and since that phone is just off my office and I don't bother answering it, I get to hear all the dumb messages people leave.

I mean, "Hello, this is who I am , this is why I am calling, and here's my phone number", right? Oh, NO! They gotta tell you everything and take up 10 minutes of time with all their B.S., when all that can ever happen is you are either gonna call them back or not, right?


Oct 2005 CTP Woes for VS.NET 2005

Well, I went ahead and installed the Oct 2004 CTP's of SQL Server 2005 and VS.NET 2005. SQL went great. VS.NET - not so great. Two main problems (one fixed, one in Product Feedback pending review from Redmond):

1) The ASPNET_ADMIN.EXE Registry entries were not updated by the install, so the service failed on boot. Reason? Simple - they were still pointing to an exe located in the 2.0.40901 folder, and the new correct version folder is 2.0.40903.

So, manually changed the registry entries and everything is fine.

2) Installation of the Virtual PC (VPC) Network driver failed on first install. Second time around, it appeared to take, but when you go to debug a Compact Framework app in the emulator, you get a nasty popup to the effect that its not installed. Tried every fix out there including Amit Chopra's blog stuff (From MS - see link above) and no dice. Boo - Hoo!

I did have EVC++ installed and Chopra indicated that could be a possible cause, but its not installed now. I even tried installing Virtual Server 2005 trial to update the driver, and it did, but it didn't help.


RE: Microsoft Delivers a New Visual Studio 2005 Beta

Microsoft recently released a new "community technology preview" (CTP) beta build of Visual Studio 2005 "Whidbey," as numerous Microsoft bloggers have noted. It includes "edit and continue" support for Visual C#.

[Via Microsoft Watch from Mary Jo Foley]

So how many times do we need to reinstall this to get to first base? I think I'll pass for now. Eh, on second thought, maybe I'll just download the bits and get around to it...

Test Blog from Bloggar

This is bloggar talking!


Presidential Debates and Communications

O'Reilly had a communications specialist on tonite, the night after the first Presidential debate. She reminded me of something very interesting about human communication (they were talking about how Dubya was looking annoyed, etc. when Kerry was running him down):

Communications is:
55 % Body Language
38 % Tone of Voice
7 % words

Your body language and tone of voice account for NINETY THREE PERCENT of what you communicate. Your words - what you are actually saying - only 7%. Think about it.


Crap! Another hurricane

hard to concentrate on your work when everybody wants to put on the Weather Channel and be entertained.


Circular References, Memory Leaks, and other Baddies

In a garbage collected environment such as .NET, it is possible to unwittingly leave objects in a state where the garbage man will be "on vacation". One way to check on this kind of stuff is with profiling products such as the Scitech .NET Memory Profiler: http://www.scitech.se/memprofiler/

Ian Griffiths has a well - written, concise piece on this subject here: http://www.interact-sw.co.uk/iangblog/2004/07/07/circulareventrefs

One of the issues we found with this is when you have a lot of controls on a UserControl or form and you unwind it, thinking you have gotten rid of everything.

Except, you may have not done so - event handler delegate calls may still hold a reference to their target. We found this to be especially noticeable on controls derived from RichTextBox - a control with a lot of Interop going on under the hood and notoriously "Buggy" to boot.

The problem is solved with a neat little method we call in the Dispose Block , "UnregisterChildControls":

private void UnRegisterChildControl(Control ctrl)
if (ctrl is CustomCheckBox)
{ CustomCheckBox cb = (CustomCheckBox)ctrl;
cb.CheckedChanged -= new EventHandler(cb_CheckedChanged);

else if (ctrl is CustomDateComboBox)
CustomDateComboBox cmb = (CustomDateComboBox)ctrl;
cmb.DateSelected -= new DateSelectedHandler(cmb_DateSelected);

-- By "cleaning up our room" in this manner, we've seen those scary looking memory consumption profiles flatten out very nicely. :-)


SQLite ADO.NET Provider and Compact Framework

Well, I spent a fruitless afternoon fiddling with SQLite 3.0.4, 3.0.5 and the Finisar SQLite ADO.NET provider. The provider works great for SQLite 3.0.X but there are serious issues with getting it to work ON the Compact Framework due to the marshaling deficiencies with C-style DLLs in CF.
Bottom line is, even though the provider has a .NETCF solution and test app, they'll compile fine - but they will always throw a System.MissingMethodException on the sqlite_open call.

This, after downloading the C source and recompiling my own SQLite3.dll library, to no avail!

Finally, a look at the Sqlite WinCE site shows the proof: "SQLite 3XXX has serious issues!"

Yeah, so does SQLite 2.8 too, if you want a 100% CF - based DBMS solution.


Eh! SP2

Geez. They are making it into some sort of opening nite gala or something.


An interesting C# managed-code wrapper for BITS (Background Intelligent Transfer) Eddie Tse: BITS C# Wrapper