3

I'm using IRunningObjectTable.Register and IRunningObjectTable.Revoke as shown in this tutorial. My VBScript client initially calls methods no problem, but when the C# COM server disposes, I always receive a "Value does not fall within the expected range" exception. This is due to the commented line below:

private const int ACTIVEOBJECT_STRONG = 0x0;

[DllImport("ole32.dll")]
private static extern int CreateBindCtx(int reserved,
    out IBindCtx bindCtx);

[DllImport("oleaut32.dll")]
private static extern int RegisterActiveObject
    ([MarshalAs(UnmanagedType.IUnknown)] object punk,
    ref Guid rclsid, 
    uint dwFlags, 
    out int pdwRegister);

// register instance so it appears in ROT
private static int Register<T>(T classToRegister) 
{  
    int pdwRegister;
    Guid guid = Marshal.GenerateGuidForType(typeof(T));

    RegisterActiveObject(classToRegister, 
        ref guid, 
        ACTIVEOBJECT_STRONG, 
        out pdwRegister);

    return pdwRegister;
}

// do stuff in VBScript before disposal calls Revoke with the stored 
// pdwRegister value from the method above

// revoke instance so it's removed from ROT
private static void Revoke(int pdwRegister)
{
    IBindCtx bc;
    CreateBindCtx(0, out bc);

    IRunningObjectTable rot;
    bc.GetRunningObjectTable(out rot);
    // EXCEPTION: pdwRegister is *always* 65536, an invalid value!
    rot.Revoke(pdwRegister);      
}

If I terminate the program and ignore the exception, the instance usually removes itself from the ROT. However, after some time, I've noticed multiple instances of my app's GUID in the ROT and my VBScript client starts failing on GetObject(, "my.id"). Any thoughts?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Pakman
  • 2,170
  • 3
  • 23
  • 41
  • 1
    The code snippet is hopeless, no sign of the Register call. Post code that can reproduce the problem. – Hans Passant Apr 01 '11 at 15:05
  • Fixed - more details can be found in the linked article – Pakman Apr 01 '11 at 15:40
  • Well, debug this. What is the value of pdwRegister right after the RegisterActiveObject call? Does the value get stored in a VBScript variable? Does it get destroyed doing so? Not checking the return value of RegisterActiveObject is unwise btw. – Hans Passant Apr 01 '11 at 15:54
  • Everytime I've debugged the program, pdwRegister has had the value 65536. The return value of RegisterActiveObject is always 0, another invalid pdwRegister value. VBScript is completely separate from this code - it only interacts with it through COM interfaces – Pakman Apr 01 '11 at 16:18

2 Answers2

2

The first one registered is always 65536, and that is correct.

Use

[DllImport("oleaut32.dll", PreserveSig = false)]
        public static extern void RevokeActiveObject(
            uint handle,
            IntPtr reserved);

And Not:

IBindCtx bc; 
    CreateBindCtx(0, out bc); 


IRunningObjectTable rot; 
bc.GetRunningObjectTable(out rot); 
// EXCEPTION: pdwRegister is *always* 65536, an invalid value! 
rot.Revoke(pdwRegister);       

And RevokeActiveObject needs to be called from the same thread and proc as it was registered in.

JMax
  • 26,109
  • 12
  • 69
  • 88
Ron
  • 21
  • 2
  • You must be correct about the first object always being 65536 because that's always the value I see. Do you know what the difference between these two methods are? Why did you suggest the pinvoke method? – Pakman Mar 15 '12 at 15:02
1

I suspect that you are not maintaining the lifetime of the object correctly. I've done the same thing you have, but used two separate types, placing each of them in the Running Object Table.

Like you, the first object I placed in the table, I received a handle value of 65536. However, for the second item, I received a different handle.

However, when calling RevokeActiveObject, both calls returned an HRESULT of S_OK.

Something tells me that your object is being disposed of before the calls to revoke them are made.

Either that, or something is not incrementing/decrementing the reference count of the item on the ROT.

casperOne
  • 73,706
  • 19
  • 184
  • 253
  • Unfortunately, I don't have the troubled code anymore and a simple test doesn't throw an exception. Perhaps it did have something to do with object lifetimes... – Pakman Mar 15 '12 at 15:00