İ am sorry it is too classic problem loading dll. But i can not solve this basic problem: i have a plugins file path i want to load these assembly into new domain but i can not do this. Firstly; it is a web application my code below: thanks your help :
foreach (var filePath in arryFiles)
{
Assembly asm = Assembly.LoadFile(filePath.ToString());
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domainSetup.DisallowBindingRedirects = false;
domainSetup.DisallowCodeDownload = true;
domainSetup.LoaderOptimization = LoaderOptimization.SingleDomain;
domainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
ApplicationHost = AppDomain.CreateDomain("Ops.Mgr.Service", null, domainSetup);
// how to load into domain my assembly...
}
Thanks your helps...
Do you want to load assembly in to same App Domain or different App Domain?
Here is the solution to load assembly in different App Domain: Loading DLLs into a separate AppDomain
For loading assembly in same App Domain: Can I load a .NET assembly at runtime and instantiate a type knowing only the name?
Related
I'm trying to check some metadata of an assembly without loading it (permanently) into my app. To do this, I create a temporary sandbox AppDomain, load the assembly into it and then unload the whole sandbox. According to the answers to this question that's "correct" way to do it.
However after unloading the assembly it still remains in the current AppDomain. Why?
The answer to this question suggest that the assembly can be "bled into" the current domain, but I don't see how can this be possible in my example. The rest of the application does not use the assembly at all, it's not even referenced. The observed behavior persists even when I unload the sandobx immediately after the assembly load.
This article says that domain-neutral assemblies cannot be unloaded this way. Is that the reason? If yes, can I somehow stop the assembly from being treated as domain-neutral?
private void Check()
{
string assemblyName = "SomeUnrelatedAssembly";
var sandbox = AppDomain.CreateDomain("sandbox"); //create a discardable AppDomain
//load the assembly to the sandbox
byte[] arr;
using (var memoryStream = new MemoryStream())
{
using (var fileStream = new FileStream($"{assemblyName}.dll", FileMode.Open))
fileStream.CopyTo(memoryStream);
arr = memoryStream.ToArray();
}
Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints false
sandbox.Load(arr);
//and unload it
AppDomain.Unload(sandbox);
Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints true!
}
private static bool IsAssemblyLoaded(string assemblyName)
{
return AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.Contains(assemblyName));
}
EDIT: I've checked the loading process with Process Explorer (like this). The loaded assembly is NOT domain-neutral.
You are correct. Your assembly is being deemed domain-neutral and shared across app domains.
Use the AppDomain.CreateDomain overload that allows you to provide setup information:
Info:
AppDomainSetup info = new AppDomainSetup();
info.ApplicationBase = domainDir;
info.ApplicationName = executableNameNoExe;
info.LoaderOptimization = LoaderOptimization.SingleDomain;
Change:
AppDomain.CreateDomain("sandbox");
To:
AppDomain.CreateDomain("sandbox",null, info);
This snippet works fine:
System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
PS.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path));
PS.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainSetup ADS = AppDomain.CurrentDomain.SetupInformation;
AppDomain domain = AppDomain.CreateDomain("Pluging", null, ADS, PS, null);
Assembly asm = Assembly.LoadFile(DLLPath);
domain.Load(asm.FullName);
Creating a new AppDomainSetup fails:
System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
PS.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path));
PS.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainSetup ADS = new AppDomainSetup();
ADS.ApplicationBase= Path;
AppDomain domain = AppDomain.CreateDomain("Pluging", null, ADS, PS, null);
Assembly asm = Assembly.LoadFile(DLLPath);
domain.Load(asm.FullName);
The whole thing is running inside an asp.net project developed in VS2012.
this is the exception I receive:
Could not load file or assembly 'MacroBase, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system
cannot find the file specified.
could you please help?
The problem was that I used to rename dlls before storing them. I still don't know the work around but I changed my algorithm so that I can store and recall dll with the same name as it was originally compiled. Problem solved.
What was the effect of changing AppDomainSetup? In first alternative, asp.net was finding a copy of that renamed dll (with original name) in bin directory of asp.net project.
As a part of BaaS project, I need to dynamically execute a code from "guest" assembly. I've tried all the examples and answers in other similar questions including AppDomainToolKit approach, but got no luck.
Similar with the plugin approach, I got positive result by copying related assemblies into host application's bin path. However, this is not possible for the current scenario:
permissions and restrictions needs to be applied per request
each request should be evaluated in a temporary appdomain
load the required assembles and referenced types from a path to temporary domain
So far, my latest piece of code is below
// ClassLibrary1.dll and ClassLibrary2.dll are in the same directory, both are marked as Serializable
var binPath = #"C:\AssemblyDemo\ClassLibrary1\bin\Debug\";
var lib1Path = binPath + "ClassLibrary1.dll";
var lib2Path = binPath + "ClassLibrary2.dll";
var setup = new AppDomainSetup();
setup.ApplicationBase = binPath;
AppDomain domain = AppDomain.CreateDomain("domainname", null, setup);
ObjectHandle handle = domain.CreateInstanceFrom(lib1Path, "ClassLibrary1.Class1");
var unwrap = handle.Unwrap();
var m1 = unwrap.GetType().GetMethod("Method1");
var result = m1.Invoke(unwrap, null);
handle.Unwrap() throws exception Type is not resolved for member 'ClassLibrary1.Class1,ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
If you want to load the assembly only in the temporary AppDomain you cannot call Unwrap in the main domain. Unwrap loads the type there as well. You must move all access to objects from the temporary assembly to the temporary AppDomain. You can do this using AppDomain.DoCallBack or a custom MarshalByRef class that you instantiate in the child domain and call from the parent domain.
I load an assembly into an appdomain via:
var appdomainSetup = new AppDomainSetup();
//string appBase = Environment.CurrentDirectory;
//string appBase = HttpContext.Current.Request.ApplicationPath;
appdomainSetup.ApplicationBase = _appBase;//System.Web.HttpContext.Current.Request.ApplicationPath: Injected into cstor
System.Diagnostics.Debug.WriteLine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
appdomainSetup.DisallowBindingRedirects = false;
appdomainSetup.DisallowCodeDownload = true;
appdomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
appDomain = AppDomain.CreateDomain("myAppdomain", null, appdomainSetup);
where BLASSEMBLYLOCATION = "c:\path\myAssembly.dll";//for now just hard coded path
Then I grab a type from this assembly in another method:
var helperObject= appDomain.CreateInstanceAndUnwrap("myssembly.NameContinued", "myNamespace.BL.Helper") as Helper;//ERROR LINE HERE
This all works just fine and dandy in a unit test. However, this blows up with error when run through the web application:
Could not load file or assembly 'myssembly.NameContinued' or one of
its dependencies.
I can reproduce the FileNotFoundException in my unit test by not specifying
appdomainSetup.ApplicationBase
I suspect the issue has to do with the directory I set as ApplicationBase. In the web program I pass the value of HttpContext.Current.Request.ApplicationPath which I see to be "/".
How can I fix this problem?
I set the ApplicationPath equal to the path where I put my assembly:
appdomainSetup.ApplicationPath = #"c:\path";
Because this assembly is referenced by the web project, I expected my assembly to be included in the same directory as my web project so I could use relative paths (much like bin folders work). However, for whatever reason this just isn't working. Specifying the full path as it lives on the server is thus far the only solution that worked.
var processAssembly = Assembly.LoadFile(baseLocationCCDebugFolder+"\\CC.dll");
var processType = processAssembly.GetType("CC.Executor.CCProcess",true,true);
AppDomainSetup appDSetup = new AppDomainSetup()
{
ApplicationBase = baseLocationCCDebugFolder,
//PrivateBinPath = processAssembly.CodeBase
};
StrongName fullTrustAssembly = processAssembly.Evidence.GetHostEvidence<StrongName>();
AppDomain executionDomain = AppDomain.CreateDomain("ExecutionDomain",null,appDSetup,internetPS,fullTrustAssembly);
CCProcess process =(CCProcess)executionDomain.CreateInstanceAndUnwrap(processAssembly.ManifestModule.FullyQualifiedName, processType.FullName);
im encountering an error on the last line of this code which goes like this.
Could not load file or assembly 'D:\\work\\compilerCom\\CompileCom_Build_4_newArchitecture\\CompilerCom\\CC\\bin\\Debug\\CC.dll' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)<br/>
im still figuring my way in app domain.
what am i doing wrong?
EDIT:-
the value of baseLocationCCDebugFolder variable is D:\\work\\compilerCom\\CompileCom_Build_4_newArchitecture\\CompilerCom\\CC\\bin\\Debug
My guess is that it is not the Assembly not being found but one of the referenced assemblies not loading correctly. You may need to handle the resolve assembly event in the parent appdomain. There is a good post here describing it.
http://social.msdn.microsoft.com/forums/en-US/clr/thread/0a18ed66-6995-4e7c-baab-61c1e528fb82/