에로드되지 - 나는 운없이이 관련 StackOverflow의 질문을 검토 : How to Load an Assembly to AppDomain with all references recursively?동적으로로드 조립이 중복되지 않습니다 새 응용 프로그램 도메인
나는 두 개의 콘솔 응용 프로그램을 가지고있다. AssemblyLoaderTest.exe 및 testapp.exe
- 내가 동적으로 testapp.exe
- 내에서 클래스에서 방법을 testapp.exe을로드하고 전화를 AssemblyLoaderTest.exe를 사용하려고하는 것은 지금까지의 코드가 작동 - 방법 " testapp.exe의 "TestWrite()"가 올바르게 실행되고 outputsuccess.txt가 쓰여집니다. , testapp.exe는 동일한 AppDomain에로드됩니다. "CallMethodFromDllInNewAppDomain"은 항상 false를 반환하기 때문에 검증되었습니다. 새로운 AppDomain에 testapp.exe를로드하려고합니다.
내 질문 : 아래 예제 코드를 수정하여 새 AppDomain에 testapp.exe를로드하면 결과적으로 "CallMethodFromDllInNewAppDomain"이 true를 반환합니다. 고맙습니다!
아래 코드. 둘 모두 VS의 새로운 콘솔 응용 프로그램으로 간단히 복사하여 실행/컴파일 할 수 있습니다.
콘솔 응용 프로그램 # 1 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Policy;
namespace AssemblyLoaderTest
{
class Program
{
static void Main(string[] args)
{
List<object> parameters = new List<object>();
parameters.Add("Test from console app");
bool loadedInNewAppDomain = DynamicAssemblyLoader.CallMethodFromDllInNewAppDomain(@"c:\temp\testapp.exe", "testapp.TestClass", "TestWrite", parameters);
}
}
public static class DynamicAssemblyLoader
{
public static string ExeLoc = "";
public static bool CallMethodFromDllInNewAppDomain(string exePath, string fullyQualifiedClassName, string methodName, List<object> parameters)
{
ExeLoc = exePath;
List<Assembly> assembliesLoadedBefore = AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>();
int assemblyCountBefore = assembliesLoadedBefore.Count;
AppDomainSetup domaininfo = new AppDomainSetup();
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain domain = AppDomain.CreateDomain("testDomain", adevidence, domaininfo);
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
domain.CreateInstanceFromAndUnwrap(exePath, fullyQualifiedClassName);
List<Assembly> assemblies = domain.GetAssemblies().ToList<Assembly>();
string mainExeName = System.IO.Path.GetFileNameWithoutExtension(exePath);
Assembly assembly = assemblies.FirstOrDefault(c => c.FullName.StartsWith(mainExeName));
Type type2 = assembly.GetType(fullyQualifiedClassName);
List<Type> parameterTypes = new List<Type>();
foreach (var parameter in parameters)
{
parameterTypes.Add(parameter.GetType());
}
var methodInfo = type2.GetMethod(methodName, parameterTypes.ToArray());
var testClass = Activator.CreateInstance(type2);
object returnValue = methodInfo.Invoke(testClass, parameters.ToArray());
List<Assembly> assembliesLoadedAfter = AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>();
int assemblyCountAfter = assembliesLoadedAfter.Count;
if (assemblyCountAfter > assemblyCountBefore)
{
// Code always comes here
return false;
}
else
{
// This would prove the assembly was loaded in a NEW domain. Never gets here.
return true;
}
}
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// This is required I've found
return System.Reflection.Assembly.LoadFrom(ExeLoc);
}
}
}
콘솔 응용 프로그램 # 2 :
using System;
namespace testapp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello from console");
}
}
[Serializable]
public class TestClass : MarshalByRefObject
{
public void TestWrite(string message)
{
System.IO.File.WriteAllText(@"outputsuccess.txt", message);
}
}
}
마이클, 당신의 의견을 주셔서 감사합니다. (2)는 유스 케이스에서는 불가능합니다 (이름으로 클래스/메소드를 호출 할 수 없으므로). (3) - domaininfo.ApplicationBase = System.IO.Path.GetDirectoryName (exePath);을 추가했으나 실제로는 아무 것도하지 않습니다 (outputsuccess.txt는 여전히 부모 AppDomain의 현재 디렉토리에 기록됩니다). – BlueSky
내 기존 코드를 편집하여 작동 시키면 매우 감사 할 것입니다. 이 주제에 관한 이론에 대해 많은 논의가 있지만 작동하는 코드 예제를 아직 찾지 못했습니다. 고맙습니다! – BlueSky
나는 방금 전멸했고, 나의 지위를 완전히 재창조했다. 귀하의 질문에 대한 대답입니다. –