Wednesday, September 24, 2003

More Compact Framework Thoughts

Wow!  Two posts in one day.  Considering the dearth of posts from this blog lately that is pretty amazing. After my earlier rant I remember something I brought up with the CF team at Microsoft.

When I have heard the limitations of CF described in the past by MS folks it has been in the context of, "We are running on smaller, memory constrained devices so we built a smaller version of the framework that fits in just 2 MB."  That is all well and good but I am starting to do work for Windows CE based devices with 128MB and 256MB and I really want the full power of the framework.  While it is impressive that they were able to compress the amount of goodness that they did into 2 MB but what about developers for which there is abundant memory available?  Why didn't the team take more of a factored approach such that if I was willing to give them another 2MB I could get remoting or <insert your favorite dropped feature here>?

This really brings to life the promise of only needing to know how to develop for one platform, .NET.  I don't need to know a long laundry list of limitations of things that I can't do on WindowsCE.  Instead I have to be willing to step up and trade RAM for features.  I know, I know not all features will be available on WindowsCE because of limitations of the OS.  I am fine with that.  The list of things removed due to OS limitations is going to be much shorter than the current list of things that were removed.  IOW the delta between desktop and compact will narrow but not necessarily close the gap.

10:26:51 AM    

Compact Framework Rant

I admit it.  I have been doing a considerable amount of Compact Framework programming over the last couple of months. First off let me say I think Compact Framework hold great potential.  That being said I think it has a long way to go.

I recently build two applications using the compact framework.  One was a kiosk style application that had to communicate with other controller programs running on the kiosk.  This communication ended up happening using windows messages.  Luckily the MessageWindow class provides a way to receive messages however it is the only hWnd exposed so the applications I was communicating with had to do a FindWindow() on my forms to find their hWnds.  Ridiculous considering the hWnd is exposed off each windows form in the desktop framework.  Next problem we hit was that come to find out Windows CE has a 32MB process size limit!  Of course we were precaching a number of graphics, etc and even attempting to play video which meant that we hit this limit pretty quickly.  In a day when devices had 2-4 MB on average a 32MB process limit probably made sense.  Today however is it ridiculously small.  Next roadblock.  We needed to play animated GIFs.  They play in PocketIE so we figured no problem.  Wrong!  The animated gif support was ripped from the bitmap class in Compact Framework!  This of course meant that we needed to write our own animated GIF class.  Things were going fine until we were handling the dispose types for an animated GIF and realized that the lack of a way to XOR bitmaps was going to make the process very, very difficult.  Granted this is a limitation in the desktop framework as well as the compact framework.  Argghh!

Next we move on over to writing a PocketPC application where things go a bit smoother but we still find some frustrations.  It is intended to be a wireless application used as a specialized tool for a customer service person.  Sort of like the folks you see at the Hertz car rental places.  It talks to a backend database as well as a wireless 802.11b printer.  Of course the middle tier that is in place uses remoting which, you guessed it, the compact framework lacks.  So we wrapped access to the remoted interface with a web service.  Things are going along well once we get around this roadblock, until we test on the actual device.  We realize that we have written an application that has no way to bring up the SIP (soft input panel) on the device. Not a problem we say.  We can just place the SIP control on our form and use it to display the SIP.  Whoa!  We don't have a menu bar on our form and for some bizzarro reason the SIP will only work on forms with a menu bar!  So we figure out how to make the API call and draw a few lines to show a fully functional SIP on our form.

If you are interested here is how you show the SIP:

  private static extern bool SipShowIM(int dwFlag);

To show it:


To hide it:


There is a bottom line missing on the SIP since it counts on the menu bar to draw it.  So add a:

e.Graphics.DrawLine(new Pen(Color.Black), 0, 294, 240, 294);

In the forms paint when the SIP is showing and you are all set.

8:39:37 AM    

  Friday, September 12, 2003

Are you happy Scott?

