David Douglass

.NET on My Mind
posts - 57, comments - 23, trackbacks - 13

My Links

News



Archives

User Group Presentations

Sunday, May 04, 2008

Observations on .NET Object Disposal

Here's what I've learned in a recent fight with a nasty object disposal bug.

Every .NET developer needs to understand object disposal.  Start with DG Update: Dispose, Finalization, and Resource Management for a complete discussion of the topic.

Carefully implement the pattern.  Here's the bug I had to deal with:

protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // dispose of managed objects // dispose of unmanaged resources } disposed = true; } }

Both the managed objects and unmanaged resources were being disposed of only when disposing was true.  The code should have been:

protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // dispose of managed objects } // dispose of unmanaged resources disposed = true; } }

 

What this bug does is interfere with finalization.  All of an object's resources that haven't already been released should be during finalization.  But, because the unmanaged resources were disposed of only when disposing was true, nothing was disposed of during finalization.

What's unusual about this bug is that you may never notice it or it may cause you to exhaust a resource and prevent your application from running.  If every disposable object is disposed of, then it doesn't matter that finalization doesn't do anything because there wouldn't be anything to do.  But what if you forget to call Dispose?  In that case the unmanaged resources will never be disposed of and you'll have a classic C++ style leak on your hands.

Whenever possible, use a using statement to ensure object disposal.

Note that there was a huge change between Visual C++ 2003 and Visual C++ 2005 regarding object disposal.  See Changes in Destructor Semantics for details.

posted @ Sunday, May 04, 2008 11:52 AM | Feedback (0) |

Thursday, February 21, 2008

Vista SP1 Upgrade

I ran the Vista SP1 upgrade on an Asus V1S running Vista Business.  I was having no issues before the upgrade and haven't found any post upgrade.

posted @ Thursday, February 21, 2008 7:25 AM | Feedback (1) |

Tuesday, February 05, 2008

Microsoft + Yahoo = Bad Idea

Microsoft has bid $44.6 billion for Yahoo.  This is not a good idea because:

  1. Microsoft and Yahoo are both struggling in search because their products are inferior to Google's.  Combining the two companies won't fix this.  Actually, Google is in a very dangerous position.  All Microsoft has to do is come out with a superior product.  Thanks to the zero cost of switching  search providers, Google could face an exodus.  While not an easy task, Microsoft has the resources to make this happen.
  2. Yahoo is not a mining company.  When you buy a company like Yahoo you're mostly buying the workforce.  The only reasonable assumption is that the technical staff is highly anti-Microsoft.  Even with a retention program, people will leave in droves.  Your best people leave (because it's easy for them) while your weak people stay (for the opposite reason).
  3. What is Microsoft going to do with all that non Microsoft technology at Yahoo?  If this comes to pass, hopefully they'll be sensible about this and maximize the return on prior investments.
  4. Microsoft is highly profitable thanks, in large part, to its corporate customers.  Will Yahoo become such a distraction that they'll take their eye off the ball?  Windows, Office, the development tools, and the server products such as SQL Server are all in a strong position; the last thing Microsoft needs is to start losing momentum in those areas.
  5. Microsoft is paying an approximately one third premium for Yahoo based on market pricing.  That's an extra $15 billion for a company in layoff mode.  Even for Microsoft that's real money.  Does that make sense?

Corporate mergers, especially big ones, have a long history not working out the way the suits plan.  Will Microsoft go from powerhouse to lost in the woods?

posted @ Tuesday, February 05, 2008 7:17 AM | Feedback (1) |

Monday, February 04, 2008

WCF REST over HTTP Service

I put together a WCF REST over HTTP service and learned a few things along the way.

Sample Project

The best way to learn about WCF REST is to examine the sample project supplied by Microsoft.  This is available at Windows Communication Foundation (WCF) and Windows CardSpace Samples.  Once you unzip the download you'll find C# and VB sample projects at TechnologySamples\Scenario\PoxMessaging.  These simple projects demonstrate everything you need to know.

Creating Your Own Project

The Visual Studio project template for creating a service hosted by IIS isn't grouped with the WCF projects but is with the ASP.NET projects:

create new project

Once you have a project created, just follow the pattern in the sample and you'll quickly be ready to test.

Testing Your Project

The easiest way to test your project is to use Fiddler 2.  Fiddler 2 includes a tab that lets you form and send HTTP requests:

image

Just select your verb (GET, PUT, etc.), enter the service URL, enter your HTTP headers, paste your XML into Request Body, and press Execute!  Content-Type should be text/xml; Fiddler 2 will automatically calculate the Content-Length header for you.  The result will appear in the left pane; you can double click on the line and get a detailed look at the request and response using the Session Inspector.

HTTP Status Code 415 Unsupported Media Type

If you've been following along exactly, your service should be returning a HTTP Status Code 415 Unsupported Media Type.  This is because when the project was created in Visual Studio there was an assumption that SOAP would be used.  Switching to REST means changing the binding in the web.config file:

<system.serviceModel> <services> <service name="MyService.Service" behaviorConfiguration="MyService.Service1Behavior"> <!-- Service Endpoints --> <!-- use webHttpBinding for REST instead of wsHttpBinding --> <endpoint address="" binding="webHttpBinding" contract="MyService.IService">

Note that this page, which is supposed to list all the System-Provided bindings, doesn't mention webHttpBinding.

posted @ Monday, February 04, 2008 9:59 PM | Feedback (0) |

Saturday, January 19, 2008

Dropping a User's Default Database in SQL Server 2005

What happens if you drop a user's default database in SQL Server 2005 and the user then tries to use SQL Server Management Studio?  You get this crystal clear error message:

image

What to do?  If you have another working administrative login, then you simply need to use that to update the properties of the user that can't connect:

image

But what if the user that can't connect is the only administrative user?  In that case, you need to tell SQL Server Management Studio to connect to a different database on startup, which is done using command line options:

"C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\SqlWb.exe" -S SQLSERVER2005 -d master -E

Here's all the command line options:

image

After executing the above command, SQL Server Management Studio will come up without the object explorer (the tree view on the left) open.  But, it will be connected to the master database and will allow you to run queries.  To fix the user login so that the object explorer can be opened, simply run a query to change the user's default database:

sp_defaultdb 'SQLSERVER2005\dbuser', master

You will be then be able to open the object explorer by using File -> Connect Object Explorer...

Appendix - exact message (for search engines):

A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.) (Microsoft SQL Server, Error: 233)

posted @ Saturday, January 19, 2008 8:00 AM | Feedback (1) |

Saturday, December 08, 2007

Dual Booting Vista

I set my laptop to dual boot Vista and discovered a some interesting things when I was done:

  • The new operating systems was the default, when I wanted the original operating systems to be the default
  • I had 2 operating systems with the exact same description (Microsoft Windows Vista)
  • The selection timeout was 30 seconds
  • My old friends boot.ini and bootcfg are history!

In Vista, BCDEdit replaces bootcfg.  I can list my operating systems simply by running BCDEdit in the shell:

C:\Users\Dave>bcdedit Windows Boot Manager -------------------- identifier {bootmgr} device partition=C: description Windows Boot Manager locale en-US inherit {globalsettings} default {default} resumeobject {7caf94b7-f303-11db-8342-fd19a316638c} displayorder {default} {current} toolsdisplayorder {memdiag} timeout 30 Windows Boot Loader ------------------- identifier {default} device partition=G: path \Windows\system32\winload.exe description Microsoft Windows Vista locale en-US inherit {bootloadersettings} osdevice partition=G: systemroot \Windows resumeobject {94cd4dd2-a14c-11dc-b2fb-d72bdf6fa59c} nx OptIn Windows Boot Loader ------------------- identifier {current} device partition=C: path \Windows\system32\winload.exe description Microsoft Windows Vista locale en-US inherit {bootloadersettings} recoverysequence {572bcd56-ffa7-11d9-aae0-0007e994107d} recoveryenabled Yes osdevice partition=C: systemroot \Windows resumeobject {7caf94b7-f303-11db-8342-fd19a316638c} nx OptIn

Because I booted the non default operating system, each operating system could be assigned a logical identifier (default, current).  Had I booted the default operating system, then the one know as current above would have a GUID as an identifier.

To change the boot order:

bcdedit /default {current}

This doesn't change the order the operating systems are listed in, it simply sets the default operating system to boot.

To change the description of an operating system:

bcdedit /set {94cd4dd1-a14c-11dc-b2fb-d72bdf6fa59c} description "Vista with Virtual Server"

