IRunningObjectTable.Register всегда устанавливает pdwRegister в значение 65536, недопустимое значение

Я использую IRunningObjectTable.Register а также IRunningObjectTable.Revoke как показано в этом уроке. Мой клиент VBScript изначально вызывает методы без проблем, но когда сервер C# COM удаляет, я всегда получаю исключение "Значение не попадает в ожидаемый диапазон". Это связано с прокомментированной строкой ниже:

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);      
}

Если я завершаю программу и игнорирую исключение, экземпляр обычно удаляет себя из ROT. Однако через некоторое время я заметил несколько экземпляров GUID моего приложения в ROT, и мой клиент VBScript начинает давать сбой в GetObject(, "my.id"). Какие-нибудь мысли?

2 ответа

Решение

Я подозреваю, что вы неправильно поддерживаете срок службы объекта. Я сделал то же самое, что и вы, но использовал два отдельных типа, поместив каждый из них в таблицу Running Object Table.

Как и вы, первый объект, который я поместил в таблицу, получил значение дескриптора 65536. Однако для второго элемента я получил другой дескриптор.

Однако при звонке RevokeActiveObject оба вызова вернули HRESULT S_OK.

Что-то говорит мне, что ваш объект утилизируется до того, как будут сделаны вызовы для его отзыва.

Либо это, либо что-то не увеличивает / уменьшает счетчик ссылок элемента в ROT.

Первый зарегистрированный всегда 65536, и это правильно.

использование

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

И не:

IBindCtx bc; 
    CreateBindCtx(0, out bc); 


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

А также RevokeActiveObject должен вызываться из того же потока и proc, как он был зарегистрирован в.

Другие вопросы по тегам