ComponentChk.cpp – I resolved my first C++ compiler "fatal error"!

Yes, for those of you with even more grey in your beard/hair than I, this is probably a “meh” event.  However, for me, who’s always looked at C++ code and wondered how the H*** anyone could ever make sense of it, this is a big event.  [Patting myself on the back.]


I’m working on finishing up the Setup bootstrapper for my VSTO add-in Word2MediaWiki.NET.  I’m targeting Word 2003 and Word 2007 (despite Microsoft’s best efforts/worst neglect to the contrary), and I’m trying to achieve what many have done before, but which seemed impossible for me: allow the Setup.exe to detect which version of Word is installed, and then conditionally install the prerequisite software (i.e. the so-called Office PIAs) for whichever version of Word is discovered.

Problem 1: most folks in the VSTO space seem to think that, despite the fact that a version of the .NET framework is required to support VSTO, the Setup.exe that goes with your VSTO add-in install package should use UNmanaged code to detect whether the pre-requisites are installed.

Problem 2: I know squat about writing unmanaged code.

Problem 3: Microsoft’s VSTO & Office teams left it up as an exercise to the VSTO app developer to figure out how to assemble the amazing number of parts necessary to make a VSTO install work transparently to the end user.

Problem 4: There’ve been many articles written posthumously (I mean, long after VSTO v2 was released) on various aspects of automating VSTO-add-in installation, but none of them addressed the very inevitable scenario where the app developer needs to support both Word 2003 and Word 2007.  [Don’t even *think* about pre-2003 versions of Office — you’d have to be clinically insane.]

Manna from heaven

One ridiculously brave soul, Mark Hogan, actually took the time to not only figure out how to build such a conditional pre-requisite detection app in C++, but he was so overcome with glee that he beat Microsoft at something even they were too scared to do, that he published the full set of source code and XML configuration files for the entire world to use.

Now, masochist that I am, I took it upon myself to try to integrate the code that Mark Hogan published into the existing code that I’d already slotted into my Office PIA bootstrapper files.  However, I didn’t anticipate the foreseeable result that, because I’m coding this stuff in my spare time, and usually late at night, I would (a) not finish the integration work in one sitting, (b) forget what I’d originally set out to do and (c) forget to integrate any of the critical code that actually performed the conditional logic.

Mike chases his tail

Miraculously, I was left with a .CPP file that would compile and that appeared to be significantly different from the original file I started from, and that threw off an error code that created a spectacular wild goose-chase:

“Unable to satisfy all prerequisites for Word2MediaWikiDotNET.  Setup cannot continue until all system components have been successfully installed.”


“Prerequisite check for system component Microsoft Office 2003/2007 Primary Interop Assemblies (Word Only) failed.

See the setup log file located at ‘C:\DOCUME~1\msmithlo\LOCALS~1\Temp\VSD33.tmp\install.log’ for more information.”

And in the INSTALL.LOG file was the illusory answer:

Running external check with command ‘C:\DOCUME~1\msmithlo\LOCALS~1\Temp\VSD33.tmp\Office2003PIAor2007_WordOnly\ComponentChk.exe’ and parameters ‘/delete /save /word {1EBDE4BC-9A51-4630-B541-2561FA45CCC5}’

“Process exited with code 1607”

Setting value ‘1607 {int}’ for property ‘SupportedWordVersionInstalled’

Setting value ‘1607 {int}’ for property ‘PIAsRegistered’

This led me down the path of chasing InstallShield errors, since the only Google search results that looked at all related were things like these.  After a few days of trying to figure out how the InstallShield scripting engine could be related to a Visual Studio SETUP.EXE or custom C++ application, I finally got my brain back and tried to isolate where in the code or configuration files the problem existed.  That led me to a line of C++ code that threw ERROR_UNKNOWN_COMPONENT, which as it turns out also shares the 1607 error/exit value.

[The whole gruesome story is illustrated in the Bug I filed to myself here.]

Back to the original goal, with a new mission

Once I realized what I’d left out of the C++ code, I quickly got it to the point where I could try compiling it.  Now a new mission emerged – how to debug a C++ compiler error?

C:\>cl.exe /Oxs /MT /GS ComponentChk.cpp advapi32.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

ComponentChk.obj : error LNK2019: unresolved external symbol __imp__WaitForInputIdle@8 referenced in function “int __cdecl MyStart(char const *,char const *)” (?MyStart@@YAHPBD0@Z)
ComponentChk.exe : fatal error LNK1120: 1 unresolved externals

That command line (cl.exe /Oxs /MT /GS ComponentChk.cpp advapi32.lib) was derived from the original article from which we were all working (or stumbling around half-blindly, it felt to me).  I just ran this without a second thought, assuming that since Mark Hogan didn’t seem to mention any modifications to it, any errors it showed must’ve been my fault.

Where is “__imp__WaitForInputIdle@8” I wondered?  It didn’t show up in the source code when I searched for it, and nor did “int __cdecl MyStart“.

After staring at this for a while longer, I figured some substring searches would work, which after a few attempts finally showed me that I was actually looking for the code

WaitForInputIdle(pi.hProcess, INFINITE);

which is called in the function MyStart().  I tried some silly things first, of course, but I eventually realized that if WaitForInputIdle() didn’t exist as a named function in the source code, perhaps it existed in another library that wasn’t yet connected to the code?  A quick MSDN Library search told me this function was actually part of USER32.DLL, and it wasn’t too painful a leap of logic to try adding USER32.LIB to the compilation parameters, like so:

cl.exe /Oxs /MT /GS ComponentChk.cpp advapi32.lib user32.lib

And when I loaded up the now-successfully-compiled COMPONENTCHK.EXE into DEPENDS.EXE, it confirmed exactly what I expected to see:


Mark, many thanks to you, and my apologies for calling into question your mad C++ skillz.

Do you Wiki? Word2MediaWiki.NET first release is live!


