Thursday, September 11, 2008

VistaBridge, Task Dialogs, and WPF

Update: problem solved. See here.

Task dialogs and the other new Vista UI features are pretty nice, aren't they? Sure they are, unless you're using WPF, in which case you've probably been frustrated by the lack of a WPF-able managed wrapper. There was speculation that .NET 3.5 would include one, but, alas, it didn't. We'll see what happens at PDC 2008 next month.

There are quite a few .NET wrappers scattered about, but both WPF and .NET developers seem to have been plagued by "entry point not found" problems when the application tries to find the TaskDialog and TaskDialogIndirect functions in comctl32.dll at runtime.

The VistaBridge SDK sample was the one library that promised to be WPF-friendly, but many developers appear to have been having the same problem with entry points using VistaBridge.

Everyone understands, I think, the basic problem: task dialogs require version 6.0 of the common control library, but applications load earlier versions by default (for compatibility reasons, I suppose). Manifests are the answer, but even with a proper manifest the problem persists.

After a good deal of hair-pulling, I finally have VistaBridge working in an application, and I thought I'd pass along what I found. (The following assumes that you've been able to build VistaBridge.dll itself, which is the VistaBridgeLibrary project of the VistaBridge solution.)

First, you need to create a manifest that specifies version 6.0 of the common control library. Here's one (fix the name and description!):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="msil"
name="bitsy.exe" type="win32" />
<description>Description of Application</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>
Call this "MyApp.exe.manifest" (using your app name, of course) and put it in the base folder of your project. Now follow these steps:

  1. If your solution is open in VisualStudio, close it.
  2. If you've previously built your project, delete the bin and obj folders, which you'll find immediately under your project folder. I've found that this step is critical--it won't work if you don't do this, even if you do a full rebuild.
  3. Copy VistaBridge.dll to your project folder.
  4. Open the project in VS.
  5. Add the manifest file to your project.
  6. In the Application tab of your project properties, select your manifest from the Manifest dropdown.
  7. Set the Copy to Output Directory property of the manifest file to "Copy always".
  8. Add a reference to VistaBridge.dll (right-click References, choose Add Reference, open the Browse tab).
At this point you should be able to use the library. There are examples of how to do this in the VistaBridgeDemoApp project. (The task dialog definitions are in the window resources in Window1.xaml.)

For completeness, I should add that there is one issue: the designer seems to have significant problems with some of the classes, including TaskDialogProgressBar and others. If you use these, the designer won't load the window, but it will still compile OK. That's been my experience, anyway. Maybe someone more experienced can take the next step and find out why this isn't working.

1 comment:

David Veeneman said...

Thanks, Chris! I had been struggling with the 'entry point not found' error all afternoon, and was having no luck implementing a manifest. I followed your prescription (especially deleting the bin and obj folders), and I'm up and running.

BTW, for other readers: No need to change the manifest to app.manifest or MyApp.vshost.exe.manifest. The directions work exactly as printed.