So I’m going through the Windows Media Center Application Step by Step guide (which incidentally, is in the XPS format — Microsoft’s pretender to the PDF throne, and a risky choice for any application to choose ahead of the widespread adoption of the underlying platform). I’ve gotten as far as to add the References to the MediaCenter assemblies, when I realize (for the first time) that developing a Media Center application might very well mean that I have to have the development environment installed on a Media Center PC.
This seems like an odd dependency to have, considering all the other types of development projects that don’t necessarily require you to run your IDE on the target platform. So I’m wondering if there’s a way to either (a) just drop the assembly files (i.e. the DLLs) into the expected directory and just reference them & go, or (b) I’ll have to figure out how to register those assemblies on my non-Media Center system.
On pages 5 and 6 of the Step by Step guide the instructions indicate to add references to the Microsoft.MediaCenter.dll and Microsoft.MediaCenter.UI.dll assemblies. While it assumes you’re working from a Vista Premium/Ultimate machine and have those assemblies in the %SYSTEMROOT%\ehome folder, I found that copying those files from the VMC box and browsing to their copied location on my Windows XP SP2 system seemed to resolve the references just fine. [I’m not convinced there won’t be other issues later on, but it’s at least worth a try.]
What’s The Sample Code Doing?
The code going into Application.cs looks interesting, but without any Comments to help us understand the purpose of each line, it’s not very instructive. For me, this is all I’m able to infer:
- we’re creating an Application class (though I don’t know what VMC developers would think of as an “application” — an add-in? a piece of UI? an assembly? the whole Media Center process and children?)
- we’re creating three Properties, both a private instance and its public instance (though I don’t really have any specific idea what these properties are meant to do)
- the Application “object” is overloaded, but I’m not even sure if it’s a Property or something else
- there are references to this, but I don’t really know what the “this” is referencing — is it the Application class, or is it something else? [It doesn’t help that I’m not an expert at coding, so I don’t intuitively recognize what each of these things are, but it sure would help to reinforce my tentative steps into this if I had Comments that told me what I was looking at.]
I’m also puzzled by why this code doesn’t follow the Design Guidelines for Managed Class Developers, when nearly all managed code published by Microsoft adheres to these standards. For example,
public void DialogTest(string strClickedText)
does not need “str” to prefix the ClickedText variable (aka Hungarian notation) — Visual Studio will always indicate the datatype with tooltips.
As another example, the private member variables
int timeout = 5;
bool modal = true;
string caption = Resources.DialogCaption;
are all named using Camel case but without any prefix (such as a leading “_” character). I understand that the Design Guidelines don’t specifically call out prefixing rules for member (? or private ?) variables, but apparently the guidelines do recommend the use of “this.” to prefix instance variables (which is awful confusing, as you can see above). Personally I’d prefer to see “_” or “m_” prefixes on private member variables, but I’d at least like to see *some* consistency in the use (or non-use) of prefixes on variables.
While prefixing is a religious fight, the use of Hungarian is not — it’s clearly not recommended.
I followed the Step by Step through to Build the Solution, at which point I got back one error in the compiler, at Line 55 of my code:
‘MyProject.Resources’ does not contain a definition for ‘DialogCaption’
If I followed the code adequately, the Step by Step has a bug (or at least an ambiguity) in the step Add Resources.resx/Add Strings. Whereas the Step by Step guide actually wanted me to create one String called “DialogCaption” in the Resources file, I understood it to instruct me to create two Strings — one called “Name” and the other called “Value”:
It seems pretty obvious now, but at the time my interpretation seemed intuitive.
After resolving that more trivial issue, the next Build confronted me with this error:
The command “%windir%\eHome\McmlVerifier.exe -verbose -assemblyredirect:”C:\VS2005 Projects\MyProject\MyProject\bin\Debug” -directory:”C:\VS2005 Projects\MyProject\MyProject\Markup”” exited with code 9009.
This turned out to be harder (and dumber) to diagnose. There were no specific errors related to McmlVerifier and 9009, and the first real lead from Google referred to path quoting issues. I finally realized that the McmlVerifier.exe file didn’t even exist on my XP (development) system. Strangely though, it didn’t exist on the VMC system either – is this one of the SDK tools? Yes. However, for some reason the SDK didn’t install it into the %windir%\ehome directory.
Once I copied McmlVerifier.exe to the ehome directory, the Build completed successfully.
Strangely, most of the steps under Enable UI Testing and MCML Verification (steps 7-17) were redundant – they were already completed on my behalf.
When I tried Debugging the solution, I got yet another error:
System.DllNotFoundException was unhandled
Unable to load DLL “EhUI.dll”: The specified module could not be found.
(Exception from HRESULT: 0x8007007E)
However, this time when I merely copied EhUI.dll to the %windir%\ehome directory, the Debugger threw another exception, slightly more impenetrable:
System.DllNotFoundException was unhandled
Unable to load DLL “EhUI.dll”: The specified procedure could not be found.
(Exception from HRESULT: 0x8007007F)
The stack trace for this was:
at Microsoft.MediaCenter.Interop.RenderApi.SpWrapBufferProc(ProcessBufferProc pfnProcessBufferProc, IntPtr* ppNativeProc)\r\n
at Microsoft.MediaCenter.Interop.RenderApi.InitArgs..ctor(MessageCookieLayout layout, ContextID idContextNew, ProcessBufferProc pfnProcessBufferProc)\r\n
at Microsoft.MediaCenter.UI.MessagingSession..ctor(UiSession parentSession, ContextID idLocalContext, TimeoutHandler handlerTimeout, UInt32 nTimeoutSec)\r\n
at Microsoft.MediaCenter.UI.UiSession..ctor(ContextID idLocalContext, IServiceProvider parentProvider, RenderingInfo renderingInfo, EventHandler rendererConnectedCallback, TimeoutHandler handlerTimeout, UInt32 nTimeoutSec)\r\n
at Microsoft.MediaCenter.UI.UiSession..ctor(RenderingInfo renderingInfo)\r\n
at Microsoft.MediaCenter.Tools.StandAlone.Startup(String args)\r\n
at Microsoft.MediaCenter.Tools.McmlPad.Main(String args)
Given that I’ve got the Vista version of EHUI.DLL in the right place, I assumed I’d have to “register” it (I forget the equivalent in the .NET Framework world) so that its procedures could be “found”. However, before going down a “.NET theory” path I decided to google the error message. The first five or so forum posts that came back pointed finally clued me in that in fact this may represent a second-order dependency in another missing DLL. With that, I decided to just copy in the entire contents of my VMC’s %WINDIR%\eHome directory and retry debugging.
Debugging exponentially: Process Monitor, Dependency Walker
That wasn’t any more successful, so next I fired up Process Monitor and watched for any “NOT FOUND” errors that followed the EHUI.DLL load event (hoping that this was merely a case of a missing filesystem reference, and not something more sinister). That helped me discover the following errors (presumably, as is often the case in these situations, mostly a list of false negatives):
- McmlPad.exe called RegCreateKey() for HKLM\Software\Microsoft\Fusion\GACChangeNotification\Default
- McmlPad.exe failed to find OLE32.DLL under C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727, and oddly didn’t try searching the environment’s PATH locations
- devenv.exe searched multiple times for C:\temp\symbols.flat.txt and McmlPad.pdb (symbols) under C:\temp\symbols\McmlPad.pdb\6B1042D64F29479FA1C07939AE072D941\, C:\Windows\symbols\exe, C:\Windows\exe, C:\Windows
- McmlPad.exe failed to find C:\WINDOWS\assembly\GAC\PublisherPolicy.tme (and didn’t look anywhere else)
- McmlPad.exe tried looking for a couple of files in the GAC search paths before it went looking directly for the file in C:\Windows\ehome:
- Once McmlPad.exe successfully loaded EHUI.DLL from C:\Windows\ehome, it (successfully) opened these files:
- Then devenv.exe successfully loaded C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\cscompee.dll
- Then McmlPad.exe loaded C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\System.Configuration\eee9b48577689e92db5a7b5c5de98d9b\System.Configuration.ni.dll
Hmmm, I’m not sure I learned much from that. It looks like the application being debugged (McmlPad.exe) was looking for some GAC registration info and a few obscure files. However, it’s likely that this is expected behaviour even on a working system.
So I went back to my google search results which convinced me to try DEPENDS.EXE to see what it would say. I expected nothing, frankly, but that gave me two new leads I wouldn’t have otherwise found: it indicates that EHUI.DLL is looking for DWMAPI.DLL and DXGI.DLL, neither of which were present anywhere on my system.
Fascinating – one of the first Forum posts I found referencing DWMAPI.DLL indicates this file may not be needed when “linked” by a multi-OS-targeting application. However, I suspect that for VMC libraries like EHUI.DLL, these two missing DLLs are not “load on demand” libraries – they’re just libraries that don’t appear on non-Vista platforms.
Once I grabbed copies of these two files from my Vista machine and dropped them into the %windir%\ehome folder, DEPENDS.EXE warned me that D3D10.DLL and NUCLEUS.DLL were required for DXGI.DLL, and that EHTRACE.DLL (a demand-load library) was missing. Okey-dokey… and then I’m “warned” that even with all these files in place…:
Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
Feeling lucky despite all evidence to the contrary, I re-ran MyProject from Visual Studio, but no love was had – still and all, “the specified procedure could not be found”. OK, let’s continue…
The unresolved imports were flagged in the following libraries on my XP development PC:
So, the obvious question is: if I copy *these* libraries from my VMC computer to C:\windows\ehome on my development XP computer, will that suffice to allow McmlPad.exe + Visual Studio 2005 to successfully debug my VMC app?
And the answer is: not quite yet. Unfortunately, when loading EHUI.DLL, Windows will still end up loading the standard libraries (such as MSVCRT.DLL) from the PATH (i.e. %windir%\system32). I realize that Windows is just trying to behave nicely, not being “tricked” into loading rogue versions of already-installed libraries, so I am not too upset by this. However, this has turned into a much more difficult problem than I first anticipated.
Files copied to my development system so far:
- %windir%\ehome\Microsoft.MediaCenter.dll (from VMC system)
- %windir%\ehome\Microsoft.MediaCenter.UI.dll (from VMC system)
- %windir%\ehome\ehui.dll (from VMC system)
- %programfiles%\Microsoft SDKs\Windows Media Center\v5.0\Tools\McmlVerifier.exe (to %windir%\ehome)
- %programfiles%\Microsoft SDKs\Windows Media Center\v5.0\Tools\McmlPad.exe (to %windir%\ehome)
- %windir%\system32\dwmapi.dll (from VMC system)
- %windir%\system32\dxgi.dll (from VMC system)
- %windir%\system32\d3d10.dll (from VMC system)
- nucleus.dll (from I don’t remember where)
- %windir%\system32\msvcrt.dll (from VMC system)
- %windir%\system32\d3d9.dll (from VMC system)
- %windir%\system32\user32.dll (from VMC system)
- %windir%\system32\advapi32.dll (from VMC system)
- %windir%\system32\mpr.dll (from VMC system)
- 😦 “I will say that if you are a hobbyist then MCML is not likely to be very friendly to you.”
- 😦 “It took me a long while to create a gallery that displays a list of images from an ArrayListDataSet.”
- 🙂 “I have persevered in the days since my last post and have managed to get a repeater/scroller working to emulate the behaviour of the ‘my music’ section of media center.”
- 🙂 “http://mobilewares.spaces.live.com/ has a good tutorial on making the sliding menu at the top of the screen.”
- 😦 “Following the rumour about Microsoft encouraging their internal teams to deprecate the use of an underscore prefix for private fields, I have decided to do the same.” [I just got my head wrapped around the use of underscores for private fields, and now I need to unlearn that behaviour just as quickly. At least I haven’t done too much damage with it.]
- 🙂 “If you can’t easily work out where the variable is defined (local scope, local parameter, member variable) then your code is too complex and needs refactoring. It’s that simple.” [I can handle that idea, yeah.]