shahine.com/omar/

homepage | Send mail to the author(s) contact

yet another Microsoft blogger

# Saturday, April 24, 2004

SeaTac sucks

SeaTac has the lamest TSA of any airport I've been to (BOS, JFK, DFW, IAD, SFO, SJC, ORD) recently. For the past two weeks I have returned from SeaTac on a Friday (both afternoon and evening). Both times the lines were 30+ minutes and they were operating less than half the scanners. Unbelievable. I don't understand why that airport is so freaking inefficient. Oh, and Dennis agrees.

I'll also add that there is no good food joint inside the security area. Mickey Mouse airport if you ask me. If they ever move the rental car area outside the main terminal area (like having to take a bus to the cars etc) then I'll just stop going ;-).

Posted Sunday, April 25, 2004    Permalink    Comments [9]  View blog reactions

 

AssemblyVersion build and revision number

The other day I was wondering where the AssemblyVersion build and revision numbers come from if you use the default synax in your AssemblyInfo files:

//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Revision
// Build Number
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:

[assembly: AssemblyVersion("1.0.*")]

Well it turns out that the build number is set to the number of days since a
random, designated start date, and the revision based on the number of
seconds since midnight.

It's interesting that it took 15 or so minutes on google to find this post that has this little nugget.

Posted Sunday, April 25, 2004    Permalink    Comments [1]  View blog reactions

 

# Tuesday, April 20, 2004

OneNote SP1 Preview Rocks

Chris Pratley has a write up on OneNote SP1 Preview. This is a huge upgrade and has lots and lots of new features. I've been running it for a few months now and love it.

Here are my favorites:

  1. Capture Screen Shots and Snippets.
  2. Scratch Out Gesture for Ink.
  3. Password Protection of Sections.
  4. Insert Meeting details from Outlook.
  5. Data Import API (I am writing two of the PowerToys that Chris talks about) ;-) and collaborating on a nice .NET managed API that hooks into OneNote's API.
  6. Lots and lots of Inking improvements. Inking feels much more natural.
  7. Insert pictures and documents.

Posted Tuesday, April 20, 2004    Permalink    Comments [1]  View blog reactions

 

# Friday, April 16, 2004

Creating Managed Outlook Buttons with Icons

I've been working on an Outlook Add-in in C# using the Visual Studio Shared Add-in project. I referenced this article on how to create a custom icon for your button: Custom Button Faces in a Managed Code Add-in for the Microsoft Office System

In addition to this article, most of the information I've seen on the internet and msdn discusses how to set the icon of a button (CustomFace) using the clipboard and calling CommandBarButton.PaseFace(). How ugly. Furthermore, if you do this then you cannot avoid the problems of the mask not getting applied (which looks really ugly, see the screenshot from the MSDN article).

You also  have to deal with issues such as saving and restoring the clipboard contents so that the user does not lose data.

If you are using Outlook 2003 there is a much better way. Here is how you do it:

Create Project

This article assumes you've created a Shared Add-in project already. For a good overview of this see http://blogs.msdn.com/dancre/archive/2004/03/21/93712.aspx

Create Bitmaps of Icons

  1. Using your favorite bitmap editor (I just use mspaint.exe) create a bitmap that is 16x16 px and paste in the icon you wish to use.
  2. Again, using the same bitmap editor create a second bitmap for the mask. This bitmap should contain white for any region that you want to appear transparent, and use RGB (0,255,0) for any area that you want to appear in the CommandBarButton.

    For example, say we want to use the Bold icon. You would create a bitmap like this:

    And the mask would look like:

     

  3. Save both the bitmap as "bold.bmp" and "bold_mask.bmp".

Create Resource Files

Now we want to add these two bitmaps to a resource file that we can embed in our assembly. I used the instructions on Custom Button Faces in a Managed Code Add-in for the Microsoft Office System with some modifications.

Build the Resource Editor that ships with Visual Studio

  1. Go to localdrive:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Samples\Tutorials\resourcesandlocalization\reseditor
  2. Run build.bat

To add items to a resource file by using the Resource Editor:

  1. In the Resource Editor, in the Add section, select System.Drawing.Bitmap as the type of item to add to the resource file from the drop-down list.
  2. In the text box to the right of the Add section, type bold as the name of the first item to add. This enables the Add button.
  3. Click Add.
  4. Type bold_mask as the name of second item to add and then click Add.
  5. Next, click File and then click Save As. . .
  6. Type IconResource.resX as the name for the project and browse to the parent directory of the sample add-in project.
  7. In the Save as type list, select ResX Files (*.resX) and then click Save to save the resource file
  8. Close the Resource Editor.

Add the resource file to your project, and set the Build Action to Embedded Resource.

Create the Buttons and set the Picture and Mask properties

Now we can create the buttons and set the Picture and Mask properties of the CommandBar. However, you cannot just use this code:

object missing = Missing.Value;
 
CommandBarButton outlookButton = (
CommandBarButton)commandBars["Standard"].Controls.Add(
MsoControlType.msoControlButton, missing, missing, missing, true);

toolbarButton.Style = button.ButtonStyle; try { ResourceManager rm = new ResourceManager( this.GetType().Namespace + ".IconResource", this.GetType().Assembly); using (Bitmap bmp = (Bitmap)rm.GetObject("bold")) { if (bmp != null) outlookButton.Picture = bmp; } using (Bitmap bmp = (Bitmap)rm.GetObject("bold_mask")) { if (bmp != null) outlookButton.Mask= bmp; } } catch { }

You see CommandBar.Picture and CommandBar.Mask do not accept bitmaps, but an instance of stdole.IPictureDisp. Great, so how does one create such an object? Not so easy. Thanks to this article though there is a solution. First you need to create this class:

using System;
using System.Drawing;
using System.Windows.Forms;
using stdole;
public class AxHost2 : AxHost
{
    public AxHost2() : base(null)
    {
    }
    public new static IPictureDisp GetIPictureDispFromPicture(Image image)
    {
        return (IPictureDisp)AxHost.GetIPictureDispFromPicture(image);
    }
}

This class inherits from System.Windows.Forms.AxHost which has a protected member GetIPictureDispFromPicture which will return an IPictureDisp  from an Image. So now that we have this class, we can modify the code above to read like so:

using (Bitmap bmp = (Bitmap)rm.GetObject("bold"))
{
    if (bmp != null) outlookButton.Picture = 
     (IPictureDisp)AxHost2.GetIPictureDispFromPicture(bmp);
}
using (Bitmap bmp = (Bitmap)rm.GetObject("bold_mask"))
{
    if (bmp != null) outlookButton.Mask= 
     (IPictureDisp)AxHost2.GetIPictureDispFromPicture(bmp);
}

And that's it. Now you don't have to use the Cliboard and PasteFace to create your icons.

Posted Saturday, April 17, 2004    Permalink    Comments [8]  View blog reactions

 

Bay Area real time traffic

http://www.zipdash.com/map/?city=94043

Posted Friday, April 16, 2004    Permalink    Comments [0]  View blog reactions

 

Office 2003 Primary Interop Assemblies Installation

I'm working on a cool Outlook .NET Add-in that target the Office 2003 PIAs. I just read this post from Brad Abrams that points to this new article which discusses designing Office XP add-ins and Office 2003 add-ins by using the .NET Framework.

Well imagine my horror when I read this:

You may redistribute Office XP PIAs. When you redistribute an Office XP PIA, you must install the Office XP PIA in the GAC. However, you must not deploy an Office 2003 PIA. When you build an add-in that targets Office 2003, you must exclude the Office 2003 PIAs from the Setup project. When the add-in loads in the target Office 2003 application, the add-in will correctly use the PIAs in the GAC at runtime. The add-in will correctly fail if the PIAs are not found in the GAC. The add-in will not fall back to load any other version of the PIA.

Crap! I thought. Correctly fail? Gee how nice. Can't I make it easy for my users to use my add-in? You see the PIAs are not installed by default when you do a typical setup of Office 2003. I don't really understand why they aren't, *but* it appears that they will get installed on-demand. Assuming that you have you local cab installation files for Office 2003 cached, or easy access to the CD or share where the files are located, Outlook will go and install the PIAs when your add-in loads for the first time.