I just wanted to let my faithful readers know that I have finally completed a beta version of the Word2MediaWiki.NET add-in for Microsoft Word 2003.

This’ll be useful to anyone that regularly contributes to Wikipedia, or those that have a bunch of Word documents that they’d like to share on Wikipedia.

It’s just as useful for any of the other hundreds of wikis that use the same server software as Wikipedia (known as MediaWiki), and it’ll be of interest to those folks who’ve used Word2MediaWikiPlus (from whose VBA source code I converted much of the basis of Word2MediaWiki.NET).

Grab a copy here:

And please, let me know about any issues or experiences you have with it by posting a Discussion item here:

"Go/No-Go" Decisions on MyPicasaPictures, Attensa Sync to Google Reader, W2MW++

I’ve done a lot of investigatory work in the last few lunar cycles of different development projects I’d dreamed up.  However, after the investigation and the internal decision making was completed, I didn’t do a good job of “closing the loop” with any of you who have wondered “what happened all those projects?”.

I haven’t thought much about the royal “you” in this work — I’ve been sharing the steps and findings, but recently I started to wonder what people would think in the future if they happened to search on something that led them to one of these projects’ articles.  I’d feel pretty frustrated trying to find out where these things led (if anywhere) and where (if anywhere) there might be code that came out of these efforts.

Well then, it’s time to close the loop on these — at least, as much as I am “decided” on any of these so far.  That said, I’m never committed to any particular decision like this if any new evidence surfaces in the future to challenge my assumptions.  So if anyone is interested in picking up where I left off on any of this, drop me a line to let me know (I’m always interested in this kind of experimental work), and if you’d like to bounce some ideas off me, or see if I’d be interested in participating, I’ll always be open to such inquiries.

MyPicasaPictures: No-Go

Bottom line: while the effort to understand the VMC development environment was instructional and probably honed my ability to figure out what to look for in future explorations, my overall impression of MCML is that it’s just too damned hard for amount of value I might derive from it.

That, plus the chronic and unresolved stability issues I’m seeing with Vista Media Center (exacerbated by the merciless complaints and teasing I receive from my wife, who keeps saying “The XP box was much more stable, wasn’t it?”) have pretty much convinced me to pave the box, downgrade to Windows XP and to give Beyond TV a try.  [Their SDKs and more open, flexible architecture look like the perfect place to invest .NET development efforts, and the customer satisfaction with Beyond TV seems far superior to Windows Media Center, at least based on my initial research.]

Attensa Sync to Google Reader: No-Go

I had already decided to move from Attensa for Outlook to NewsGator Inbox, and then a few weeks ago NewsGator announced that their previously $30 Outlook client would henceforth be available for FREE to any and all concerned.

While there was no conversion possible from Attensa to NewsGator (well, I could import the OPML, but I couldn’t sync the “read/unread” status of all my articles, nor transparently migrate old articles to the new folder structure), everything else about this has been a positive experience.  I’m totally addicted to the NewsGator Mobile Reader for iPhone, and the fact that it syncs with my Outlook “read/unread” status is just awesome.  Congrats, NewsGator!

Attensa, I wish you luck in trying to survive the competitive pressures from NewsGator.  If I didn’t know better, I’d guess this is the beginning of the decline for Attensa, even though I think their Outlook client is superior to the current NewsGator Inbox offering.

W2MW++: Undecided

When I first read about the “export to MediaWiki” capability in OpenOffice Writer 2.3, I quickly concluded that any work I or the rest of the community had done for an Office add-in would become a moot point.  [Amusing but not-entirely-inaccurate Spoonerism: my wife knew a guy who insisted that the term was “a mute point”.]

However, after using Writer 2.3 to convert a few relatively simple Word 2003 documents to MediaWiki format, I realize that they still have a long way to go to preserve real fidelity of layout and formatting in Word documents.  I have faith that they’ll get there, and that eventually Writer’s integrated engine will become the translation engine for .DOC & .DOCX, but I now feel like there’s a significant unmet need that the work I’ve invested so far in W2MW++ could still address, and that that unmet need will exist for quite a while yet.

That said, there’s one thing that’s been bugging me for a few months now: the name.  WordToMediaWikiPlusPlus is a clever extension of the Word2MediaWikiPlus project, and it makes obvious the heritage of W2MW++, but it makes it sound like the project is more “hardcore” than it really is.  If I had my druthers, I’d rename the project “Word2MediaWiki.NET” (W2MW.NET), to make it clearer that the project is based in .NET code, not C++.  I’d hate to think anyone would be disappointed by the fact that it’s written in one of these “shiny new” languages — there’s something more “honest” or “obvious” about using the “.NET” suffix instead.

Now all I have to do is figure out how to Rename all the dozens of “++” references throughout the project AND figure out how to get a CodePlex project renamed.  [THAT should be fun :)]

Codeplex Licensing: Who controls license to my projects? Not I, apparently

Man, does this ever kill the relationship I thought I was building with the Codeplex team.   A few weeks ago I got another RSS notification from one of my Codeplex projects that the License to the project had changed (AGAIN).

In my interpretation of the world of software licensing, the License Agreement is a contract between the author of the software and the users of it.  I have the impression that these License Agreements carry the weight of law behind them, and that as such there should be restrictions on who can and cannot change the terms of the contract.

The way I see it, and unless I can find some text to the contrary in the Codeplex Terms of Use, the person who creates the Codeplex project is the only one who should be able to make any changes to the License — and even then, they should be very careful not to make frequent or arbitrary changes to the License (so as to provide as stable a set of expectations as you can with your users).

Codeplex: No Respect For Licenses

So why is it that the License for my CacheMyWork project has changed (TWICE), without my consent or participation?  I’ve looked over the Terms of Use published on the Codeplex site, and I can’t find any warning or mention of Microsoft or the Codeplex team monkeying with the License for any project:

“Microsoft does not claim ownership of the materials you provide to Microsoft…or post, upload, input or submit to any Services or its associated services for review by the general public, or by the members of any public or private community, (each a “Submission” and collectively “Submissions”).”


“Microsoft does not control, review, revise, endorse or distribute third-party Submissions. Microsoft is hosting the CodePlex site solely as a web storage site as a service to the developer community.”


“…Microsoft may remove any Submission at any time in its sole discretion.”

I see nothing claiming that Codeplex or Microsoft reserves the right to alter, update or otherwise affect any License agreement attached to any current projects.  I do not believe that this is an implicit right of the Terms they have published, nor of the kinds of services that are being provided here.

SourceForge: The Opposite Extreme

Out of curiosity, I decided to examine the Sourceforge Terms of Service:

“ reserves the right to update and change the Terms, including without limitation the Privacy Statement, Policies and/or Service-Specific Rules, from time to time.”


“In addition, the content on the Website, except for all Content, including without limitation, the text, graphics, photos, sounds, sayings and the like (“Materials”) and the trademarks, service marks and logos of COMPANY contained therein (“Marks”), are owned by or licensed to COMPANY, subject to copyright and other intellectual property rights under United States and foreign laws and international conventions.”


“Except for Feedback, which you agree to grant COMPANY any and all intellectual property rights owned or controlled by you relating to the Feedback, COMPANY claims no ownership or control over any Content. You or your third party licensor, as applicable, retain all intellectual property rights to any Content and you are responsible for protecting those rights, as appropriate.

With respect to Public Content, the submitting user retains ownership of such Public Content, except that publicly-available statistical content which is generated by COMPANY to monitor and display project activity is owned by COMPANY.

By submitting, posting or displaying Content on or through, you grant COMPANY a worldwide, non-exclusive, irrevocable, perpetual, fully sublicensable, royalty-free license to use, reproduce, adapt, modify, translate, create derivative works from, publish, perform, display, rent, resell and distribute such Content (in whole or part) on and incorporate Content in other works, in any form, media, or technology developed by COMPANY, though COMPANY is not required to incorporate Feedback into any COMPANY products or services. COMPANY reserves the right to syndicate Content submitted, posted or displayed by you on or through and use that Content in connection with any service offered by COMPANY.

With respect to Content posted to private areas of (e.g., private development tools or Mail), the submitting user may grant to COMPANY or other users such rights and licenses as the submitting user deems appropriate.”


“ fosters software development and content creation under Open-Source Initiative (“OSI”)-approved licenses or other arrangements relating to software and/or content development that may be approved by COMPANY. For more information about OSI, and OSI-approved licenses, visit

Use, reproduction, modification, and ownership of intellectual property rights to data stored in CVS, SVN or as a file release and posted by any user on (“Source Code”) shall be governed by and subject to the OSI-approved license, or to such other licensing arrangements approved by COMPANY, applicable to such Source Code.

Content located on any subdomain which is subject to the sole editorial control of the owner or licensee of such subdomain, shall be subject to the OSI-approved license, or to such other licensing arrangements that may be approved by COMPANY, applicable to such Content.”

My interpretation of these Sourceforge terms is that they’re at least as generous as the Codeplex terms, and they are much better specified.  It’s as if the Sourceforge leaders took their responsibilities seriously, whereas the Codeplex leaders still consider this a *Microsoft* project, where they can make arbitrary decisions just as Microsoft always does with their customers’ welfare.

Would you feel comfortable hosting your source code on the Sourceforge site?  I would.

Google: Somewhere in the Between-Space

Compare also to the Google Code Terms of Service:

“Google claims no ownership or control over any Content submitted, posted or displayed by you on or through Google services. You or a third party licensor, as appropriate, retain all patent, trademark and copyright to any Content you submit, post or display on or through Google services and you are responsible for protecting those rights, as appropriate. By submitting, posting or displaying Content on or through Google services which are intended to be available to the members of the public, you grant Google a worldwide, non-exclusive, royalty-free license to reproduce, adapt, modify, publish and distribute such Content on Google services for the purpose of displaying, distributing and promoting Google services. Google reserves the right to syndicate Content submitted, posted or displayed by you on or through Google services and use that Content in connection with any service offered by Google. Google furthermore reserves the right to refuse to accept, post, display or transmit any Content in its sole discretion.”


“Google reserves the right at any time and from time to time to modify or discontinue, temporarily or permanently, Google services (or any part thereof) with or without notice. You agree that Google shall not be liable to you or to any third party for any modification, suspension or discontinuance of Google services.”

Pretty spartan, but still more specifics in their terms of what rights you receive and give up than the Codeplex service.

If I was starting over…

If I had to choose it all over again, and if I knew I had equivalent IDE integration for any of the source code management add-ins, I’d have a hard time choosing among them.  Currently, the fact that all four of my projects are hosted on Codeplex is a significant barrier to hosting any project on any other site.  The next strongest reason keeping me on Codeplex is that I understand the basics of how to check-in and check-out my code using the Visual Studio integration with TFS — not that it means I find it brainless or foolproof, but it happens to be the source code management system I know best right now.  [As well, I continue to figure that I’ll focus my development skills in .NET, which likely will work better in Visual Studio, which is investing heavily in TFS integration and adoption – and I suspect if I ever get into coding for work, that I’ll have the TFS infrastructure available to really exploit for our projects.]

What about Sourceforge?  I like that it’s the first one out there, and I imagine it’s been held to a higher standard (by the zealots of the open-source community) than any other site — which is goodness.  However, I don’t “get” Subversion or (the older source code management tool), and I must admit I’m put off by the number of stale or poorly-used projects littering the Sourceforge site.  I imagine that Codeplex will look similar, given the same amount of time, so this isn’t a knock against Sourceforge but rather just a reflection of its age and roots.

What about Google Code?  Despite my better [i.e. paranoid] judgment, I’ve become a fan of Google’s services, and I really appreciate the ability to easily leverage all their “properties” in what appears to me to be a cohesive fashion.  I’m also thrilled that most of their properties are frequently updated, and that the updates focus on the kinds of changes that I usually appreciate seeing.  At this point I haven’t looked much deeper into it, but if it was possible to test it out, I probably will.

If I was running Codeplex…

If I could sit down with the Codeplex team, I’d tell them this:

  • You should feel free to publish any updated licenses you wish, and make them available at any time
  • You should NEVER alter ANY of the properties of any of the hosted projects on Codeplex, let alone the License for any project

It’s possible the database admins are simply updating database records for the existing licenses, rather than inserting new records for each new or updated license

  • If you don’t want to make available “older” licenses because you think that would be too confusing for Codeplex users, then at least leave the existing licenses in place, but mark them such that they cannot be assigned to new projects.  There should be NO excuse why you can’t leave existing projects alone, and allow the project coordinators to choose when or if to update the license on their project.
  • If you’re simply updating the existing licenses for the purpose of streamlining, constraining or clarifying the licenses attached to Microsoft projects, then you ought to be publishing Microsoft-specific versions of these licenses, since the changes you’re making to the existing licenses are having unintended consequences on those non-Microsoft projects that also use those licenses.
  • Ideally, however, you should be able to publish and maintain multiple versions of each license, and to be able to publish new licenses as well.  If the GPL can manage three different versions of their license, and if these are really simply database records (with “published on” and “version” metadata attached to each) then there should be no excuse why Codeplex cannot keep multiple versions of its licenses online at the same time, and leave the existing projects’ licenses ALONE.

Having worked at Microsoft for six years, I saw firsthand how arrogant and ignorant Microsoft can be about the impact of sweeping decisions they make, since most of those folks have never been responsible for large populations of users before, and they rarely have had exposure to an environment where their decisions (no matter how foolish or under-thought) are openly challenged.

I wouldn’t be surprised if the Codeplex team was no different; in fact, I’d be surprised if they were even measured on such end-user impact.  There’d sure be no incentive for Codeplex management to care, since (a) there’s no revenue to be gained or lost by poor or quality service, and (b) there’s no revenue to be “stolen” from a competing service (since all the major online code repositories charge nothing for their service, and their advertising revenue must be pretty thin).

I’m hopeful that the Codeplex folks wise up and take their responsibilities more seriously, but after the catastrophic database failure of last year, plus this half-arsed attitude towards the legal aspects of this service, I’m not going to make any bets on it.

If anyone has any suggestions on how I could help remedy either the Codeplex situation or my own desire for a better service (to which I could quickly adapt, given my sorry skills), please speak up – I’d love to hear it.

MyPicasaPictures Part 2: Rolling up my sleeves, sketching out a Spec

I find that the more time I spend detailing exactly what features and behaviours I expect from something I’m building, the faster and more successfully I’m able to actually build the thing I’m seeking.  This is a truism of technology development (and an old boss would say, of project management), whether you’re a one-person shop or a team of thousands.  However, it’s a lesson each person has to learn and digest to be able to figure out exactly what works best for them.

mini “Functional Spec” for MyPicasaPictures

Here’s a list of the features I’ve dreamed up so far, and the priority (1=high, 3=low) I’m personally assigning to them:

  • Pri1: upload a currently-selected Picture to (the default, if such a thing exists) folder/album/library (or whatever Google calls its collections) on the photo-sharing server
  • Pri1: enumerate and select the working folder/album/library when there are multiple folders to choose from
  • Pri1: authenticate to remote server
    • Pri3: cache remote server’s credentials securely, using DPAPI
  • Pri2: view names and/or thumbnails of pictures already in the selected remote folder/album/library
    • Pri3: enumerate and present the other metadata associated with each picture (e.g. Tags) and each folder/album/library
  • Pri2: write the code so that it abstracts the service-specific logic – enabling future versions of this app to easily add support for other server-based Photo sharing sites such as Flickr, Windows Live Spaces, Facebook, etc.
  • Pri2: Assign a new tag for a photo that has already been uploaded
    • Pri3: enumerate existing tags from remote server, and allow user to assign tag(s) from that set (along with new tags not part of the existing enumeration, in a mix-and-match formation)
  • Pri2: collect tags from the user for photo about to be uploaded, and submit the tags simultaneously (if supported by the photo-sharing service) with the upload, or right afterwards (if simultaneous isn’t supported)
  • Pri2: upload a batch of photos all at once (i.e. entire contents of a local folder that has been explicitly selected by the user).  Note: this may not be possible, as buttons or other controls cannot be added to the existing VMC UI.
    • Pri3: pick & choose a set of photos to be uploaded (e.g. subset of a single local folder, subset of photos in > 1 folders)
  • Pri2: delete existing photos in online albums (one at a time)
    • Pri3: delete existing photos in online albums in a batch (e.g. a subset of one album, or a subset of photos that span multiple albums)
  • Pri3: resize the photo(s) before they’re uploaded
    • Pri3: enumerate and present “spinner”-based choices control for the user to select one of the photo sizes “supported” by the remote server (if there’s any sort of default/preferred sizes that the server chooses to assert)
  • Pri3: rename the to-be-posted picture where another of the same name already exists on the remote site

Questions that keep coming to mind

  1. How do I implement client-side support for a SOAP- or REST-based Web Service in MCML apps?
  2. What “model” should I aspire to use for this kind of development? [cf. Gang of Four]
  3. Where will the entry point(s) for this add-in be located?  Steven Harding crystallized a suspicion I had been gathering on this topic – “Unfortunately, you can’t add anything to an existing Media Center interface.  So there’s no “Send This Folder to Picasa/Flickr” possible.”
  4. What exactly is a Start Menu Strip, and why are only two of them allowed at one time (and why does VMC seem to “punt” the oldest one out unceremoniously when a third is added)?
  5. What is the real difference between a VMC application and a VMC “background application” (other than the obvious visibility issue)?  i.e. Under what circumstances would I want to use one approach and not the other?
  6. What does “running on the public platform” mean in terms of (a) additional functionality that’s possible, and (b) what kinds of security restrictions are lifted on apps running on that “public platform”?
  7. If the More Information (“i” button) is so strongly discouraged, how should we provide that kind of “added functionality” in context of the application, ONLY when the user wants it, and WITHOUT cluttering up the UI in a way that makes it harder for most users to get their basic needs met?
    • Should we use a horizontal, multi-layer menu that’s presented on the Recorded TV screen?
    • Should we try the vertical stack of buttons that stay resident for all contexts, such as you see when you browse the detailed info for a Movie?
  8. Why is it that 3rd parties can’t add controls to the VMC UI, but Microsoft gets to change the user experience whenever they please (e.g. with the “Internet TV (beta)” object that quietly inserted itself – without asking, and without giving me any visible way to opt out – on the TV menu strip a few months ago)?
  9. What parts of the VMC UI are off-limits to third-parties?
    • Adding new objects to existing Start Menu Strips?
    • Adding new objects to existing “More Information” context menus?
    • Adding new sorting/filtering options to existing collections of content e.g.
      • I’d love to add “Show only Movies” to the “By Title” and “By Date” choices currently enabled in the Recorded TV collection
      • I’d give my left…toe to be able to sort a TV show’s episodes by the “Originally Broadcast” date, so I could accumulate a bunch of episodes of some show and then watch them in the order they were meant to be seen, not in the order they happen to have been recorded
    • Adding new tiles to the “More Programs” collections that are buried one click away from the Start Menu?


  • 🙂 “I’ve watched a video on Channel 9 where Charlie Owen and a programmer (Mark Finocchio?) demonstrate how to do basic MCML.  That was slightly more illuminating (though it took 35 minutes to get to the programming), but then I discover that you basically have to create your own buttons from total scratch. It really is back to the ark stuff.”


  • 😦 “I’ll check in to the ability to catch the More Information button — last I recall the handler is there but didn’t work exactly as planned.”  [sounds like one of those famous understatements of the year…]
  • 😦 “There are only the very basic visual elements – ‘Graphic’, ‘Text’, ‘Colorfill’ and ‘Clip’. Everything complex – like a button, menu, scroller etc. must be built from those four visual elements.” [also see 😦 ]
  • 😦 “This question comes up a LOT.  Enough that I covered it in my blog… Please check out the article called ‘Scope in MCML’.”

Next Steps

Here’s the list of beginner articles I’ve seen multiple folks point newbies at, to get a feel for what I’m about to take on:

  1. VMC SDK‘s “Step-by-Step” walkthrough (linked from the Windows Start Menu once you install the v5.2 or v5.3 SDK)
  2. MCML: UI’s (Steven Harding)
  3. UI Properties: Making UI’s Flexible (Steven Harding)
  4. Model-View Separation (Steven Harding)
  5. Stage 1: A Basic Layout (Steven Harding) through Stage 11
  6. GData .NET client library “Getting Started” guide
  7. cURL client for testing upload of files to Picasa

Source code to investigate: (as it might have some hooks already worked out that I won’t have to learn from scratch)

Picasa Web Albums Data API + Vista Media Center = MyPicasaPictures

I’ve found over and over, if I don’t upload pictures to the web when I first download them from my camera, then there’s little or no chance I’ll do it later.  Out of sight, out of mind.

But I wonder…

If I had an add-in command in the My Pictures sub-app of the Vista Media Center, would I be more inclined to upload pictures to the web then (and give my mom at least a glimpse into my life more than once a year)?

Google developer help: plenty

Since I’m already personally using Picasa’s companion Web Albums for what few pictures I’m sharing, I’m inclined to tie the online component of such an add-on to Google.

Having already investigated the Google APIs, I figured there was likely an API tuned for the Picasa Web Albums, and so there is.  Further, it appears that it provides the ability to post photos, create albums, update & delete photos, manipulate tags, and review existing albums/photos/comments/tags.  Sounds like it provides more than I was even looking for.

From what I gather with a quick skim, the basis for the “PWA” Data API is the Google Data API.  And while I don’t know whether it’s absolutely necessary, Google provides a .NET Client Library (currently v1.1.2) to speed web services client development.

Similar apps

Big Screen Photos v2 — the Yahoo Flickr client for Vista Media Center.  It doesn’t enable you to upload the pictures hosted in Media Center, but rather to view the pictures that are already available on the Flickr site.

Yougle Vista — provides access to online Video, Music and Picture sites including Flickr.  Still no upload capability.

PhotoConnect — extends My Pictures with some interesting functionality including the ability to email pictures to others.  However, it looks like this vanished in a puff of smoke and synthetic ash.

FlickrMCE — another viewing app, only for Windows XP MCE 2005.

PictureBook 1.0 — screensaver add-in, not really all that similar after all.

Windows Vista Media Center add-ons: sorting through all this new technology

Most add-ons for Windows Media Center 2005 (i.e. Windows XP) or earlier were written as “hosted HTML” apps that ran outside the Media Center shell.  Now, while hosted HTML apps may still work in Vista, the drive is towards either the MCPL/MCML or XBAP/XAML:

  • MCPL: Media Center Presentation Layer (the programming model)
  • MCML: Media Center Markup Language (the managed code language derivative)
  • XBAP: WinFX XAML Browser Application (the programming model)
  • XAML: eXtensible Application Markup Language (the language in which XBAP is more-or-less implemented)

However, it appears that the XBAP/XAML model has already been dumped by the eHome team.  Lovely, not even a year out of the gate and they already drop support for the “future-forward looking” programming model — I wonder what hurdles they had to clear to be able to explicitly drop support for the whole WPF (aka .NET 3.0) (aka WinFX) (aka WS-*) company-wide drive.?  Oh well, at least that’s one less choice to confuse me…but I have to bitch just this once: when can we abandon app-specific languages?  Any language or programming model that starts with the name of the vendor-specific technology makes me feel more than a little soiled.

Other resources that should prove useful

Some specific coding issues that I’ve noted for future reference

Interesting Tidbits

  • 🙂 Add-ins run out-of-proc in a hosted process called ehExtHost.exe, and communicate with the main Media Center process using .NET Remoting over “Named Pipes” (aka IPC within .NET).
  • 🙂 Media Center unloads the add-in when the Launch( ) method exit.
  • 🙂 The entry in More Programs is created by the running of RegisterMceApp.exe not by the running of the add-in itself.
  • 🙂 In an MCML application, you can only embed a couple of visual elements, NOT including ActiveX controls (i.e. no native Flash rendering).
  • 🙂 You can’t embed a WPF app / window inside of MCML.
  • 🙂 Charlie Owen has invited anyone to provide good/bad developer feedback on Media Center and the SDK, and left his contact info here.
  • 🙂 You can’t override ANYTHING on the Windows Media Center screens — if you want any new functions, they have to be added on completely new screens, which would mean re-building the whole ‘Videos’ library.


I’m not 100% convinced I’m going forward with this yet — I’m inclined to spec out the features, dig into the SDK/MCMLookalike/Codeplex-hosted sources to get a feel for just how much (a) volume and (b) complexity of code I’m facing, and then decide whether to keep pushing forward.  I’d sure appreciate feedback from anyone who has ever delved into any of these areas for encouragement or “there be dragons” warnings…

  • MCML programming
  • web services integration in managed code — Google or otherwise

Cheers all!

Porting Word2MediaWikiPlus to VB.NET: Part 13 (VBA Oddities)

[Previous articles in this series: Prologue, Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9, Part 10, Part 11 (The Return), Part 12 (Initialization continued).]

How to convert the VBA String() Function?

There’s a more-complicated-than-it-probably-needs-to-be subroutine in the Word2MediaWikiPlus codebase — called MW_SurroundHeader() — that seems to only be there to cleanup and reformat text in a Word document that has one of the Headings styles.  It uses a function from VBA called simply String(), which is one of the first cases of a VBA function for which I cannot find an equivalent in VB.NET.

It turns out I found out what I needed from an article, and after running into a few brick walls in looking for a reference to this in MSDN, I started a more intelligent search.  I kept coming back to references to the String Data Type, so I next looked at the “Strings in Visual Basic” topic that was referenced by “For more information on string manipulation…”.  From there the next most logical leap was to “Building Strings in Visual Basic“, which led to “How to: Create Strings Using a StringBuilder in Visual Basic“.

Once there, I figured that since this was so helpful to me, I’d like to save someone the trouble next time so I added a little of that “Community Content” sauce that I myself appreciate so much.

Converting the Selection Object from VBA?

The MW_FontFormat() subroutine also uses a no-longer-supported VBA-ism, the Selection object.  This isn’t all that well documented online either — or at least, I wasn’t able to find anything useful online to help figure out how to translate this into VB.NET.  The best I could find was a mention that the Range object in VB shares some common methods & properties with the Selection object in VBA.

However, I happened to have a copy of an old book called the Microsoft Office XP Developer’s Guide, which was surprisingly results-oriented for an MSPress book.  Pages 176-177 actually discuss “The Selection Object vs. the Range Object”, in which I am told that the Range object is actually superior to the Selection object, and should always be favoured wherever possible.

I’m not feeling up to the subtleties of Selection vs. Range right now, so I’ll leave this for another time.

Converting the Font Colour to HTML-compatible values?

This is another interesting puzzler… It seems that MediaWikiConvert_FontColors() calls RGB2HTML(), which calls OleConvertColor(), which calls OleTranslateColor(), which is a p/invoke to OLEAUT32.DLL.  [Man, this is starting to read like a book of the Old Testament…]

I have a really strong gut instinct that there’s a managed code equivalent to this that will make the intended conversion in one step, and I intend to find it.  There’s no good reason at this point to (a) have this many calls going on the stack, just to get access to a “simple” math function, or (b) to preserve an unmanaged call just because it’s been used all the way up to now.

I can think of at least three ways to try to find the managed class I’m after: search on OleTranslateColor, search on “RGB & HTML”, or start browsing books on managed web development.

According to this “Format Color for HTML” article, the call to OleTranslateColor is only necessary in cases where you’re using “system color constants” or “palette indices”.  Since we’re getting very predictable input here that doesn’t appear to be using either of these two alternatives, right away we should be able to eliminate the unmanaged code.

That is, if I’m reading this right, then I should just be able to remove OleConvertColor() from the initial call in RGB2HTML() and leave the first line of code as

nRGBHex = Right("000000" & Hex(rgbColor), 6)

However, upon double-checking, it seems that other code blocks on the VBA macro are passing in some of the Word.WdColor enumeration constants — which I assume are equivalent to “system color constants”.

Rather than have the RGB2HTML() routine always thunk down to unmanaged code, it’d be smarter if we checked whether the color value of interest is a member of the Word.WdColor enumeration.  But do the routines that generate the input parameter to RGB2HTML() generate either Long or WdColor values?  Or alternatively, would the code implicitly convert from WdColor to Long as the RGB2HTML() routine initialized?  I didn’t notice any overloaded instances of RGB2HTML() that took the input parameter as a WdColor value, so I have to assume that no matter what goes on outside this routine, all operations inside RGB2HTML() will only operate on colors of type Long.

If that assumption is correct, then we should be able to safely ignore the possibility that the input parameter may start out as a WdColor datatype, and that means we can safely eliminate the OleConvertColor() and OleTranslateColor() routines.  [For the moment, having already had to dig them back up once, I’ll just comment them out and leave myself a note to delete them once I’ve had time to test these colour conversions and confirm this assumption is true.]

Colours in VBA vs. Colours in .NET

A more interesting question, however, is whether we’re losing colour fidelity in the conversions being performed here.  According to VSTO For Mere Mortals, Chapter 4, “In VBA, colors are of type Long, and there are eight constants that can be used… In Visual Studio 2005, colors are of type Color, and there are more than 100 choices”.

Is it possible that the calls being used to derive the colours from the Active document are limited to the VBA colour constants, and that I should be looking to switch to other calls that return the .NET Color constants?  I’ll just add this as another Task to the CodePlex project list, and deal with it later — it seems to me like this is hardly the biggest problem facing this Addin at the moment.

Porting Word2MediaWikiPlus to VB.NET: Part 11 (The Return)

[Previous articles in this series: Prologue, Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9, Part 10.]

After a few weeks’ hiatus to work on some other projects (including a couple of releases of CacheMyWork — now with more filtering!), I decided to come back to the W2MWPP effort.  And my overwhelming feeling right now is: thank god I was blogging as I coded!  As it is, it took me probably a full hour to figure out where to focus my attention next:

  • while the Configuration dialog still isn’t finished, I’m going to set that aside for now — it should be pretty easy to figure out what I need to add, especially once I know better which functionality is or isn’t required.
  • I’m going to start into the fundamentals of the code that’ll be called when the “Convert to Wiki” button is clicked.  This code will be called by ThisAddIn.uiConvert_Click().
  • The code in question will be derived from the VBA project’s modWord2MediaWikiPlus.bas file, from the Public Sub Word2MediaWikiPlus() routine.

Sub Word2MediaWikiPlus(): Overview

There are many types of constructs in this library, many of which I’m sure will be called as part of the base Word2MediaWikiPlus() routine.  However, the routine itself is only about 150 lines of code, so in itself the routine shouldn’t be too difficult to implement.

However, it’s probably a good idea to familiarize myself with some of the constructs in this library:

  • There are three unmanaged code Functions — two for MessageBox construction, and one called SendMessage.  I’m sure I’ll understand what they’re supposed to be for once I see them in context, and likely I can use some very simple managed code Methods in their place.
  • There are Constants both private and public.  [Thankfully, most of these seem to have been reasonably well documented.]
    • Some, like WMPVersion, will be taken care of by Visual Studio.
    • Others, like WikiOpenPage, should be implemented as configuration settings not code constants.
    • The majority, such as NewParagraphWithBR, will likely be preserved as stylistic choices whose usage choices I may not personally agree with, but likely are things that have been requested over the years and which if I dropped them, would probably piss off a whole bunch of folks who’ve grown to know and love the VBA macro.
  • There are plenty of Variables as well of course, and while the usage of the majority will likely become self-evident, there are a few (e.g. Word97) that I can probably safely drop.
  • There are some constructs labelled as Types as well here — I’m not sure, but they resemble the use of Structures in managed VB, and I’ll likely see them in heavy use.

At this point, I’m going to implement these constructs as needed.  I’d rather not add all these up front, ’cause (1) it’ll be pretty confusing for me, and (2) there’s likely some code that is no longer needed (or even has been forgotten).

Sub Word2MediaWikiPlus(): Initialize ActiveDocument

Even before generating the first set of routines, I figured I should do what I could to setup the Class Library with a little forethought:

  • Added a new Class to the Word2MediaWiki++ project called “Convert.vb”
  • Wanted to add this class to a global W2MWPP namespace (see Part 4 for details)
  • I once tried to add a namespace designation to a project after I’d already started coding it, and it was a disaster — references broke everywhere, and I’m not sure I ever got it cleaned up
  • Not knowing enough about namespace and class naming, I flipped through a couple of the books I had on hand and determined that this should be trivial to do up front
  • I wrapped the Public Class…End Class statements with Namespace Word2MediaWikiPlusPlus…End Namespace statements, and proceeded onwards

The first sixty lines or so of code in Word2MediaWikiPlus() all have to do with acquiring a handle to an active document.  In the world of Document add-ins, I presume this can be very tricky, since the code itself starts from a single document’s context and has to navigate outwards from there.  However, when we’re working with VSTO Application add-ins, it seems fairly easy to me to get access to an active document.

In fact, for the purposes of this tool, I’m going to assume that the user wants to convert whichever Word document is the active document.  The only error condition I should need to check is that there is at least one document object open.  This leads to the following code:

            Dim App as Word.Application = Globals.ThisAddIn.Application
            Dim Doc as Word.Document = App.ActiveDocument

            If Doc Is Nothing
                'When there's no active document open just return back to Word
                Exit Sub
            End If

The only code left in the document initialization block is this:

    DocInfo.DocName = ActiveDocument.Name
    DocInfo.DocNameNoExt = DocInfo.DocName
    p = InStrRev(DocInfo.DocName, ".")
    If p > 0 Then DocInfo.DocNameNoExt = Left$(DocInfo.DocName, p - 1)

I was baffled by this, so a quick trip to MSDN Library cleared it up.  The macro appears to be trying to parse out the document Name without the file extension.  DocInfo itself is an instance of the DocInfoType Type, which is just a structure to store various properties of the document.  There’s no particular reason I can see so far to use a structure for the DocName & DocNameNoExt properties, and the other properties to me don’t seem particularly related to the document itself.  At this point, I’ll assume DocInfo isn’t needed.  [Certainly my searches of the modWord2MediaWikiPlus.bas source only found two references to the DocInfo.DocNameNoExt property: once to assist the MW_GetImagePath() function, and once to set DocInfo.Articlename.  Both should be doable without this Structure, since .NET provides a Path.GetFileNameWithoutExtension function.]

However, this leads to the MW_Initialize() function, which I would guess also should be part of the Convert class’ initialization code.  I’ll check that out soon.

The last of the code in this section is the call to MW_LanguageTexts().  This is a localization macro, that will set a series of Registry values and Msg_* variables depending on a language setting retrieved from the Registry.  All this can be managed quite well using Resource files, so there’s no need to mess with setting all this via code at the moment.

