This project has moved. For the latest updates, please go here.

MMDeviceEnumerator constructor is throwing

Oct 25, 2013 at 10:51 PM
I'm trying to use NAudio to capture audio in an application compiled by VS2012 for .NET 4.0. I can compile and execute the capture demo with VS2012. But when I compile and run in my application, line 48 of MMDeviceEnumerator.cs throws "System.InvalidCastException: Unable to cast object of type 'CoreAudioApi._MMDeviceEnumerator' to type 'NAudio.CoreAudioApi.Interfaces.MMDeviceEnumeratorComObject'":
_realEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
The compiler and/or ReSharper is telling me "Suspicious cast: there is no type in the solution which is inherited from both 'NAudio.CoreAudioApi.Interfaces.MMDeviceEnumeratorComObject' and 'NAudio.CoreAudioApi.Interfaces.IMMDeviceEnumerator'. The compiler says the same thing in the demo, yet it executes.

Any suggestions?
Coordinator
Oct 28, 2013 at 3:09 PM
R# just thinks its as suspicious cast because MMDEviceEnumeratorComObject doesn't implement IMMDeviceEnumerator. That's just because it's COM.

You'll have to find the difference between the demo (which you say works) and your version. Is it the version of .NET? is one 64 bit and the other 32 bit?
Oct 28, 2013 at 3:56 PM
I find it ironic that the executable throws at exactly the same place as the compiler complains.

I will look at your other suggestion.
Coordinator
Oct 28, 2013 at 4:05 PM
you get that warning for every single COM object you create and cast to an interface this way. Obviously the COM object does have to implement the interface you are casting it to, but that cannot be known at compile time. What version of Windows are you running on?
Oct 28, 2013 at 4:18 PM
I am running on Windows 7 Professional 64-bit. I am compiling with VS 2012 for x86 because our apps have to run on XP. This part of the project won't run on XP, of course, but we compile everything for 32 bit. I retargeted the demo to .NET 4.0 and it compiles and runs fine. Now I need to go see whether it is targeted to x86 or x64. I'll report that shortly.

Thanks for the help.
Oct 28, 2013 at 4:39 PM
Ok. I just went through both solutions. By the way, I downloaded NAudio 1.7 late last week to see if that would help, so that is the version I am using.

In the demo I made sure all components were targeted to .NET 4.0 and x86. It compiles and runs (wav capture, wasapi).
In the app I also made sure that NAudio and the other components were targeted to .NET 4.0 and x86. They compile and and give the same exception as I initially reported.

By the way, in my app I am using only NAudio. Is there any possibility that is the cause?
Coordinator
Oct 28, 2013 at 5:04 PM
I'm not sure what you mean by using only NAudio.

So you're saying that if you make the NAudio WPF demo and the NAudio dll use .NET 4.0 it stops working? That would be strange since the WPF demo is already on .NET 4.0 and is set to x86 and I've had no problems myself with the MMEnumerator.
Oct 28, 2013 at 5:09 PM
Edited Oct 28, 2013 at 5:13 PM
Sorry if I wasn't clear. In the demo I made sure all components were targeted to .NET 4.0 and x86. It all compiles and runs (wav capture, wasapi) quite well. But after compiling NAudio into my app the same way (.NET 4.0 and x86), when I run the app the exception is thrown.

I have been using the WinForms demo. I just tried compiling and running the WPF demo and it runs file also.

In my app, I don't need AudioFileInspector, MidiFileConverter, MixDiff, or NAudio.WindowsMediaFormat, so I am not compiling those. In my app, I am compiling only The NAudio project copied from the NAudio solution.
Coordinator
Oct 28, 2013 at 5:14 PM
I can't see why the same code would work in one place and not the other. There must be some other difference between the projects. Are you sure you've not modified anything about MMDeviceEnumeratorComObject or IMMDeviceEnumerator?
Oct 28, 2013 at 5:15 PM
This morning I deleted my copy of the NAudio folder from my project and copied it again from the downloaded version, and then added it back to the project and recompiled. So I'm pretty sure I haven't changed anything.
Oct 28, 2013 at 5:24 PM
This is the code I'm using that crashes. It never gets to the third line (foreach).
#if USE_NEW_USB_MIC_CAPTURE
        var deviceEnum = new MMDeviceEnumerator();
        var devices = deviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToList();
        foreach (var device in devices)
        {
            logger.Trace("UsbMicrophone.ctor(): trying '{0}' vs '{1}'", device.FriendlyName, name);
            if (Utilities.IsLeadingSubstringOf(name, device.FriendlyName))
            {
                _name = device.FriendlyName;
                // TODO what else?
                break;
            }
        }
#endif
Coordinator
Oct 28, 2013 at 5:25 PM
OK, one idea. In your app, could the cast be happening on a different thread from the thread that created the MMDeviceEnumeratorComObject? Put a breakpoint on both lines and see what thread you're on. The apartment threading model on a lot of the Windows media APIs can cause weird errors like this. You need to use objects on the thread on which they were created.
Oct 28, 2013 at 5:30 PM
I don't think there is a thread issue. At the moment, this is exactly the only place that NAudio is referenced in my app. Since I haven't been able to get past this point, I haven't implemented anything else. So this is the first call to the MMDeviceEnumerator(), which, if I understand the call, does the creating of the MMDeviceEnumeratorComObject.
Coordinator
Oct 28, 2013 at 5:31 PM
Well I'm afraid I'm out of ideas then. If you have one project that works and one that doesn't, then you can usually resolve the issue by slowly simplifying both projects until they have the absolute minimal code that compiles the problem code (take copies of both first). At some point one will either break or start working. If not, then there is still a difference you haven't taken into account.
Marked as answer by medvezhonok on 10/28/2013 at 12:53 PM
Oct 28, 2013 at 5:37 PM
I'm a fan of that "divide-and-conquer" debug technique. I'll see what I can do to use it here. Unfortunately, my app is enormous (35 projects in the solution). But your suggestion makes a lot of sense, so I'll give it a go. Thanks for all your help. I might be back ... :) And of course I'll post the solution if I can identify one.
Oct 28, 2013 at 7:53 PM
YEA! Two thumbs up to your suggestion! I found the problem. Back when I was confused about CoreAudioAPI.dll I had added a raw copy of that to another project in the solution. Apparently that was causing conflict with NAudio. I removed that (and carefully deleted all of the copies of the DLL and all of the possible references thereto) and it magically works! So now I can move on to the real challenge -- capturing audio. But the demo looks like a pretty good model, so I'm not anticipating serious troubles going forward.

Thank you so much for your prompt help. You are a rarity on these discussion forums (or is that fora?)!
Coordinator
Oct 29, 2013 at 11:43 AM
great, glad you got it working