I need to double check this on a clean machine (will use Virtual PC for that) and make sure that this is correct. If it is then I'm psyched. If not, then I'll be pretty pissed cause it's quite a pain to install them and telling end users to do that is just a headache.

Posted Friday, April 16, 2004    Permalink    Comments [2]  View blog reactions

 

# Wednesday, April 14, 2004

Dictionary Tool update and source

I've been meaning to get to this for a long time, and finally did.

I created a GDN Workspace for Dictionary Tool for Tablet PC. This is a Tablet PC PowerToy that I released last year. It was the first .NET code I had ever written and a few months ago I went back in there and fixed a few bugs, and ported it to C# from VB.NET. It's amazing how much I've learned in that time so I re-wrote a bunch of silly things (looking at your old code is funny some times).

Anyway, the most notable changes are:

  • Supports importing of txt files that have non ASCII characters correctly.
  • Support Backup of your custom user dictionary.
  • Support Restore of your backup to the user dictionary.
  • The UI looks like an XP App (back then I didn't know about Application.EnableVisualStyles();
  • Only works with .NET Framework 1.1 (sorry, no time to test on 1.0).
  • Resizing and non standard Windows resolutions should be fixed.
  • Fixed a bug when entering an empty string into the add text field.

I haven't tested the app extensively, but it seems to work just fine ;-). If you have any problems with it please let me know or file a bug in the workspace.

You can download 1.0.1 from here.

Posted Thursday, April 15, 2004    Permalink    Comments [0]  View blog reactions

 

# Tuesday, April 13, 2004

NewsGator for Media Center

I've been using this for a few weeks and it's dammed cool. Check your RSS feeds while being a couch potato using Windows Media Center 2004. It even streams videos from feeds such as Channel 9.

Posted Tuesday, April 13, 2004    Permalink    Comments [0]  View blog reactions

 

# Thursday, April 08, 2004

Bedlam

When I joined Microsoft this story was already very famous. There have been a few instances since then where people would reply to mysterious DLs saying take me off this and then the flury of replies. However, someone who has been here long enough usually says “remember bedlam”.

Posted Thursday, April 08, 2004    Permalink    Comments [0]  View blog reactions

 

# Wednesday, April 07, 2004

Caltrain Express Service starts June 7th

In what has to be some of the most exciting news for my commute, Caltrain is set to launch it's Baby Bullet Express service which will get me from San Francisco to Mountain View in 45 minutes (currently it takes anywhere from 69-78 minutes). Right now, I can currently drive from SF to MV in about 45 minutes which makes the current commute time on the train less than appealing.

The big day is June 7th.

Posted Wednesday, April 07, 2004    Permalink    Comments [0]  View blog reactions

 

# Sunday, April 04, 2004

Entourage: A journey to becoming an Office application

It’s not often that a new Office application is born. That’s especially true on the Mac. This is a story about Entourage, a product that was called Alpaca for the longest time.

I joined Microsoft in January 1999. At the time, the team I joined was publicly working on Outlook Express 4, 5 and secretly building a Personal Information Manager for Mac Office. When we started the project we shared very little to no Office code. Over a 2 year period we morphed into a product that shipped in the Office box. The first thing I got to do when I joined was basically run the Outlook Express 5 project. I was 22 years old. Can you imagine showing up at a Company and being given responsibility like this? It was just unbelievably exciting (coincidentally, my soon to be roommate, Jimmy Grewal, was given similar responsibility on Internet Explorer). Two 22 year old punks who never shipped anything in their lives shipping what became the most popular browser and mail client on the Macintosh. I remember going over to Apple for meetings some times and they would be like, are you kidding? Where are your parents?

Outlook Express was actually a new name for a product that was called Internet Mail & News. No offense to the people who worked on this, but compared to the competition, IMN was a crappy mail product. Microsoft hired a lot of people from Claris and Apple who helped take the IMN code and build OE. Development and features were added at warp speed. However, the group building Outlook Express and IE were folded into the MacBU about 6 months before I joined. At that point OE was viewed as a product that would grow to become the PIM for Mac Office. Since Windows Office had Outlook, we needed something similar on the Mac. At the time there wasn’t a viable product that offered all the functionality of Outlook in a single application. So when I joined we were all really working on Entourage 2001. At the time, we managed to convince upper management (mainly Ben Waldman, our General Manager and Kevin Browne, our Lead Product Planner and soon to be General Manager) that we needed to do another release of OE to stay competitive and compliment IE 5. It really wasn’t until MacBU took on our group that OE was given any attention. Before that, IE was the sexy product and the one that got most of the attention and resources. Office changed all that.

I remember sitting in a room with a bunch of people and trying to convince Ben Waldman that OE 5 was a good idea (this ultimately meant sucking resources away from Office, the big money maker, for a free product). Somehow we were successful, but I remember being scared to death. So the OE 5 project was born and I got to pick the code name [update: corrected mistake per this post from my first manager]. We called it Newman, after the mail delivery man on Seinfeld. He was famous for saying “When you deliver the mail, you control Information”. The code name for Entourage was harder to select. We had some bad ones, but finally, Jud Spencer settled on Alpaca. If you have ever flown Alaska Airlines you’ll note the Alpaca ads that they have in there. “Alpacas, the huggable investment”. If you watch CNN late at night you’ll also see the commercials. Alpaca would remain the code name and the actual product name till months before RTM… finding a name that no one else was using was next to impossible (remember, dotCom days).

Anyway, OE & Entourage were native Mac applications (no ported code, and no Office code), and we didn’t really follow the methodologies that the rest of Office followed. Entourage, OE and IE were developed in North San Jose, while the rest of MacBU was in Redmond (PowerPoint was in Cupertino). None of us had any exposure to the long established processes of the rest of the business unit, and we all got a crash course.

In addition to being a kick ass mail product we also had to build a calendar, contacts, tasks and notes interface, support internet RFCs like iCal, vCard, and create a data store for all this data. We also had to interoperate with numerous different products (wire protocols, authentication, meeting requests, e-mail formatting etc). On top of that we had to have some features that leveraged the fact that we were an Office suite, and of course we had to “Look and Feel” like an Office application.

That final sentence was the source of so much contention, especially for me. Remember, we were a native Macintosh application. Office still had a lot of legacy code, non native Mac UI, and other things. So “Look and Feel” like an Office application sometimes meant look and feel less like a Macintosh application. Let me give you some examples.

Icons

In Outlook Express 5 we wanted to have a fresh and pretty look and feel. I went out and hired the Icon Factory to design about 120 icons from scratch. These were 256 color icons, a big deal in that day. The Icon Factory OE 5 page states: “The goal of the project was to give the entire OE icon suite a cleaner, more "mac-like" look and feel.” By comparison Mac Office and Win Office were limited to 16 colors. And they were the most saturated and ugly 16 colors on the planet. We were “told” that we would have to take our beautiful 256 color icons and make them only 16 colors. Ack! That was battle number one. I tried to convince Office to move their toolbars to 256 colors but it was deemed too expensive. Ack! I panicked. In the end we managed to change the 16 colors to a more muted and pleasant 16 colors, redid most of the Mac Office icons in these new 16 colors and updated the Entourage icons to use the same palate but we could keep our 256 colors.

Preferences

Mac program had their preferences menu in the Edit menu. Office programs have their Preferences menu in the Tools menu. Guess where OE and Entourage had theirs? One of my favorite accomplishments was getting all the rest of Office to do things like a proper Mac application ;-).

