twitter
    musings about technology and software development..
Showing posts with label software. Show all posts
Showing posts with label software. Show all posts

Best feature of Outlook 2010

Office 2010 is almost ready to ship!  I'm an Outlook user by day, and Gmail user by night.  But I find that Gmail doesn't scale well when you are being flooded with e-mail -- for example, basic UI metaphors like shift-click don't work, and labels just don't cut it compared to Outlook rules.  So, here's my favorite new feature from Outlook 2010 for dealing with floods of e-mail:


Basically, it deletes any e-mails that are entirely contained within replies later in the conversation. This is great for high traffic discussion aliases and long-winded threads.  There's just something really gratifying about pressing a button and seeing half my Inbox disappear..

Windows 7 Shortcuts

Just thought I'd share some shortcut keys I use all the time:

Windows + D: Show Desktop
Windows + Tab: 3D Flip
Windows + #: Runs the #'th program on your Quick Launch

And in Explorer:

Shift+Right-Click on a folder/file: Additional options like "Open command window here"
Alt+Up: Goes up a folder level in Windows Explorer (plus Alt+Left/Right for Back/Forward)

Hard Drive Backup with Live Mesh

I hope everyone out there is backing up their data.  Up until now, I've used the tried-and-true method of copying my files periodically to another drive.  Of course, in the event of data catastrophy, I would lose all my changes since the last xcopy .. which was .. about 9 months ago.  A file backup gestation period, if you will.

In any case, I'm now using Live Mesh.  It's cross-platform and you get 5gb of online storage for free (you can sync unlimited data between machines).  I've synchronized my musics, videos, and documents between all my machines which is pretty fantastic.  In case you want to try it, here's what I would have liked to know beforehand:
  • You cannot synchronize your Desktop folder.
  • Your first 5gb of synchronized files ends up in the cloud. Choose wisely.
  • You have to login with a LiveID, but it doesn't share cookies with the browser.  So, if you will ever want to sync with a friend, create a new LiveID to share.
  • When you add a folder to be sync'd, it will show up on every other machine as a virtual folder.  This can be very confusing when you've named them all "Documents" -- prefix folder names with the computer name.
My next step is to set up a sync with my a friend in another state, in case my home with all my computers burns down.  Overall, it was pretty easy to setup, although I now have a paranoia that one node will decide to delete something, and spontaneously trigger all my files to be deleted on every machine simultaneously.

Concurrency bug..

OK, spot the bug in the code:

    object m_lockObject = new object();
    object[] m_collection = null;

    public object[] GetCollection() {
        lock (m_lockObject) {
            if (m_collection != null) {
                // already initialized
                return m_collection;
            }
            else {
                // needs to be initialized
                m_collection = new object[5];
                initialize(m_collection);
                return m_collection;
            }      
        }
    }
.. the bug is that a second call could come after m_collection is new'd up, but before it's initialized, resulting in an empty collection being returned.  The first call works, the second call sometimes fails, and the third call onwards likely succeeds.  Bugs like this can be a pain to track down as, depending on what these objects do, the symptoms will appear really strange...
If you think Microsoft code is bad, you should read DailyWTF.  It has great coding patterns like:
   try
   {
     int idx = 0;
     while (true)
     {
       displayProductInfo(prodnums[idx]);
       idx++;
     }
   }
   catch (IndexOutOfBoundException ex)
   {
   }
And sweet UI dialogs like:
   Cancel print job?
     OK | Cancel
And stories about "C-Pound".  Yes, geek humor.

Writing Office client code

Writing Office client code is ... an experience.

First, everything is in unmanaged code, which means each line of code takes 5 minutes to write.  Why?  Because you have to check the APIs every time, to make sure you know who owns the memory and what the exact parameters are.  If you don't, you will get an intermittent AV or corrupt the heap and crash the app.  And, since none of the APIs are documented, you have to go trolling through the sources to figure out what the hell's going on.

Second, you get to use classes with interesting names.  For example, their web service APIs are still called things like HSUser -- long live HailStorm!  Then you've got funny ones like “BpscBulletProof”, obscure ones like “MsoGelIInsertSortPx”, and classes like “MSOGRFXMLNS” (buy a vowel?).

Third, Office has wrappers for almost everything.  I started by writing everything in standard C/C++, and it all worked beautifully.  But that was a big mistake, because none of it worked once I tried to merge it into the code depot.  I wasted the better part of a week translating ATLSoap to CBaseHSUser, vector to MSOPX, CMap to LKRHash, RegQueryEx to MsoRegReadWz, CString to CMsoString, and the list goes on. 

Fourth, the wrappers are actually pretty neat -- until you have to debug one.  Good luck figuring out what the author's intention was for “const WCHAR* const *rgwzArg” or “MSOPFNSGNPX pfnSgn” (I couldn't make that up even if I tried).  The time I saved using a “convenient wrapper” is quickly negated by having to figure out why my memory keeps getting wiped out.  It's like that movie Memento, but with a lot more swearing.

I think that's enough ranting for one post, back to work.

Calling a web service from unmanaged code

Just wasted a few hours of my life with a seemingly trivial segment of code.  Spot the error:

   HRESULT hrInit = CoInitialize(NULL);

   CUserProfileWebService webService;
   webService.Execute();

   if (SUCCEEDED(hrInit))
      CoUninitialize();
I was getting an Access Violation when the application exited, which means I was trying to access memory that no longer belonged to me.  Turns out, the problem was due to scope.  The "webService" object doesn't fall out of scope until after CoUninitialize has been called, so it doesn't know to clean itself up until it's too late.  The fix is to enclose the webService variable in it's own scope, such as the following:
  HRESULT hrInit = CoInitialize(NULL);
  {
    CUserProfileWebService webService;
    webService.Execute();
  }

  if (SUCCEEDED(hrInit))
    CoUninitialize();
In this instance, “webService” will clean itself up immediately after the } curly brace. Of course, it took forever to narrow it down to these five lines of code, at which point I realized my mistake. *sigh*