Finally, to bring the timeout down something acceptable for Type A people:

bcdedit /timeout 5

The TechNet page referenced above isn't much more than the basic help you get with "bcdedit /?".  See the MSDN documentation at Boot Options for Driver Testing and Debugging for a tutorial.

This just in!  I stumbled across a really detailed BCDEdit Reference document from Microsoft.

posted @ Saturday, December 08, 2007 9:34 AM | Feedback (1) |

Thursday, November 15, 2007

Root element is missing.

The following code doesn't work; the exception message reads "Root element is missing.":

MemoryStream transformed = new MemoryStream(); XmlDocument doc = new XmlDocument(); XmlReader input = null; XslCompiledTransform xslt = new XslCompiledTransform(); input = XmlReader.Create("Example.xml"); xslt.Load("Example.xslt"); xslt.Transform(input, new XsltArgumentList(), transformed); try { doc.Load(transformed); } catch (Exception ex) { Console.WriteLine("XmlDocument.Load failed: {0}", ex.Message); } Console.ReadLine();

It isn't a problem with the input file or the transform script.  The problem is that the XslCompiledTransform.Transform function leaves the stream position set to the end of the stream.  There's no root element because the XmlDocument.Load function thinks the stream has a 0 byte length.  The fix is to simply set the position to 0:

MemoryStream transformed = new MemoryStream(); XmlDocument doc = new XmlDocument(); XmlReader input = null; XslCompiledTransform xslt = new XslCompiledTransform(); input = XmlReader.Create("Example.xml"); xslt.Load("Example.xslt"); xslt.Transform(input, new XsltArgumentList(), transformed); // THE FIX transformed.Position = 0; try { doc.Load(transformed); } catch (Exception ex) { Console.WriteLine("XmlDocument.Load failed: {0}", ex.Message); } Console.ReadLine();

posted @ Thursday, November 15, 2007 7:23 AM | Feedback (0) |

Wednesday, November 07, 2007

I'm Speaking at the Fairfield / Westchester Code Camp

The first ever Fairfield / Westchester Code Camp will be held on Saturday, November 10th, at the The University of Connecticut School of Business, Stamford Campus.  I'll be speaking on Debugging Tools for Windows starting at 4:15.  The last I heard, there are still a few seats available.

Hope to see you there!

posted @ Wednesday, November 07, 2007 7:16 AM | Feedback (0) |

Saturday, November 03, 2007

Nice, Free XML Editor

You can pick up a nice, free XML editor, Liquid XML Studio 2008, from Liquid Technologies at http://www.liquid-technologies.com/Product_XmlStudio.aspx.  All the important stuff is there:

  • document text editor
  • intellisence
  • schema graphical view
  • document validation
  • XPath builder
  • XML formatter
  • syntax highlighting

The UI has a Visual Studio look and feel.  Without a doubt, the best free XML editor I've come across!

posted @ Saturday, November 03, 2007 3:13 PM | Feedback (0) |

Saturday, October 27, 2007

Dynamically Creating Tabs in WPF

I've been experimenting with dynamically created tabs in WPF.  The idea is that the user selects a menu item and a tab is created and populated with a user control.  Like so many things, WPF makes this easy once you figure out how to do it.  The thing I struggled with the most was getting the user control to display when the first tab was created.  Below is a function that takes a user control and tab name, creates a tab, and shows it to the user.

/// <summary> /// Create a new tab, populate it with the passed in user control, /// and display it to the user. /// </summary> /// <param name="detail">UserControl to populate the tab with</param> /// <param name="name">Name of the tab</param> public void AddDetail(UserControl detail, string name) { // make sure the passed in arguments are good Debug.Assert(detail != null, "UserControl detail is null"); Debug.Assert(name != null, "string name is null"); // locate the TabControl that the tab will be added to TabControl itemsTab = (TabControl) this.FindName("ItemsTab"); Debug.Assert(itemsTab != null, "can't find ItemsTab"); // create and populate the new tab and add it to the tab control TabItem newTab = new TabItem(); newTab.Content = detail; newTab.Header = name; itemsTab.Items.Add(newTab); // display the new tab to the user; if this line is missing // you get a blank tab itemsTab.SelectedItem = newTab; }

posted @ Saturday, October 27, 2007 6:56 AM | Feedback (0) |

Powered by: