Re[2]: Com+ , Reference и AppDomain
От: AThe  
Дата: 14.08.07 08:01
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Давненько я этим не занимался, отвечаю по памяти.


M>1. У тебя в данном случае (по меньшей мере, если речь идет о com-приложении, а не библиотеке) и должен быть MarshalByRefObject. Приводиться он должен к интерфейсу (ты ведь определил интерфейс и назначил ему Guid, правда?).

M>2. В настройках COM+ приложения есть рабочая папка, которую можно задать.

Оказалось первая проблема — следствие второй. Вот тестовый пример.

Компонент.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.EnterpriseServices;
using System.Reflection;
using System.Runtime.Remoting;
using Reference;
using System.IO;

[assembly: ComVisible(true)]
[assembly: Guid("640468B8-2988-4539-B8BA-7C3ED04EB5A8")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false)]

namespace ComPlusComponent
{
#if(!TEST1)
    [ComVisible(true)]
    [Guid("406FFB62-DC77-47AE-8C78-A31F9DA50F57")]
    [ProgId("ComPlusComponent.1")]
    [ClassInterface(ClassInterfaceType.None)]
#endif
    public class ComPlusComponentClass
#if(!TEST1)
        : ServicedComponent
#endif
    {
        public ComPlusComponentClass()
        {
        }

        static void Log(string message)
        {
            using (StreamWriter sw = new StreamWriter("c:\\ComPlusComponent.log", true))
                sw.WriteLine(message);
        }

        static ComPlusComponentClass()
        {
#if(TEST1)
            Log("Test1");
#endif
#if(TEST2)
            Log("Test2");
#endif
#if(TEST3)
            Log("Test3");
#endif
#if(TEST4)
            Log("Test4");
#endif

            try
            {
#if(TEST1)
                Log(AppDomain.CurrentDomain.BaseDirectory);
                AppDomain domain = AppDomain.CreateDomain("Second Domain");
                ObjectHandle handle = domain.CreateInstanceFrom("Reference.dll", "Reference.ReferenceClass");
                ReferenceClass refer = (ReferenceClass)handle.Unwrap();
                refer.Init();
#endif
#if(TEST2)
                Log(AppDomain.CurrentDomain.BaseDirectory);            
                AppDomain domain = AppDomain.CreateDomain("Second Domain");
                ObjectHandle handle = domain.CreateInstanceFrom("Reference.dll", "Reference.ReferenceClass");
                ReferenceClass refer = (ReferenceClass)handle.Unwrap();
                refer.Init();
#endif
#if(TEST3)
                Log(AppDomain.CurrentDomain.BaseDirectory);            
                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = new FileInfo(typeof(ComPlusComponentClass).Assembly.Location).DirectoryName;
                AppDomain domain = AppDomain.CreateDomain("Second Domain", null, setup);
                ObjectHandle handle = domain.CreateInstanceFrom
                    ( "Reference.dll"
                    , "Reference.ReferenceClass");
                object obj = handle.Unwrap();
                Log(obj.GetType().ToString());
                ReferenceClass refer = (ReferenceClass)obj;
                refer.Init();
#endif
#if(TEST4)
                Log(AppDomain.CurrentDomain.BaseDirectory);            
                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = new FileInfo(typeof(ComPlusComponentClass).Assembly.Location).DirectoryName;
                Log(setup.ApplicationBase);            
                AppDomain domain = AppDomain.CreateDomain("Second Domain", null, setup);
                ObjectHandle handle = domain.CreateInstanceFrom
                    ( Path.Combine(setup.ApplicationBase, "Reference.dll")
                    , "Reference.ReferenceClass");
                object obj = handle.Unwrap();
                Log(obj.GetType().ToString());
                ReferenceClass refer = (ReferenceClass)obj;
                refer.Init();
#endif
            }
            catch (Exception ex)
            {
                Log(ex.GetType().ToString());
                Log(ex.Message);
            }
        }
    }
}


Сборка от которой зависит комопнент
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Reference
{
    public class ReferenceClass
        : MarshalByRefObject
    {
        public ReferenceClass()
        {
        }

        private void Log(string message)
        {
            using (StreamWriter sw = new StreamWriter("c:\\ComPlusComponent.log", true))
                sw.WriteLine(message);
        }

        public void Init()
        {
            Log("Init Called");
        }
    }
}


Тестовый проект.
using System;
using System.Collections.Generic;
using System.Text;
using ComPlusComponent;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            ComPlusComponentClass c = new ComPlusComponentClass();
        }
    }
}


Вот результаты.

Test1
Z:\Tries\TryComPlus\Test\bin\Debug\
Init Called
Test2
C:\WINDOWS\system32\
System.IO.FileNotFoundException
Could not load file or assembly 'file:///C:\WINDOWS\system32\Reference.dll' or one of its dependencies. Не удается найти указанный файл.
Здесь вставляем путь к Com-dll в Службы компонентов->ComPlusComponent->Активизация->Корневая папка приложения
Test2
C:\WINDOWS\system32\
System.IO.FileNotFoundException
Could not load file or assembly 'file:///C:\WINDOWS\system32\Reference.dll' or one of its dependencies. Не удается найти указанный файл.
Test3
C:\WINDOWS\system32\
System.IO.FileNotFoundException
Could not load file or assembly 'file:///C:\WINDOWS\system32\Reference.dll' or one of its dependencies. Не удается найти указанный файл.
Test4
C:\WINDOWS\system32\
Z:\Tries\TryComPlus\Test\bin\Debug
System.MarshalByRefObject
System.InvalidCastException
Unable to cast transparent proxy to type 'Reference.ReferenceClass'
Переписываем Reference.dll в System32
Test2
C:\WINDOWS\system32\
Init Called
Test3
C:\WINDOWS\system32\
Reference.ReferenceClass
Init Called
Test4
C:\WINDOWS\system32\
Z:\Tries\TryComPlus\Test\bin\Debug
Reference.ReferenceClass
Init Called

Где копать?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.