У меня есть сборка .NET, после запуска которой один объект в ней я регистрирую в ROT, running object table.
Этот тип наследован от интерфейса:
[Guid("D61A6B54-F44E-4c30-85D4-4FAD0DC2BF95")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IExecute
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(1)]
void ExecuteArgument([In, MarshalAs(UnmanagedType.U4)] uint x);
}
Вот само описание класса, который наследован от интерфейса:
[ProgId("DomainManagerExample.ClassUserObject")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("F9012B74-DBC6-44e7-BF48-6CC8CE6F486A")]
public class ClassUser : IExecute
{
// Методы, поля, прочее
public void ExecuteArgument(uint x)
{
Console.WriteLine(x.ToString());
}
} // ClassUser
Вот как происходит регистрация в ROT:
public void Register()
{
try
{
UnicodeEncoding enc = new UnicodeEncoding();
int errorcode;
UCOMIRunningObjectTable rot;
UCOMIMoniker moniker;
int register;
string delimname = "!";
byte[] del = enc.GetBytes(delimname);
byte[] item = enc.GetBytes(MONIKER);
errorcode = GetRunningObjectTable(0, out rot); Marshal.ThrowExceptionForHR(errorcode);
errorcode = CreateItemMoniker(del, item, out moniker); Marshal.ThrowExceptionForHR(errorcode);
rot.Register(0, (IExecute)this, moniker, out register);
}
catch(Exception ex){
MessageBox.Show(ex.Message);
}
}
Регистрация происходит успешно и объект там зарегестрирован — проверял.
Теперь я получаю этот объект из ROT — вот тут начинаются проблемы
const string IMONIKER = "!DomainManagerExample.ClassUser";
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
static void GetRunningObjects1()
{
try
{
UCOMIRunningObjectTable ROT;
UCOMIBindCtx ctx;
UCOMIEnumMoniker EnMon;
UCOMIMoniker[] pMon = new UCOMIMoniker[10];
int errorcode;
string display_name = String.Empty;
errorcode = CreateBindCtx(0, out ctx); Marshal.ThrowExceptionForHR(errorcode);
ctx.GetRunningObjectTable(out ROT);
ROT.EnumRunning(out EnMon);
EnMon.Reset();
int pceltFetched = 0;
object myApp = new object();
while (EnMon.Next(1, pMon, out pceltFetched) == 0x0)
{
pMon[0].GetDisplayName(ctx, pMon[0], out display_name);
Console.WriteLine(display_name);
// Получение объекта моникера
if (display_name == IMONIKER)
{
ROT.GetObject(pMon[0], out myApp);
break;
}
} // while
// здесь execute будет равен null
IExec execute = myApp as IExec;
uint l = 7;
execute.ExecuteArgument(l);
}
catch(Exception ex){
MessageBox.Show(ex.Message);
}
}
Исключения валятся разные, в данном коде NullReferenceException.
Для начала я делал интерфейс без параметров вообще — все получалось, и понятно, почему, двоичная сигнатура понятна, не нужно никаких типов.
После того, как я ввел параметр, начались проблемы.
Были исключение также: "security exception". (когда в класс ClassUser я ввел контструктор по умолчанию )
Да и даже без конструктора по умолчанию все работало.
Если я пытаюсь получить объект моникера при помощи кода:
object myApp2 = Marshal.GetActiveObject("DomainManagerExample.ClassUserObject");
или
object myApp = Marshal.BindToMoniker(IMONIKER);
То в первом случае исключение:
[System.Runtime.InteropServices.COMException]: {"Operation unavailable" }
Во втором случае:
[System.Runtime.InteropServices.COMException]: {"Invalid syntax" }
В общем, я в тупике окончательном.
Подскажите, пожалуйста, как действовать.
Были исключение также: "security exception". (то того, как в класс ClassUser я ввел контструктор по умолчанию )
Это нужно для файловых ассоциаций. Приложение использует несколько расширений, при этом открывать их нужно при открытом приложении.