Scott Hanselman recently wrote an article about the difference between friends and acquaintances where he mentioned me.  Of course he also browbeat me about the fact that I hadn't posted anything recently on my blog. The last non-blogging stretch I had was due to Radio melting down but this time around I just have been insanely busy for the last couple of months.

Scott I have frequently asked myself the same question.  I frequently confuse the two terms calling acquaintances friends quite often. Friendship is a two way thing.  While I would have no problem at all with any of the acquaintances I call friends crashing at my place (if that is the criteria) I can't say that the feeling would be mutual. Not a problem for me. Still call them friends and my door is still open.  Scott you are of course welcome to crash at my place anytime.

It is almost at an end however and I am looking forward to getting back to normal.  I sit right now in a Hotel room in Orlando preparing for an all day workshop I am giving tomorrow on "Best Practices for Enterprise Development" with Rockford Lhotka. As I sit here preparing I can't help but remember a talk Scott, Bill Evjen and I had just today about the content at most conferences. Bill had just finished an intro to Web Services talk that was so well received it suprised him. He couldn't believe that almost three years after the release of the first .NET Web Services stack that folks were still interested in the basics. I then mentioned that I was doing a workshop tomorrow that was all new to me and quite honestly a new type of workshop for VSLive! which tends to be focused on very pragmatic code based talks. It is a talk that is really focused not on code but on the other things that need to go into a project to make it successful.  It is really pretty basic blocking and tackling but come to find out is the most popular workshop so far based on registrations! Just goes to show that what I find interesting isn't necessarily what my attendees will find interesting.  I think speakers get caught in a trap of creating content that they think their peers will find impressive instead of looking at the conference attendees and determining what is useful to them. Let's face it.  Most speakers wouldn't be at the conference if they weren't speaking.  They aren't the intended audience.  What do you think?

Hopefully this will not be my last post in a long while.  I have been doing quite a bit of Compact Framework development that has really given me a new perspective on .NET.  I really need to write down some of my experiences and hope to do so over the next couple of weeks.  First I have to finish my last conference of the season, Guided Design .SUMMIT on campus at Microsoft October 1-3. 

3:14:49 PM    

  Wednesday, June 18, 2003

New .NET Architecture List

I am starting a new list of Architecture links related to .NET.  I put it off for a long time until I was sitting with someone today trying to show them an architecture document from PAG and then couldn't find it for 15 minutes as I waded through the site.  The list will start out quite unordered.  Eventually over time I will impose more organization as it grows in size.

1:07:40 PM    

  Thursday, June 12, 2003

.NET Posters

Ever wanted one of those cool VS.NET object model posters you see on other developers walls? Have a 36" wide HP InkJet sitting unused down the hall since the last time you printed out that 1500 table ERD diagram? Well solve both problems with one link:

9:56:42 AM    

  Monday, June 09, 2003

Validation and Form Close

Ran into a weird one today.  We have a windows forms application that uses the validating event on it's controls.  When the user clicks the close box (red x) in the corner we want to prompt whether they would like to save and then close the form.

The validators cause problems with this.  Clicking on the close box causes validation to run. First blush you think no problem, I will set CausesValidation on the form to false.  Whoa!  The Validating event still fires.  It appears that the close box always causes validation. Next you think I will override OnClosing() and ask whether they want to save before calling the base implementation thus only allowing the Validating events to fire if they are saving.  Wrong again.  Validating fires before OnClosing!

So here is the hack I came up with.  Override WndProc in the form and look for the WM_CLOSE message.  If you receive it then set a protected member on the form to indicate it is currently closing.  I have this hidden in a base class that exposes the member as a read only property.

