Issues with C++ to C# migration

Im working on a device application (no this is not a device related question, just happens to be the context of my issues) and I continuosly get an error stating "Exception from HRESULT: 0x8005000A" Invalid Advise Flag. Any ideas on what this means or what I should be looking for

I am also confused on the use of CreateEvent. This is something i ported over from the C++ app, (with some modification), but I do not know the signifigance of the method or what exactly it does. Any ideas

This is what I've done so far

class BBChannel : IChannelEvents{

[DllImport("kernel32.dll", EntryPoint = "CreateEvent")]

static extern IntPtr CreateEvent(IntPtr eventAttributes, bool manualReset, bool initialState, String name);

public BBChannel() {

IntPtr[] iarr = new IntPtr[2];

iarr[0] = BBChannel.CreateEvent((IntPtr)null, false, false, null);

iarr[1] = BBChannel.CreateEvent((IntPtr)null, true, false, null);

 

DeviceManager oDeviceMgr = new BBDEVMGRLib.DeviceManager();

 

// Open Channel expects 2 arguments. Channel Name, IChannelEvents

IChannel theChannel = TheDevice.OpenChannel("Channel", this); 

// CODE ERRORS RIGHT HERE - I get an error of "Exception from HRESULT: 0x8005000A" Invalid Advise Flag

}

public void OnChallenge(int RemainingAttemps, byte[] Password) {

}

public void CheckClientStatus() {

}

public void OnNewData() {

}

public void OnClose() {

}

}

 

This is pretty much where I am stuck. Does anyone know what this error means Is it a generic error Im really struggling here.



Answer this question

Issues with C++ to C# migration

  • YMaod

    Not sure about the advise flag. It seems like it is the code you're calling raising the error. You should look at the documentation for it.

    I can answer the event question. CreateEvent creates a sync object in Windows. You don't need to do this in .NET as it already exposes an Event class. You can remove the interop call and whatnot and replace it with the following code:

    class BBChannel : IChannelEvents
    {
    private AutoResetEvent m_evt1 = new AutoResetEvent();
    private ManualResetEvent m_evt2 = new ManualResetEvent();

    public
    BBChannel()
    {
    DeviceManager oDeviceMgr = new BBDEVMGRLib.DeviceManager();

    // Open Channel expects 2 arguments. Channel Name, IChannelEvents
    IChannel
    theChannel = TheDevice.OpenChannel("Channel", this);

    // CODE ERRORS RIGHT HERE - I get an error of "Exception from HRESULT: 0x8005000A" Invalid Advise Flag
    }
    }

    Notice how simple it becomes in .NET. In general when porting from unmanaged to managed code any Win32 function call that deals with objects (events, semaphores, threads, etc) will have a class to back it. In other cases a Win32 function is attached to a static class. Most apps don't use interop directly. This URL provides a list of the common Win32 functions and their .NET equivalent http://msdn.microsoft.com/library/default.asp url=/library/en-us/dndotnet/html/win32map.asp.

    In your code you should probably name the events more descriptively. Also you didn't actually use them so I can't demonstrate their usage in your code but you can set the event (SetEvent in Win32) using m_evt#.Set(). All other event functions work similarly.

    The only exception is closing the event. Since it is an object you don't really close it. Instead when the GC runs the event will be automatically released. For your particular case this might not be so bad however good .NET programming says that unmanaged resources (such as events) are released when they are no longer needed. The event classes implement IDisposable. This means you should dispose of them when you no longer need them. More importantly however since you have nested disposable objects your class should also be disposable. This tells your callers that they should release you when they no longer need you. This allows the unmanaged resources to be cleaned up. Therefore here is an updated version of your code with the relevant changes:

    sealed class BBChannel : IChannelEvents, IDisposable
    {
    private AutoResetEvent m_evt1 = new AutoResetEvent();
    private ManualResetEvent m_evt2 = new ManualResetEvent();

    public void OnClose ( )
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }

    void IDisposable.Dispose ( )
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }

    private void Dispose ( bool disposing )
    {
    if (disposing)
    {
    if (m_evt1 != null)
    {
    m_evt1.Close();
    m_evt1 = null;
    };

    if (m_evt2 != null)
    {
    m_evt2.Close();
    m_evt2 = null;
    };
    };
    }
    }

    A few comments about the code. A full discussion of dispose is beyond this post so I recommend that you look it up in MSDN and on the forums as it has been discussed in detail. My comments however. Firstly I did not set up a finalizer. Unless the general community I believe you should not define a finalizer unless you have unmanaged resources to clean up (not child objects that manage unmanaged resources). Since your class does not no finalizer is needed. The reason is that your finalizer would ultimately do nothing anyway, would add additional code for no reason and would slow down clean up. However if you chose to add one the code is already set up to properly handle that case. Next is that the object can be disposed multiple times so you must handle that case. The given code handles it for you. Thirdly the dispose is not thread safe. If thread-safety is an issue then you'll need to modify the dispose method.

    Your callers should ensure that they close your object when they no longer need it. Since you already had a OnClose method I used that as the disposing method. Ideally though you should either expose Dispose directly (add public to the method and remove the IDisposable. prefix from the method) or define a general Close method that calls OnClose internally.

    Michael Taylor - 11/3/06


  • JW0000

    Thank you very much for the response.

    Im very new to C++, but know a decent amount about C#, just having troubles understanding the aspects of C# that (just as you said) replace the C++ aspects. That link is great you provided me!

    As far as the issue I was having with the error. I figured it out and really it was an issue of not understand how that particular com object functioned, but I figured it out. This is more really a note for anyone else who finds this thread and kinda hits a little off topic and more on the BlackBerry side (feel free to move the thread if necessary). When you open a channel using the IDevice.OpenChannel method, you need to make sure that the Blackberry has opened the channel on the device of the same name.

    I will certainly look more into the IDisposable and making my classes implement that when using unmanaged resources.

    Thank you again - Ryan


  • Issues with C++ to C# migration