Toolbars

Outlook Express and Entourage had docked toolbars while Word, Excel, PowerPoint had global toolbars. Our toolbars were contextual (they changed depending on where you were in the application) where the others were always global and static. We were told to change our toolbar to be more like Office. Well, that was another long battle that we thankfully compromised on by promising to at least make our toolbars look like Office. However, since we didn’t’ share any code with Office we had to write our own implementation. For Office X we ended up throwing this all away when our new Toolbar implementation for Office (to support 32 bit icons) was done.

Spell Checking, Autocorrect etc.

There are many features that are just expected of an Office application. Two of those are spell checking and autocorrect. These were enormously complex things to do. Our application was built on a Macintosh development framework called PowerPlant. Meanwhile Office had its own custom framework and a lot of work was done on both sides to factor our applications such that we could use Office components without the massive overhead of supporting the office framework in its entirety. This was really hard stuff to get right, but when we did it was just so cool to have the red squiggly. We never did grammar checking.

Shared Features

There were lots of ideas for shared features. Some of them never saw the light of day, and others took a very long time to get right. One of these was the Word/Entourage integration. The idea being that you can access the Entourage address book from Word for composing letters, inserting contacts and customizing Word templates based on your personal information (we created the notion of a “Me” contact in Entourage, that allowed us to do some cool things like auto fill personal information in Word templates, or get driving directions to and from people’s work and home addresses via Expedia). This work required a lot of collaboration between to teams that sat many miles away and didn’t always see eye to eye. In the end the feature worked, and worked well, but it was another one of those amazing learning experiences. There were many more of these shared features. They all required extensive work on both ends. We were really building the bridges between Entourage and the rest of Office that would then be used for many years to deliver much more advanced and user centric features that really leverage the entire Office suite (Project Center in Office 2004 is a good example).

