IRunningObjectTable.Register всегда устанавливает pdwRegister в значение 65536, недопустимое значение - PullRequest
3 голосов
/ 01 апреля 2011

Я использую 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 ]

2 голосов
/ 01 октября 2011

Первый зарегистрированный всегда 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 необходимо вызывать из того же потока и процедуры, в которых он был зарегистрирован.

1 голос
/ 13 сентября 2011

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

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

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

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

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

...