I’m interested in knowing whether all the Registry settings being used by this VBA project are for localization, so let’s enumerate them all…

Registry value Purpose
ClickChartText localization
EditorKeyLoadPic localization
EditorKeyPastePicAsNew localization
EditorKeySavePic localization
EditorPaletteKey localization
txt_Footnote localization
txt_PageFooter localization
txt_PageHeader localization
txt_TitlePage localization
UnableToConvertMarker localization
WikiCategoryKeyWord localization
WikiSearchTitle localization
WikiUploadTitle localization

Wow, what a…symphony of Registry settings here, only a handful of which are directly used for localization.  There’s quite a number of them used for various Image manipulation operations, and others for various application settings etc.  Generally, from what I can tell, there’s no reason these too can’t be stored in the project’s app.config file.

There’s the Msg_* variables as well – are all these devoted to localization as well?

Variable name Purpose
Msg_CloseAll localization
Msg_Finished localization
Msg_LoadDocument localization
Msg_NoDocumentLoaded localization
Msg_Upload_Info localization

Yes, that’s all of them.

Further Config and Init

The final bit of code I’ll deal with today is the “user dialog on config settings”.  It appears that this calls some additional initialization code:

  1. performs customization if never performed
    • opens the frmW2MWP_Config form
    • sets ImageExtractionPE Registry setting
    • sets the variables EditorPath, OptionHtml, OptionPhotoEditor, OptionPhotoEditor.Enabled
    • sets language settings
    • sets any configured customization settings from the Config form (aka the VSTO UI Config dialog)
  2. sets Article name
  3. sets convertImagesOnly = False
    • this variable is used in Word2MediaWikiPlus() to determine whether to convert the whole document or only the embedded images.
    • Since this is apparently never set to True, I’ll remove the references.
  4. checks Word version and sets some control characters
    • It doesn’t appear that we’ll need this, as VSTO only seems to support Word 2003 and above
  5. sets Image Path
  6. sets the image editor path
  7. caches the value of a couple of Word’s Tools, Options settings
    • I’ve commented in these commands in case they’re necessary later
    • However, I assume there are better ways of preserving Word’s initial configuration than caching before changes and then flushing after changes
    • That is, it should be possible to make per-session changes to such settings, without having to make sure that Word’s settings are explictly reconfigured after the session has completed


That’s enough for one sitting, eh?

CacheMyWork enhancements: Managed Stack Explorer ideas

Wow, what you can learn by perusing someone else’s code…

Cool Code: Managed Stack Explorer

I stumbled across the Managed Stack Explorer app on CodePlex, and as soon as I ran it I knew that it had some killer features I wanted to implement in CacheMyWork!

  1. It’s got a two-panel layout for (a) Processes and (b) the Threads in each Process
  2. More importantly, it’s got auto-resizing of these panels when the whole app window is resized (much like I want to have a panel for Applications and another for the Documents open in each Application).  Very slick-looking.
  3. Whenever you click on a Process in the left-hand panel, it updates a lower display of detailed information about the Process (much like I’d wanted to put in tooltips in CacheMyWork, but this might be even better).
  4. It has another panel that is initially collapsed, but that can be opened/expanded by the user, and possibly by the app in response to certain events (much like I’d wanted the Documents panel to initially be hidden and/or hideable, but able to be opened by the user or in response to certain events e.g. (a) click on a Process; (b) if the Process has Documents open, automatically open the Documents panel).
  5. When a new .NET application starts, the list of Processes in this application is automatically updated!


Makes me want to do it all now, but there are some questions to which I don’t know the answers right yet:

  • Is there such a thing (i.e. a native or custom Class available) to create a CheckListBox (as I have right now) that has multiple Columns?  Could the Columns be resizeable and resortable?
  • Does the auto-update of the Processes list require multi-threaded coding?

Reverse-engineering the code

It turns out that, for some unknown reason, when I download the source code and try to open the Design View on any of the WinForms classes (e.g. MainGui.cs, InfoSelect.cs), Visual Studio throws an error and won’t show me the visual design view.  That sucks, ’cause it’s a heckuva lot easier to explore the code by selecting the control(s) you’re interested in and jumping right to the relevant entry point.

Instead, I’ve spent a couple of hours poring over the MainGui.Designer.cs class, assembling a picture for myself of which components relate to which.  It was very instructive, but it felt kind of like trying to build a Lego model of a Tie Fighter in a pitch-black room:

  • I found out that the SplitContainer control class is what’s used to implement (1) and (2)
  • There are multiple SplitContainer objects in this application, nested one inside the other like those carved Russian dolls.
  • The SplitContainer object hierarchy appears to be like this (I’ve colour-coded the object names to show where they are in the UI below):
    • listsSplitData > ptSplitInfo & FixedPanel.Panel1
      • ptSplitInfo > processSplitThread & groupBox2
        • processSplitThread > processView & threadView
  • The other objects encapsulated in the SplitContainers are arranged:
    • groupBox2 > processDataLayout
      • processDataLayout > label1 – label 12
    • processView > ProcessName column, PID column
    • threadView > tid column, threadState column

This means the application’s UI is more or less constructed as follows:


I think I’ve done a decent job mimic’ing the SplitContainer usage demonstrated here, so all I’d like to do at this point is figure out how to create that right-column expand/contract control.  [I’ll leave the auto-update with new Processes behaviour for later.]

After jumping back & forth through the code a few times, it appears that:

  • The control I’m after is labeled viewStackTraceToolStripMenuItem.
  • It appears be to an instance of ToolStripItem and a child of a ContextMenuStrip, and has a single Click() Event Handler.
  • That event handler calls a routine threadview_DoubleClick(), which calls ShowSelectedThreadStackTraces().
  • The former routine calls ExpandAndCollapse(), which appears to be the magic behind the whole thing.

If I were to implement this routine or similar, then all I have to figure out is how they created the “>” control that expands & collapses the FixedPanel.