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, как он был зарегистрирован в.