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.
Related
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.
İ 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?
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/
I tried the below code to load and unload managed assemblies.
AppDomain dom = AppDomain.CreateDomain("some");
AssemblyName assemblyName = new AssemblyName();
assemblyName.CodeBase = pathToAssembly;
Assembly assembly = dom.Load(assemblyName);
Type [] types = assembly.GetTypes();
AppDomain.Unload(dom);
however, i got an exception "Friendlyname or appdomainbase invalid
", while loading the assembly into the appdomain.
Can anyone help me
As the exception implies - it's just that it can't find the assembly.
You need to need to use the AppDomainSetup type when creating the AppDomain and set the ApplicationBase to the folder where you want it to probe for assemblies when using the Load method. You can also set the PrivateBinPath as well for additional paths.
This other MSDN topic (linked from the previous one) gives an example.
Providing a CodeBase in the AssemblyName will not work.