我的.NET应用程序有不同版本的dll,大多数时候我想使用最新版本的dll.但是,有一种方法我在一个单独的线程上运行,我需要能够根据某些条件选择较旧版本的dll.
我已经知道不可能只加载一个程序集然后在默认的应用程序域中卸载它(我不能只保持两个版本都加载,因为那时我遇到了类型问题的重复定义)
可能我必须创建一个单独的AppDomain,在那里加载程序集然后卸载它.此应用程序域将在单独的线程上执行一个方法,并且可以使用该库的不同版本.
你认为这是一个好方法/你有更好的想法/你能指出一些能让我入手的资源吗?
非常感谢 ;)
我正在编写一个插件架构.我的插件dll位于运行插件管理器的子目录中.我将插件加载到单独的AppDomain中,如下所示:
string subDir;//initialized to the path of the module's directory.
AppDomainSetup setup = new AppDomainSetup();
setup.PrivateBinPath = subDir;
setup.ApplicationBase = subDir;
AppDomain newDomain= AppDomain.CreateDomain(subDir, null, setup);
byte[] file = File.ReadAllBytes(dllPath);//dll path is a dll inside subDir
newDomain.Load(file);
Run Code Online (Sandbox Code Playgroud)
然而.newDomain.Load返回当前域尝试加载的程序集.因为插件dll位于子目录中,所以当前域不能也不应该看到这些dll,并且当前域抛出FileLoadException"ex = {"无法加载文件或程序集......或其依赖项之一.
问题是,我们可以将程序集加载到单独的AppDomain中而不返回已加载的程序集吗?
我知道我可以在当前域中为AssemblyResolve事件添加一个处理程序并返回null,但我宁愿不去这条路线.
提前致谢.
因为并非我想要实例化的类中使用的所有类都是可序列化的,所以我无法解包.
这可能吗?
var appdom = AppDomain.CreateDomain(amServiceable.GetType().ToString());
var objectHandle = appdom.CreateInstance(amServiceable.GetType().Assembly.FullName,
amServiceable.GetType().FullName);
var plugin = objectHandle.Unwrap() as IPlugin //throws an error. that some class in not marked serializable.
Run Code Online (Sandbox Code Playgroud) WCF中AppDomain的生命周期是多少?
它与InstanceContextMode,ConcurrencyMode和/或AspNetCompatibilityRequirements RequirementsMode有关吗?
我想知道我的静态变量将存在多长时间以及它们必须重新创建的频率.
如果我们创建两个具有相同友好名称的appdomains,任何人都可以知道发生了什么吗?
static void Main(string[] args)
{
var myDomain = AppDomain.CreateDomain("mydomain");
var myDomain2 = AppDomain.CreateDomain("mydomain");
}
Run Code Online (Sandbox Code Playgroud)
正如我注意到这不是抛出异常,也许两个局部变量指向同一个appdomain?
目标:我需要在权限非常有限的 AppDomain 中运行一些代码 -除了我在其他地方定义的一些辅助方法之外,它不应该访问任何花哨或不安全的内容。
我所做的:我正在创建一个具有所需基本权限的沙箱 AppDomain,并创建一个运行代码的代理对象:
static AppDomain CreateSandbox()
{
var e = new Evidence();
e.AddHostEvidence(new Zone(SecurityZone.Internet));
var ps = SecurityManager.GetStandardSandbox(e);
var security = new SecurityPermission(SecurityPermissionFlag.Execution);
ps.AddPermission(security);
var setup = new AppDomainSetup {
ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
};
return AppDomain.CreateDomain("Sandbox" + DateTime.Now, null, setup, ps);
}
public class Proxy : MarshalByRefObject
{
public Proxy() { }
public DoStuff()
{
// perform custom operation requiring permission
HelperAssembly.HelperMethods.Method1();
// do other stuff with low permission level
...
...
...
} …Run Code Online (Sandbox Code Playgroud) 我有一个.NET 3.5 SP1应用程序,它是一个Excel加载项.应用程序分为父AppDomain(Excel)和子域,我们在其中加载所有dll.当我们希望更新我们的应用程序时,我们卸载子域,替换文件并重新加载它.
不幸的是,卸载域将激活2个工作线程,并且它们将开始消耗CPU周期(20-40%).
如果我使用VS 2010调试,在此之前和之后的那一刻AppDomain.Unload,除了Excel的主线程之外,没有线程处于调用堆栈的活动状态.这AppDomain.Unload确实是卸载的,因为如果我再次尝试调用Unload,我会得到一个AppDomainUnloadedException.
如果我使用ProcessExplorer,我可以看到2个线程正忙着工作,即使VS调试器已经破坏.看着callstack没有显示任何东西,因为没有符号.
如果我使用WinDbg,我可以看到2个renegade线程的callstack.它总是一样的:
我创建了一个非常简单的测试应用程序来加载/卸载子程序集.使用简单的1级装配执行此操作时,它可以正常工作.如果我让它加载/卸载真实应用程序的子域,它会触发相同的renegade线程.
创建子域的代码如下:
AppDomainSetup appSetup = new AppDomainSetup();
appSetup.ApplicationBase = baseDir;
var ps = new PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
return AppDomain.CreateDomain(name, null, appSetup, ps, null);
Run Code Online (Sandbox Code Playgroud)
从父域到子域的通信是通过代理和反射进行的.创建它的代码如下:
string …Run Code Online (Sandbox Code Playgroud) 是否有一个卸载事件,或者任何事件,通知,消息,机制或挂钩,可以用来在“默认”应用程序域卸载之前得到通知?
我有一些代码需要知道应用程序域(几乎总是默认域)何时结束。
注意:我不知道开发人员在使用我的代码时将创建什么样的应用程序。它可能是:
无论哪种方式,我都需要知道域关闭的时间,以便我可以执行一些“工作”。而且我不会要求用户调用任何形式的“关闭”或“清理”方法。(此外,建议要求用户自己调用方法并不能回答问题:这是有关在我正在运行的应用程序域关闭时收到通知的)。
由于AppDomin.GetCurrentThreadId()已过时
"AppDomain.GetCurrentThreadId已被弃用,因为当托管线程在光纤(也称为轻量级线程)上运行时,它不提供稳定的Id.要获取托管线程的稳定标识符,请使用Thread上的ManagedThreadId属性 .http:// go .microsoft.com/fwlink /?linkid = 14202 "
我尽量不使用它.但是,'Thread.CurrentThread.ManagedThreadId'可以解释的解释是没有价值的,因为它没有提供Win32线程ID,这是Win32调用所需要的.所以我自己实现如下.
public sealed class AppDomainExtender
{
public static int GetCurrentThreadId_New()
{
return Process.GetCurrentProcess().Threads.OfType<ProcessThread>().SingleOrDefault(x => x.ThreadState == System.Diagnostics.ThreadState.Running).Id;
}
}
Run Code Online (Sandbox Code Playgroud)
现在有两个问题.
问题:
TL; DR:如何通过杀死主进程来隔离加载项异常?
我希望有一个非常稳定的.Net应用程序,它运行的代码不太稳定AppDomain.这似乎是最初的主要目的之一AppDomain(嗯,那和安全沙箱),但它似乎不起作用.
例如AddIn.exe:
public static class Program
{
public static void Main(string[] args)
{
throw new Exception("test")
}
}
Run Code Online (Sandbox Code Playgroud)
在我的"稳定"代码中调用:
var domain = AppDomain.CreateDomain("sandbox");
domain.UnhandledException += (sender, e) => {
Console.WriteLine("\r\n ## Unhandled: " + ((Exception) e.ExceptionObject).Message);
};
domain.ExecuteAssemblyByName("AddIn.exe", "arg A", "arg B")
Run Code Online (Sandbox Code Playgroud)
将抛出的异常AppDomain直接传递给创建域的应用程序.我可以记录这些domain.UnhandledException并在包装器应用程序中捕获它们.
但是,抛出更多有问题的异常,例如:
public static class Program
{
public static void Main(string[] args)
{
Stackoverflow(1);
}
static int Stackoverflow(int x)
{
return Stackoverflow(++x);
}
}
Run Code Online (Sandbox Code Playgroud)
这将抛出stackoverflow异常,每次都会终止整个应用程序.它甚至没有开火domain.UnhandledException …
appdomain ×10
c# ×9
.net ×4
asp.net ×2
assemblies ×2
atomic ×1
clr ×1
reflection ×1
static ×1
wcf ×1