Anyway, our team learned a lot in becoming not just an Office app, but in becoming a team and an integral part of the success of the suite. For the next project, Office X, Entourage was the first application to get Carbonized. Because we didn’t share much code with Office, and because we were the youngest code base it only took a few months to get us running on X. It took many more months to make our Look and Feel stunning on OS X and the good news was that the rest of Office really had to purge a lot of the old crust to get to X. Since X was all about a new Look and Feel called Aqua, this was a boon for us, and it meant that all of Office got 32 bit icons. A far cry from the 256 colors in 2001! We also got more and more Office functionality as a result and that was great. Entourage really started to become the hub of Office, and that is so very true in this year’s release.

Posted Monday, April 05, 2004    Permalink    Comments [15]  View blog reactions

 

# Friday, April 02, 2004

System.Drawing.Image Performance Update

Update: I've been informed that using the method below can have significant consequences in the future. Using private reflection isn't a good idea because the private methods can change in the future and this code WILL BREAK. Be forewarned.

Well, thanks to Justin Rogers you can have lightning fast loading of Jpeg images w/o having to wait for a Service Pack or get a hotfix from Microsoft as I recently blogged about.

I tested his code and found no difference in speed between the method I was using and his method. Since using his method will work on .NET Framework 1.1 it's the preferred solution. You still need permission to run Unmanaged Code.

One way to handle the need for Unmanaged permission is to add this attribute to the function and then add a try/catch and use the regular method in the catch:

[SecurityPermission(SecurityAction.Demand, 
Flags = SecurityPermissionFlag.UnmanagedCode)] public static Image FastFromFile(string filename) { try { filename = Path.GetFullPath(filename); IntPtr loadingImage = IntPtr.Zero; if (GdipLoadImageFromFile(filename, out loadingImage) != 0 ) { throw new Exception("GDI+ threw a status error code."); } return (Bitmap) imageType.InvokeMember("FromGDIplus",
BindingFlags.NonPublic |
BindingFlags.Static |
BindingFlags.InvokeMethod,
null,
null,
new object[] { loadingImage }); } catch (SecurityException) { return Image.FromFile(filename, true); } }

Posted Friday, April 02, 2004    Permalink    Comments [1]  View blog reactions

 

Laptop gripes

Dennis just wrote about some laptop frustrations. I have to agree. I can't tell you how many times I've closed my laptop lid, placed it in my bag and opened it back up on the train a 30 minutes later to find the battery half drained. Since I refuse to install any of the Toshiba Power management software for my Tablet PC (because it locks it up from time to time) I get about 1.2 hours of juice as my tablet runs at full bore the whole time.

Today I flew up to Redmond and for the first time in my life forgot my power brick. What a disaster. This made me wonder why the world needs 25 different kinds of power tips and adapters. Can't the manufacturers just agree on one common plug and then design DC adapters that aren't ugly and huge but smart and small, include cable management and can dynamically adapt to charge any laptop? Then I could just borrow one from anyone with a laptop.

Apple has always made superior laptops. They just work, aren't ugly with dozens of panels, protruding pieces of plastic and boneheaded design placement like my microphone that is located right near my loud fan. Oh, and lets not even mention the 15 or so “stickers that come on the thing. That's just tacky. I'm not sure this will ever change. The business that OEMs are in require that they compete on price, so they'll never spend the kind of money Apple does to make their stuff sexy and functional. If you don't know what I'm talking about, go to an Apple store and play with a 15 or 12 inch PowerBook. Notice the clean design, smart placement of panels, lack of stickers and panels, fluid lines, pulsing LED lights, keyboard controls that have stunning On Screen UI, and ambient light detection for back lighting the keyboard etc.

Posted Friday, April 02, 2004    Permalink    Comments [2]  View blog reactions

 

# Monday, March 29, 2004

System.Drawing.Image Performance

As I mentioned earlier, I wrote an application called JPEG Hammer for manipulating and viewing EXIF data in digital photos. As a .NET Application the single biggest performance bottleneck has been:

Image photo = Image.FromFile(fileName, true);

For a 6.1 megapixel (3008 x 2000) 1.47 MB JPEG it took on the order of 631 milliseconds to load. Multiply this by 50 or so photos and you are talking about 32 seconds to fully load these pictures. Then add the time necessary to draw the UI for the app, update thumbnails etc. On a 1.8 ghz Pentium 4 I'd expect more... and lets just say it's no where near as fast as the XP Shell (or other non .NET phot apps), so what gives?

Well, after much Googling (with no success) I tried http://support.microsoft.com/ and I came across this gem (Microsoft KB 831419):

FIX: Slow performance when you call System.Drawing.Image.FromStream to load a bitmap image

So, curious as I am, I get my hands on this hotfix which updates:

  • System.Windows.Forms.dll
  • System.Design.dll
  • System.Drawing.dll

Specifically, this update adds a new method to System.Drawing.Imaging:

System.Drawing.Image.FromStream(Stream stream, bool useICM, bool validateImageData)

This is essentially a new signature for an existing method:

System.Drawing.Image.FromStream(Stream stream, bool useICM)

As you can see, validateImageData is a new parameter. Setting it to true is the default behavior that we have today (essentially the same as calling FromStream(Stream stream, bool useICM)).

So I made a change to my application. Before my code looked like this:

using (Image photo = Image.FromFile(this.fileInfo.FullName, true))
{
    //do stuff
}

So I changed it to:

using (FileStream fs = new FileStream(this.fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite))
{
    using (Image photo = Image.FromStream(fs, true, false))
    {
        // do stuff
    }
}

And here are the results. The average time it took to process 37 JPEGs taken from the same camera and roughly the same size went from 631ms to 6.76ms. So, this new method is 93x faster. Holy Cow!!! I thought that maybe something was wrong, so I re-ran the tests many times, and always got the same result. Simply mind boggling. This probably brings the .NET implementation to the same speed as writing native C++ code against GDI+.

The good news is that the article mentions that this fix will get rolled into the next Service Pack. However, you'll need to modify your code as I did to take advantage of this.

Update: you can download this fix in SP1 of the .NET Framework 1.1:

http://www.microsoft.com/downloads/details.aspx?FamilyID=a8f5654f-088e-40b2-bbdb-a83353618b38&DisplayLang=en

Posted Monday, March 29, 2004    Permalink    Comments [6]  View blog reactions

 

# Sunday, March 28, 2004

dasBlog log relief coming soon

For those of you that are finding your log directories are > 100 MB you’ll be happy to see the screenshot below. Each time a new log file get created, a process is queued to archive the previous day’s log file.

Posted Sunday, March 28, 2004    Permalink    Comments [3]  View blog reactions