Here is some sample code:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace ValidationTest { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.TextBox textBox2; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null;

public Form1() { // // Required for Windows Form Designer support // InitializeComponent();

// // TODO: Add any constructor code after InitializeComponent call // }

/// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }

#region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // textBox1 // this.textBox1.Location = new System.Drawing.Point(80, 96); this.textBox1.Name = "textBox1"; this.textBox1.TabIndex = 0; this.textBox1.Text = "textBox1"; this.textBox1.Validating += new System.ComponentModel.CancelEventHandler(this.textBox1_Validating); // // textBox2 // this.textBox2.Location = new System.Drawing.Point(80, 128); this.textBox2.Name = "textBox2"; this.textBox2.TabIndex = 1; this.textBox2.Text = "textBox2"; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 273); this.Controls.Add(this.textBox2); this.Controls.Add(this.textBox1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false);

} #endregion

/// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); }

// Constant for WM_CLOSE private const int WM_CLOSE = 16; // flag to indicate we are closing private bool m_bFormClosing = false;

protected virtual bool FormClosing { get { return m_bFormClosing; } }

private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) { // Bail out if the form is in the process of closing if(FormClosing) return;

// Do my normal validation if(this.textBox1.Text == "invalid") { e.Cancel = true; MessageBox.Show("Invalid entry"); } }

protected override void WndProc(ref Message m) { // Check for the closing message if(m.Msg == WM_CLOSE) // Set our flag m_bFormClosing = true;

// Call the base base.WndProc (ref m); } } }


Wow that is ugly!  If anyone knows of a good C# -> HTML converter that works with Radio send me a pointer at This is from

2:58:19 PM    

  Monday, April 07, 2003

Managed Wrapper for BITS

BITS is a pretty cool background transfer service that does the hard work of actually determining when your network connection is idle to transfer files. A managed wrapper for the API just became available on MSDN.

5:38:38 PM    

Blast from the Past

Keith brings up writing certification exams for Microsoft.  We both did this for a while and became SMEs (Subject Matter Experts) in the terminology of the team at the time.  It was interesting to get some insight into the truly bizarre way that importance is assigned to topics in those tests.  The way correct answers were determined was sometimes even more bizarre.  One of the main reasons that I stopped the whole exam treadmill years ago. 

I still laugh when I remember back to arguing with Ken and Mike over whether or not Access questions should be on a Windows Architecture exam...

7:49:56 AM    

  Wednesday, March 26, 2003

.NET 1.1 Breaks ChainStream

Well we have been working hard on converting our 1.0 code base to 1.1.  We keep running into little things that are breaking our code though.  The latest is a breaking change in ChainStream.  We had a compression stream that we were running on top of our web services. In .NET 1.1 some new code (SoapServerProtocolHelper) was introduced that attempts to seek the stream closest to .NET without checking the CanSeek property.  Essentially what this means is that whereas non-seekable streams were legal in 1.0 they are no longer legal in 1.1.  Kind of kills some of the utility of ChainStream since it means that you pretty much have to buffer the whole request or figure out how to just buffer some of the envelope so you can seek back when requested. Here is the disassembly courtesy of Anakrino:

internal static SoapServerProtocolHelper GetHelper(SoapServerProtocol protocol) {

SoapServerMessage local0;

long local1;

XmlTextReader local2;

string local3;

SoapServerProtocolHelper local4;

local0 = protocol.Message;

local1 = local0.Stream.Position;

local2 = SoapServerProtocolHelper.GetXmlTextReader(local0.ContentType, local0.Stream);


local3 = local2.NamespaceURI;

local4 = SoapServerProtocolHelper.GetHelper(protocol, local3);

local0.Stream.Position = local1;

return local4;


The killers are the lines that attempt to set the position...

9:45:04 AM    

  Tuesday, March 25, 2003

Radio Fixed!

Radio is working again finally!  Thanks to Lawrence Lee.

5:31:15 PM    

  Wednesday, March 19, 2003

.NET Memory Profiler

Great tool that I found that helped us find a pernicious "memory leak". offers a memory profiler that doesn't slow down your application as much as the Borland memory profiler but still allows you to compare memory snapshots, find objects that aren't being disposed and potentially trace down the root references of those objects.

12:51:57 PM    

WildGrape NewsDesk and DotNetWebLogs

I am reminded why I have yet to leave Radios aggregator.  As I am reading the blogs on http://dotnetweblogs NewsDesk continues to show blogs I have read as new every time I start it up!  Radio OTOH is smart enough to only show items that are truly new.  I have no idea how or why they differ but I certainly prefer the way Radio does it.

10:50:56 AM    

  Thursday, February 13, 2003

SourceGear Vault

I don't mention products here very often but this one has me excited.  I have hated Visual SourceSafe for quite some time now.  I am sure that many of you share my frustrations with it.  SourceGear the makers of the popular SourceOffsite add-in for VSS shipped Vault at the VSLive show in San Francisco this week.  Vault is a complete replacement for VSS using SQL Server as a back end store and Web Services/ASP.NET as a transport mechanism!  It is a purely managed solution that replicates almost 100% of VSS functionality. I have no connection to the company but I have already ordered a copy.  They have a great starter pack at $599 for 5 developers.  I have just started using this product and I have high hopes for it.  Check it out.

6:48:00 PM    

  Friday, January 10, 2003

Read Only Application Object


Pre-Load the ASP.NET Application object and donít allow other pages in your project to add/modify/delete. Basically, make Application read-only.


         private void SetApplicationReadOnlyStatus( bool state ) {
                  Type type = Application.GetType().BaseType;
                  PropertyInfo readPropInfo = type.GetProperty("IsReadOnly",  BindingFlags.NonPublic | BindingFlags.Instance) ;
                  if( readPropInfo != null ) {
                        readPropInfo.SetValue( Application,Convert.ChangeType(state,readPropInfo.PropertyType ) ,null);
            private void Page_Load(object sender, System.EventArgs e) {
                  Application["MyKey"] = "myValue";
                  // Set application to readonly so that we will not allow any changes.
                  SetApplicationReadOnlyStatus( true );
                        // Try setting a value 
                        Application["MyKey"] = "New value";
                        Response.Write("You won't see this");
                  catch(Exception ex) {
                        // You'll end up here

Thanks to Sairama for the code!

Set the ASP.NET Application Object to Read-Only. [Scott Hanselman's Weblog]
1:20:52 PM    

  Thursday, November 21, 2002

PAG ASP.NET Security Beef

I know that a number of folks out there in the wild have been reading this document.  I have been reading it in parts over the last couple of weeks.

I found it extremely strange how insistent they seem to be on encrypting the connection between the application server and the database server.  To the extent that they are talking about running it over IPSec or SSL.  They don't really address their reasoning for this insistence. I can see this being a valuable technique where the communication between your application server and database server must be done over a semi-trusted network. In the case where you totally control the network is this still necessary or just overkill?  I mean today how many non ASP.NET applications communicate with the DB server over internal networks using an encrypted connection?

My second beef is that they show you how to setup an IPSec connection between the application server and database server and then say the technique is only suitable for development servers.  They never address how it should be done in production with an actual example.

7:44:09 AM    

  Friday, November 08, 2002

Ready...Set..Visual Studio.NET

I will be doing a local event for developers considering the move to Visual Studio.NET in Seattle 12/4 and Portland 12/11 with Chris Sells, Scott Hanselman, Bill Vaughn and Jim Blizzard.  The PDF file of the invite is here.  If you haven't yet made the jump to Visual Studio.NET join us for a day of orientation!

6:55:06 PM    

  Thursday, October 31, 2002

Radio Broke My RSS Feed

Well it finally happened to me.  I kept seeing posts about Radio breaking this or that and just figured it was folks who were messing with the internals.  I just got email this morning saying my plain vanilla install has a broken RSS feed.  Problem is I have no idea how to fix it...

7:57:33 AM    

  Thursday, October 17, 2002

ASP.NET Security

Great article on ASP.NET Security has been posted to MSDN by the folks in the PAG.  Takes a look at a number of different scenarios and gives recommendations for each.  ASP.NET Security

12:57:08 PM    

  Wednesday, October 09, 2002

Tiny Abstract OS

All I can say is wow!  I can't figure out why you might want to do this but it sure is cool.  Check out the miniature operating system Scott has created entirely in C#. Tiny Abstract OS and CPU in C#  PowerPoint deck Tiny Abstract OS and CPU in VB.NET  [Scott Hanselman's Weblog]

5:23:19 PM    

  Friday, September 20, 2002

Build Practices

Great article on build practices with .NET.  It outlines the problems but doesn't really offer code to solve any of them!  Article

Also an interesting utility for automating builds that I plan to check out:  FinalBuilder.  Another interesting tool: Visual Build. A reader wrote about another great build tool Autonomy that integrates with NAnt.

At my current project we wrote our own automated build facility that does our nightly builds by:

  • Parsing an XML file for projects to include
  • Gets the current projects out of SourceSafe
  • Updates all the AssemblyInfo.cs files with a new version number
  • Walks the dependencies in the .csproj files to determine a build order
  • Builds the source
  • Emails the result to a build manager
  • Starts smoke test if the build was successfull. 

This whole process is very specialized for our environment but I think it is stuff that any development team should be doing.  The question is why hasn't Microsoft filled this gap with tools for teams to do this type of thing?  For that matter why do we still have the crappy Source Safe shipping as part of VS.NET?  It is an embarrassment but until Microsoft drops it from the package it is going to be what most teams are forced to use since it is "free". 

I know a ton of you will write me and say, "Why not use CVS?".  Great question.  I consider myself fairly technical.  I tried to setup CVSNT and spent three days searching the web, etc just trying to get the service up!  This doesn't include getting a front end application working or trying to understand how to use it!  We need something with the usability of Source Safe in both daily use and setup that has a much more robust store mechanism and uses TCPIP for communication with the central server in an efficient fashion. 

1:55:47 PM    

  Thursday, September 19, 2002

Sample Installer Action To Install .NET Policies

I have been doing a lot of smart client development over the last 18 months.  When I mention this to folks they invariably ask me how I am distributing policies to our users.  Here is a sample installer action that shows how to create Code Groups and Persmission Sets as well as how to remove them.  Have fun!  Sample

8:33:39 AM    

  Wednesday, September 04, 2002

Vermont .NET Users Group

I will be speaking at the Vermont .NET Users Group on 10/7/2002 about Windows Forms vs. Web Forms: Why choose?

Been awhile since I even went to a user group let along spoke at one.  INETA has gathered me back into the fold as it were and has me hitting this group.  I am really looking forward to it.  Hanging out and talking with folks excited about .NET has got to be a blast I figure.

5:20:28 PM    

  Thursday, August 22, 2002

.NET Framework SP2

Anybody else having problems installing this thing.  Out of a sample of about 15 machines we have had a variety of problems on 6.  IIS not working, complaints about DirProp on ASPNET_ISAPI.dll, etc.   I am scared to have our customers even attempt to run this due to the number of support calls we will end up receiving.  We are thinking very seriously about skipping this service pack and waiting for SP3.  I hate to say that since it is back to the SP hell we had with NT 4.0 as opposed to the relatively smooth Win2K SP process.

9:52:35 AM    

  Tuesday, August 20, 2002

GotDotNet Workspaces!

GotDotNet Workspaces are sourceforge like collaborative environments for developers. I have wanted something like this ever since I first saw SourceForge.  SourceOffsite has their collab edition but this requires a Win32 client or offers only reduced functionality in the web client.

If gotdotnet does this right and leverages Rob Howards ASP.NET forums, all their internal experience on the various iterations of RAID, and adds a web based source control mechanism WOW!  Hopefully it will not only be a hosted offering but also something that can be downloaded and run locally in a secure fashion.  The more I think about it I am suprised this isn't a product feature in VS.NET instead of what is appearing to be a free giveaway..

4:17:09 PM