Dan Crevier's Blog
view rss
News on the upcoming SkyDrive release
13/11/2008 external link
We’ve posted some details of our upcoming SkyDrive release here. I’m really excited about what’s coming all across Windows Live with our wave 3 release and how well everything works together. I’m sorry I haven’t been posting much lately There are a bunch of topics I want to write about, like ASP.NET MVC, PowerShell and Silverlight!
Font Smoothing with Remote Desktop and Windows Server 2003
12/7/2008 external link
I spend a lot of time time connected to Windows 2003 Server. I was really happy to come across this post which describes a KB article to turn on font smoothing to Windows 2003 Server. This makes a huge difference with Consolas Helge Klein » Blog Archive » Finally! Font Smoothing Over RDP/ICA on Server 2003
Disappearing disk space on Vista
9/6/2008 external link
The hard drive space on my Vista machine recently dropped to almost nothing, and I was really confused what was going on. I used my favorite disk space visualizer (WinDirStat). However, I couldn’t figure it out. Finally, I found that the following steps cleared it up: 1. Run Disk Cleanup (search from Start menu) 2. Choose “Files from all users on this computer” 3. When it’s done scanning (which can take forever), select the More Options tab 4. Select Cleanup under System Restore and Shadow Copies This freed over 40 GB for me! I think that what happened is that the Zune software touched all of my media, which created shadow copies of each file, using a bunch of space. Shadow copy space must not show up for utilities like WinDirStat. There’s a useful article on My Digital Life on how to limit how much space will be used. My was set to unbounded space.
New updates to SkyDrive!
22/5/2008 external link
We’ve made some more updates to SkyDrive including some features like comments, captions and better iteration through items in a folder. For details, check out our team blog post: Windows Live SkyDrive Team Blog: Hot new updates to SkyDrive!
Bootcamp 2.1 update available
17/5/2008 external link
Apple has an update of Bootcamp available, fixing some stability issues. I’ve had more than my fair share of crashes on my MacBook Pro, so I’m hoping it will help out. It was offered to me via Apple Software Update, but you can also grab it here: Apple - Support - Bootcamp
Implications of the just in time nature of LINQ
26/3/2008 external link
I love LINQ! I’ve found that much of the code I write involves manipulating collections in ways that can be very naturally expressed in LINQ. One interesting aspect of LINQ is that things are evaluated just in time as you enumerate over them. This can have a few unexpected consequences. Here are a couple of examples. Take the following test class: private class Test { public int Value { get; set; } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Now, think about the following code: IEnumerable<Test> tests = Enumerable.Range(1, 3).Select(i => new Test() { Value = i }); foreach (Test test in tests) { test.Value += 100; } foreach (Test test in tests) { Console.WriteLine(test.Value); } For those not familiar with LINQ, the Enumerable.Range(1, 3) creates an IEumerable that ranges from 1 to 3, and then the Select creates new Test objects with a Value equal to the current value, meaning the overall expression creates Tests with values that range from 1 to 3. So, what does this output? You might expect 101, 102, and 103 because the first foreach increments the values. However, it prints 1, 2, 3. The reason is that foreach calls tests.GetEnumerator which runs through the process of creating Test objects as MoveNext/Current is called through the foreach loop. So, the first time we go though the loop it creates 3 Test objects and we increment the value. However, those Test objects are just returned by the enumerator and don’t get stored anywhere. The second time we go through the loop we create 3 new Test objects with values 1-3. One way to get the expected behavior would be to replace the first line with: List<Test> tests = Enumerable.Range(1, 3).Select(i => new Test() { Value = i }).ToList(); This creates a list with the Test values once, and then the foreach statements will enumerate the same set of Test values in that list. Another gotcha of the just in time evaluation is that values in the lambda functions are evaluated at the time of enumeration. So, in the following example: int x = 0; tests = Enumerable.Range(1, 3).Select(i => new Test() { Value = x + i }); x = 100; foreach (Test test in tests) { Console.WriteLine(test.Value); } You get 101, 102, and 103 output. That’s because the “x + i” expression is evaluated after x is set to 100. This sort of issue is more subtle when you return a LINQ expression from a function. Who knows when that will be evaluated and what will change by then. Using ToList() is a reasonable way to force the evaluation time.
Why does my computer need to tell me when I plug into the headphone jack?
20/3/2008 external link
And, why is the icon so ugly?
mstsc /console is now /admin in Vista SP1
20/3/2008 external link
I find it kind of annoying that Vista SP1 switches the /console switch to /admin. I don't understand why they had to break this and couldn't keep the old switch working. There's a bit more info at: Nick MacKechnie : MSTSC /console switch in Windows Server 2008 and Windows Vista SP1
Yield and usings - your Dispose may not be called!
15/3/2008 external link
We ran into an interesting bug recently where a resource was being leaked because we weren't disposing of an IDisposable in some cases. Before I go any further I should state that the root bug is that the IDisposable hanging onto the resource should have implemented a finalizer, or even better, used SafeHandle. However it wasn't our code. We tracked down the bug to some code that looked like: static IEnumerable<Foo> MyEnumerable() { using (new MyDisposable()) { // code that calls yield } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Then, someone called MyEnumerable().GetEnumerator().MoveNext() without disposing it or wrapping it in a foreach. The result was that Dispose was never called on the disposable. I usually think of using guaranteeing that Dispose() gets called, except in extreme cases like thread abort exceptions. It sparked my curiosity to dig and figure out how this all works. First, a couple of words about Enumerables, Enumerators and yield. An IEnumerator provides a simple way to iterate through a collection, using MoveNext() to advance to the next element, and a property Current to get the value at the current position. MoveNext() returns false at the end of the collection. An IEnumerable is simply an object you can call GetEnumerator() on to get an IEnumerator you can use to enumerate it (for example, collections are IEnumerables). The yield keyword is a handy way to implement an IEnumerable that exposes the result of a series of calculations or operations in such a way that you can write serial code. I could spend a whole post on how cool yield is, but you can find that elsewhere. For a cool example, you can see the Fibonacci series implemented using yield. Note: yield is not a feature of the CLR, it's magical syntactic sugar provided by C# 2.0. Let's take a simple example: class MyDisposable : IDisposable { public void Dispose() { Console.WriteLine("Disposed"); } } and the function: static IEnumerable<int> MyEnumerable() { using (new MyDisposable()) { yield return 1; yield return 2; } Console.WriteLine("complete"); } If you walk the collection with the following code: IEnumerator<int> enumerator = MyEnumerable().GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine(enumerator.Current); } It will print "1", "2", "Disposed", "complete". But, how does it work? If you were to implement this without yield, you'd probably have to create a gnarly state machine, with some special cases for cleanup. Well, that's exactly what the C# compiler does for you! Using .NET Reflector, we can see what code is generated. The MyEnumerable() function returns a new instance of a compiler generated class. Leaving out some of the details, the core of MoveNext() looks like: switch (this.<>1__state) { case 0: this.<>1__state = -1; this.<>7__wrap1 = new MyDisposable(); this.<>1__state = 1; this.<>2__current = 1; this.<>1__state = 2; return true; case 2: this.<>1__state = 1; this.<>2__current = 2; this.<>1__state = 3; return true; case 3: this.<>1__state = 1; this.<>m__Finally2(); Console.WriteLine("complete"); break; } return false; With: private void <>m__Finally2() { this.<>1__state = -1; if (this.<>7__wrap1 != null) { this.<>7__wrap1.Dispose(); } } So, if you walk through the states, you can see in case 0, it creates the MyDisposable, sets current to 1 and returns true. When it's called again in state 2, it sets current to 2 and returns true. When it's called a third time, it calls the finally function that disposes of the MyDisposable and then writes out "complete". But, what happens in a partial enumeration? If you use foreach, like: foreach (int i in MyEnumerable()) { Console.WriteLine(i); break; } You might not expect it to call dispose. But, what it outputs is "1", "Disposed". The reason that this works is that the generated IEnumerator class also implements IDisposable where Dispose() calls <>m__Finally2(). And, foreach calls Dispose on its enumerator if it is an IDisposable. However, in the case of our bug, we weren't using a foreach, we were just using MoveNext/Current directly without enumerating through the entire list. In this case, the MyDisposable is never disposed, even when GC takes place. Is this a bug? I've gone back in forth in my mind. On the one hand, the Enumerable code has a using, and that's supposed to clean things up! The compiler could have implemented a finalizer for the temporary class to clean up. On the other hand, the IEnumerator it generated was an IDisposable, which we failed to dispose. I tend to land on the side that this isn't a bug (and I bet the C# team agrees). If you have something that's holding onto a critical resource, you should implement a finalizer or use a SafeHandle and not rely on Dispose being called. However, I did find it a bit surprising. Now I know!
Josh Zana's perf blog
12/3/2008 external link
One of my coworkers, Josh Zana, has started a perf blog. Josh has been the perf champion for the SkyDrive and FolderShare websites, and I've been really impressed by his passion about perf and the results. I hope to see lots of good posts coming up. Speaking of which, I realized I haven't had any technical posts for far too long. I need to get back to it!
FolderShare updates
12/3/2008 external link
Yesterday, we released a new version of the FolderShare web site and client. My team worked on the web site, which you might guess from the similarity to SkyDrive. In case you aren't familiar with FolderShare, it's an application that lets you sync files from multiple machines, peer-to-peer. I've been a happy FolderShare user for many years (since before Microsoft acquired it), and am glad to be a part of making it better. We did extensive usability testing on the core FolderShare scenarios and are really happy with the improvements we've seen with the new site. Before you ask, I can't comment on FolderShare future plans, but rest assured, it's not dead!
SkyDrive is out of beta
21/2/2008 external link
We released SkyDrive to 38 more regions, we're out of beta, and we now give everyone 5 GB of free storage. See the team post for details.  We also made some significant performance enhancements that hopefully everyone should notice.
Why do iTunes updates keep making me reboot?
15/1/2008 external link
Very annoying...
A WPF Framework
8/1/2008 external link
Rob Eisenberg posted a new WPF Framework here. I haven't looked at it in detail, but it looks pretty interesting!
More SkyDrive goodness
11/10/2007 external link
We've updated SkyDrive with some nice new features. One of the biggest hassles with SkyDrive before that was that it was hard to invite new people or add new contacts to the list. We now allow you to add new contacts (whether or not they have Live IDs) and people will be sent invites. If they don't have a Live ID, they'll have the opportunity to set one up. This should make sharing much nicer. Another thing we added is RSS feeds. For example, the feed to my public folder where I put blog related stuff is: http://cid-f9dac4c43e9a681d.skydrive.live.com/feed.aspx/Blog For more details on the new features, see the SkyDrive blog.