Scott Hanselman

Speeding up a Slow Outlook 2007

April 15, '07 Comments [10] Posted in Tools
Sponsored By

Outlook 2007 has been pretty slow for me since I installed it. If you've got RSS Feeds Enabled and/or if you're a packrat, Outlook 2007 can be a downright performance pig. I've got internal contacts that say that the Office team is hot on the tail of a number of really interesting issues.

What can you do today? A patch KB933493 went live yesterday to help speed up access to large PSTs and OSTs. For now, you have to go get it. We'll see what the future holds for this, but I suspect that Office SP1, whenever it comes out, is going to be a very snappy performer.

Initial reports on this patch are positive. Searches are faster, Undos are faster, moving messages is faster, and moving quickly while reading in the preview pane is faster. The future bright on this one...I was really starting to get bummed about Outlook's performance.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Custom Cultures - WinForms Font Embedding Code with Ethiopian Amharic for Vista and XP

April 14, '07 Comments [4] Posted in Africa | Internationalization
Sponsored By

Even though my wife is Ndebele (Zulu) and we are trying to teach Z that particular Bantu Language, my first Linguistic African Love was Ethiopian Amharic. I almost majored in this stuff and I actually met my wife while I was speaking Amharic to one of her longtime college friends. Here's a small primer on Amharic I did in 2005 and there's a good basic Amharic Dictionary online here, that will exercise your fonts and mind as well. If you want to hear the languages, there's an Amharic audio dictionary here, or if you know me in person, I'll teach you some. Heck, if you know me, you know that'll be a long conversation because I love this stuff.

If you're running Windows Vista, you already have the Amharic Unicode Font "Nyala" and Input Method Editor installed! You can visit this test page to see that the Amharic support is quite complete on Vista. Here's my name in Amharic: ስካተ. If you aren't running Vista then you'll likely see black squares.

If you're running Vista, try this out. Go to the Control Panel and run the Regional and Language Options. Go to the Keyboards and Languages tab and click Change Keyboards. Don't worry, I won't break anything on your system, promise. Amharic is am-ET, by the way, compared to en-US or en-GB.

Click over to the Language Bar tab and make sure that Docked in the Taskbar or Floating on the Desktop is checked. You'll see your existing culture appear in the Language Bar - mine is in the tray.

Run Notepad, then go back to this menu and click Amharic.

You can always remove this by going BACK to the Control Panel and just Removing the Amharic Language.

While you're in Notepad, you're going to type "Thank You" in Amharic, which is pronounced (roughly) "Amäsägnalähu." Amharic is an "abugida" አቡጊዳ (not quite a syllabary) kind of like Katakana in Japanese, and with most Input Method Editors for languages with a lot of characters that are entered with an English keyboard, there's a mapping. You type and English Transliteration, and the IME gives you possible characters.

Amharic has no official transliteration, so this IME is kind of the standard, but there's always been arguments about the best way to describe the vowels. There are more vowels than in English, including a non-vowel-vowel.

