3

I think this article has the same problem with me. However, there's no workable solution for my case.

I'm using Windows Media Player ActiveX in my program.

For some reason, I don't want to add a reference of it and convert to AxHost automatically by IDE.

I create the instance by Activator and ProgID

protected const string WMP_PROG_ID = "WMPlayer.OCX.7";

private dynamic _wmp;

protected virtual bool init(){
    try{
        _wmp = Activator.CreateInstance(Type.GetTypeFromProgID(WMP_PROG_ID));
    }
    catch{ return false; }
    return true;
}

I was tried to do this by Reflection, but I found that dynamic is suitable to my case.

Every property and method works alright, like these:

protected override bool setSpeed(float speed){
    try{
        _wmp.settings.rate = speed;
    }
    catch { return false; }
    return true;
}

protected override int getLength(){
    double res;
    try{
        res = _wmp.currentMedia.duration;
    }
    catch { return 0; }
    return (int)(res * 1000);
}

Unfortunately, when I want to attach event like the article I indicated in the top, it got no work.

My code like this:

protected bool connectEvent(){
_wmp.StatusChange += new EventHandler(_wmp_StatusChange);
    return true;
}

protected void _wmp_StatusChange(object sender, EventArgs e){
    Console.WriteLine(_wmp.Status);
}

I've checked the type of event handler of StatusChange, it's EventHandler.

These codes compiled well, and I can load some music, play it, pause it, ...do anything I like.

But the StatusChange event never triggered.

I tried to set a break-point at connectEvent.

When run at _wmp.StatusChange += new EventHandler(...), the IntelliTrace give me some information.

Those information had written in Trad. Chinese, I think it means:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Could not apply operator "+=" to type System.Dynamic.DynamicObject and System.EventHandler

Even though there's an exception, but just like I said, compile was passed, everything still work -- except I could not listen event.

So, how can I attach event successfully in the dynamic object _wmp?

Any possible solution (like Reflection) is useful to me.

Also, in the case above, the handler type of StatusChange is EventHandler.

But if I want to handle PlayStateChange event, it is an "Unknown handle" if I don't add a reference of wmp.dll.

I hope the solution is suitable to this case, too.

Thanks everyone in advance for all of your support, and please forgive me for my poor English.

Community
  • 1
  • 1
J.C
  • 633
  • 1
  • 13
  • 27
  • How are you ensuring that the WMPlayer status is changing? – Srikanth Venugopalan Mar 26 '13 at 06:28
  • @SrikanthVenugopalan: accroding [MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/dd564082.aspx), this event raised when my `_wmp.Status` changed. I've check the status string, and it changed, so I think the event should be raise, too. – J.C Mar 26 '13 at 06:41
  • Agreed- was wondering if you were aware of Status property getting changed and since it is a read-only property, how would you make the Status change? – Srikanth Venugopalan Mar 26 '13 at 06:43
  • @SrikanthVenugopalan: The `Status` is `String.Empty` in the beginning. After I load a media by `_wmp.URL = "some media"`, it change to _Connecting_. When media start to play, the status will change to _Playing some media in mm:ss_ – J.C Mar 26 '13 at 06:49
  • That looks ok, need to check about event binding to dynamic type. Can you try the approach from [this answer](http://stackoverflow.com/a/4264616/326543). Reflection seems to be an option. – Srikanth Venugopalan Mar 26 '13 at 07:02
  • @SrikanthVenugopalan: Thank for your suggestion. In fact, I've read that article before I ask the question, but I have no idea about how to write a wrapper of an ActiveX. BTW I've got some tips from a MVP just now and I'm trying to solve this problem. Once I reach the goal I'll post it as an answer here:) – J.C Mar 26 '13 at 07:58

1 Answers1

1

The generic strategy to turn a program that uses a COM object from early bound to late bound calling is to first write it early bound. IntelliSense will help you fall in the pit of success, ensuring that you use correctly named methods, pass the right kind of arguments and particularly useful to help you find out what the event handler signatures should look like.

Which produces this bit of test code:

    void testEarlyBound() {
        var wmp = new WMPLib.WindowsMediaPlayer();
        wmp.StatusChange += new WMPLib._WMPOCXEvents_StatusChangeEventHandler(wmp_StatusChange);
    }

    void wmp_StatusChange() {
        throw new NotImplementedException();
    }

With the StatusChange event handler assignment and method body completely auto-generated by IntelliSense. Note the signature of the event handler, it is not an EventHandler. Just a method that returns void and takes no arguments, it matches the Action delegate type. Now you have a good shot at writing the late-bound version without the undiagnosable runtime exceptions:

    void testLateBound() {
        dynamic wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX"));
        wmp.StatusChange += new Action(wmp_StatusChange);
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I've got the same tip / answer from a MVP in Trad. Chinese [MDSN Social](http://social.msdn.microsoft.com/Forums/zh-TW/233/thread/90328268-1c50-4278-a226-cb2e9bfb8bfc). I've implement `StatusChange` and `PlayStateChange`, it's so far so good. However, I can't attach to `wmp.Error` and the exception description is "Can not apply operator '+=' to 'System.__ComObject' and 'Action'". I'm still trying to solve this problem now. I'll try to solve this problem following your tips. Thanks. – J.C Mar 28 '13 at 01:51
  • It seems there's an Error event according [the MSDN documentation](http://msdn.microsoft.com/zh-tw/library/windows/desktop/dd564051(v=vs.85).aspx). But when I use the `WMPLib.WindowsMediaPlayer` type, the token `Error` is a property. I'm looking for some way to attach the Error event. – J.C Mar 28 '13 at 02:22
  • suppose the event handler has arguments like this public void wmp_StatusChange(object sender , MyCustomArgument e){ } In this case what will be the event registration code? – Aneesh May 09 '14 at 05:58