Back to the point. In Notepad, type, using an English Keyboard:

  1. a-downarrow-space (this is a special character, that I can't see how to type without the down-arrow)
  2. m-e
  3. s-e
  4. g-'
  5. n-a
  6. l-e (the "e" is pronounced like "ay," by the way.
  7. h-u-space

You've just typed አመሰግናለሁ (ameseg'nalehu) which is one of the ways to say Thank You in Amharic. If you speak Japanese or another Asian languages you're likely used to using an IME like this. Notice how Notepad's support for Unicode means that it doesn't care about this new languages. It's just rolling with it.

Evil Black Squares

Be sure to know the details in Joel's classic Unicode post if you're doing international work and check out my Internationalization (i18n) Category. This "black square" issue is common when the system doesn't have a font available to render a Unicode code point, and since it's not legal to distribute that Ethiopian Nyala Vista Font outside the operating system by just copying it, how would an Ethiopian write and application and have it work on Windows XP. Surely a company in Ethiopia might want to defer upgrading to Vista (even though it includes all this great support for Amharic, including the custom IME (Input Method Editor)) for a while to save costs. This issue of course, applies to many languages beyond Amharic, and that's why I'm interested.

I've been bugging Michael Kaplan about this for as long as I've known him. It should be easier to create WinForms applications with cultures that don't include as much support as the Asian Languages. Plus, when a new OS like Vista comes out, how can we pass on the benefits to XP?

 At my urging Michael has created a great multi-part series on Font Embedding such that a person could develop on Vista and a downlevel OS could still work - even without the font installed, without violating the EULA.

In the screenshot above, we see a WinForms app running on XP. The OS doesn't have the font, but the font HAS come along for the ride as the app was built on Vista using this Font Embedding Technique.

 This will allow folks to develop Amharic Language (and other language) applications under Windows Vista and run them elsewhere. This is a huge accomplishment, in my opinion. Thanks Michael for your work!

I hope that folks tell Michael and Microsoft that this is a significant business scenario and encourage them to advance Michael's Sample Code into a full-fledge and supported feature in WinForms.

NOTE: You'll have to build the sample on Vista first in order to get the font. To get this sample running on XP, build it on Vista - note the creating of the font .bin file - and then run it on an XP box.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Managing Change with .NET Assembly Diff Tools

April 14, '07 Comments [1] Posted in Programming
Sponsored By

Sometimes you find yourself wanting to compare two versions of a .NET assembly as a way getting your head around all the changes that might be happening a your project. Perhaps you're writing a Framework for consumption by other developers.

There's a few different kinds of change you want to concern yourself with.

First is the "public face" of your assembly - the interface or 'linking' contract it makes with other assemblies that might choose to reference it.

Second is the semantic contract that is made. Most folks expect certain things of your assembly. They give you two "1's" and they expect a "2" in return. Sometimes people start to rely on bugs and you have to make breaking changes.

Breaking changes like deletion or modification of existing assemblies can, of course, wreak havoc.

One word to describe the changes that happen between versions - and many versions over time - is "churn." What percentage of the "surface area" of your assembly has changed? If a large number of things change it implies that the assembly is still being actively designed, or that the problem area isn't well understood. If very few things change and/or what does change is only additive, it implies that the assembly is fairly stable and can be counted on.

Here's some tools I use to get an understanding of what's changed between binary versions of an assembly, without resorting to source-level diffs.

  • LibCheck - The Standard. And oldie and a goodie. We use this tool to create reports that can be generated as part of your Continuous Integration build. The reports can be given to Project Owners (non-developers) and downstream consuming developers and gives them a very clear picture of what's changed; what should we worried about, test harder, and what should we worry less about. It also helps catch inadvertent breaking changes.
    • "This tool allows you to compare two versions of an assembly, and determine the differences. The tool reports the differences as a combination of 'removed' and 'added' APIs. The tool is limited to looking only at APIs (i.e., it can't check for behavioral changes), and only compares public differences, or changes which are deemed to be 'breaking.' The tool can be used to quickly determine what has changed between one version of your assembly and another, and can help ensure that you won't introduce any breaking changes to clients of your assembly. Instructions and intended use of the tool are described in the 'libcheck tool specification' document with the zip file"
  • Reflector Diff Add-In (a member of the Reflector Add-Ins Family with source available) - This tool by Sean Hederman plugs into Reflector and shows you the differences between two binary assemblies. More low-level than LIbCheck, but again, useful when you don't have source lying around.
  • NDepend - A must-have tool for Lead Developers and those who have to manage large numbers of projects and seek to understand the big picture. Version 2.1 added a Build Comparison feature and extended the already powerful CQL (Code Query Language) to support queries across features. You can see what code metrics have changed between two versions, and answer questions like "did this project get more complicated in this version, or did our recent refactoring actually reduce complexity. Check out the screencast here and download here. It also integrates nicely with source level diffs, so you can jump from the macro-view to a micro-view and back.

Being acutely aware of what's changed and avoiding the surprise of a breaking change can greatly reduce the stress level of your whole team as you deliver. I use all three of these tools and I encourage you to check them out.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 59 - Hanselminutiae #3

April 13, '07 Comments [3] Posted in Podcast
Sponsored By

My fifty-ninth podcast is up. Carl and Scott discuss the weeks events in their technology lives, in this 3rd Hanselminutiae. Who are the Spyware People? Is the AppleTV any good? What's your backup strategy? And Scott's Dad gets a Mac.

ACTION: Please vote for us on Podcast Alley! Digg us at Digg Podcasts!

Subscribe: Feed-icon-16x16 Subscribe to my Podcast in iTunes

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Telerik is a new sponsor. Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

  • The basic MP3 feed is here, and the iPod friendly one is here. There's a number of other ways you can get it (streaming, straight download, etc) that are all up on the site just below the fold. I use iTunes, myself, to listen to most podcasts, but I also use FeedDemon and it's built in support.
  • Note that for now, because of bandwidth constraints, the feeds always have just the current show. If you want to get an old show (and because many Podcasting Clients aren't smart enough to not download the file more than once) you can always find them at http://www.hanselminutes.com.
  • I have, and will, also include the enclosures to this feed you're reading, so if you're already subscribed to ComputerZen and you're not interested in cluttering your life with another feed, you have the choice to get the 'cast as well.
  • If there's a topic you'd like to hear, perhaps one that is better spoken than presented on a blog, or a great tool you can't live without, contact me and I'll get it in the queue!

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Fusion Loader Contexts - Unable to cast object of type 'Whatever' to type 'Whatever'

April 13, '07 Comments [2] Posted in Learning .NET | Programming
Sponsored By

It's funny how things you don't think about for a long time appear in twos or threes. This issue came up at work twice recently, and once via an email from a blog reader.

I blogged about part of this in 2004 when we were dealing with a lot of the icky complexities of the Loader (Fusion) in .NET. We used Mike Gunderloy's 2003 Binding Policy Article an a lot of testing to figure out how Fusion worked for us. We also are HUGE fans of Richard Grimes' amazing Fusion Workshop as a resource. Also, I just keep Fusion logging (FORCELOG) turned on all the time and logging to c:\fusionlogs.

Anyway, the issue was this error message about an InvalidCastException: 

System.InvalidCastException was unhandled
Message="Unable to cast object of type 'Plugin.Person' to type 'Plugin.Person'."
Source="LoaderContextSample"
StackTrace:
at LoaderContextSample.Program.Main(String[] args) in C:\LoaderContextSample\Program.cs:line 29
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

This can be initially very confusing because it says it's trying to cast type Person to type Person. Why aren't Person and Person the same, eh, Person?

Suzanne Cook puts it best, emphasis mine:

For example, path matters when determining whether a type is castable to another type. Even if the assemblies containing the types are identical, if they're loaded from different paths, they're considered different assemblies and therefore their types are different. This is one reason why using contexts other than the Load context is risky. You can get into situations where the same assembly is loaded multiple times in the same appdomain (once in the Load context, once in the LoadFrom context, and even several times in neither context), and their corresponding types won't be castable.

If you have an assembly you reference, but you also have a plugin that you've loaded, perhaps via LoadFrom (bad), if you intend for the types to be the same but they are loaded from different paths, they are effectively different types.

In this sample, I create a Person object via an assembly I've referenced the usual way, via Add Reference. Works great.

Then I load Person using Assembly.Load and create a Person via Reflection, then cast the object instance to the first kind of Person. Because I used Assembly.Load - usually the most appropriate Binding Context - the Loader (Fusion) finds the same assembly, and the Person Type created via Reflection is the same kind of Person as before. Works great. Note that Assembly.Load takes an Assembly Qualified Name like "Person" - not "Person.dll." Remember that Assembly QNs NEVER have .dll in their names.

Then I load the Person from a different path. In this example I've copied Person.dll to Person2.dll via a Post-Build-Event to illustrate this, but the most common way this would happen is that you've got a static reference to an assembly in the GAC, but your Plugin design uses LoadFrom to load a DLL from another path. Then you try to cast them. LoadFrom will almost always lead you astray.

If I was really serious I should have used the complete Assembly QN: Person, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, and I would have strong named it for Assembly verification purposes, but that's another post.

Here's part of the sample:

Person p = new Person("Franklin", "Ajaye");

//Use the Load Context...almost ALWAYS the right thing to do...
Assembly a = Assembly.Load("Person"); 
Type t = a.GetType("Plugin.Person");
object instance = t.InvokeMember(String.Empty,BindingFlags.CreateInstance, null, null, null);
Person p1 = (Person)instance;

//Use the LoadFrom...almost ALWAYS the *WRONG* thing to do...
Assembly a2 = Assembly.LoadFrom(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Person2.dll"));
Type t2 = a2.GetType("Plugin.Person");
object instance2 = t2.InvokeMember(String.Empty,BindingFlags.CreateInstance, null, null, null);
Person p2 = (Person)instance2; //BOOM!

Lucky Line 13 is where the InvalidCastException happens and I see the dialog pictured at the top of this post. Boom.

The Loader has a  lot of nuance, and it's helpful if you're building a large system with plugins and many points of extensibility to ask yourself - Where are my plugins on disks? What Types are shared? How are my plugins getting into memory?

Here's what we documented a long time ago. This only applies to dynamically loaded assemblies:

  • Assemblies will only EVER be loaded from the GAC based on a full bind (name, version, and public key token).  A partial bind with name and public key token only WON’T load from the GAC. 
    • If you reference an assembly with VS.NET you're asking for a full bind. If you say Assembly.Load("foo") you're asking for a partial bind.
  • However, the way this usually works is…
    • You do a partial bind on assembly name, or name and public key token with Assembly.Load
    • Fusion (the code name for the Assembly Loader/Binder) starts walking the probing path looking for an assembly that matches the partial bind.
    • Counter Intuitive: If it finds one while probing (the first one) it will then attempt to use the strong name of the one it found to do a full bind against the GAC.
    • If it’s in the GAC, that’s the one that gets loaded.
    • Any of that loaded assemblies will try to load from the GAC first without going to the probing path, since the embedded references constitute a full bind.
    • If they aren’t found in the GAC, then it will start probing.
    • It’ll grab the first one it finds in the probing path.  If the versions don’t match, Fusion fails.  If they do match, Fusion loads that one.
    • So, if you specify a partial name, and the file is in the GAC, but not the probing path, the load fails, since there’s no way to do a full bind.  

Here's the complete sample code from above if you like.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.