当在.NET中的AppDomains之间封送对象时,CLR将序列化对象(如果它具有该Serializable属性),或者它将生成代理(如果它继承自MarshalByRef)
但是对于字符串,CLR只会将对字符串对象的引用传递给新的AppDomain.CLR仍然确保完整性,因为.NET字符串是不可变的,并且第二个AppDomain对字符串的任何更改都不会影响原始对象.
这让我想到了一个问题:有没有办法告诉CLR我的自定义类型是不可变的,当用于远程处理它应该只是传递对象的引用,就像它对字符串类一样?
我很好奇是否有任何类似于.Net的AppDomain的Java抽象.
特别是,我很好奇,因为我发现使用我们的Coldfusion/J2EE服务器,我们需要每隔几天重新启动它,因为我们还没有能够轻松跟踪内存泄漏.这可能会破坏我们长期运行的流程,而且我们真的想要一种慢慢地将人们推向新JVM的方法,因为他们已经超过了某个时间段/内存阈值.
从我有限的.Net经验来看,我非常肯定这是IIS和AppDomains能够通过回收内存压力下的AppDomain无缝管理的一种情况.如果我在这个场景中帮助AppDomains,请告诉我.
有什么建议?
是否可以将lambda表达式作为IL字节流传递给辅助AppDomain,然后使用DynamicMethod将其组装回那里,以便可以调用它?
我不太确定这是一个正确的方法,所以这是(详细的)原因我问这个问题...
在我的应用程序中,有很多情况需要加载几个程序集进行反射,因此我可以确定接下来要对它们做些什么.问题部分是我需要能够在完成反射之后卸载组件.这意味着我需要使用另一个加载它们AppDomain.
现在,我的大多数情况都有点类似,但不完全相同.例如,有时我需要返回一个简单的确认,有时我需要从程序集中序列化资源流,有时我还需要进行一两次回调.
因此,我最终AppDomain一遍又一遍地编写相同的半复杂临时创建代码,并实现自定义MarshalByRefObject代理以在新域和原始域之间进行通信.
由于这不再是可以接受的,我决定编写一个AssemblyReflector可以这样使用的类:
using (var reflector = new AssemblyReflector(@"C:\MyAssembly.dll"))
{
bool isMyAssembly = reflector.Execute(assembly =>
{
return assembly.GetType("MyAssembly.MyType") != null;
});
}
Run Code Online (Sandbox Code Playgroud)
AssemblyReflector将AppDomain凭借自动卸载IDisposable,并允许我执行一个透明地Func<Assembly,object>将反射代码保存在另一个中的-type lambda AppDomain.
问题是,lambdas不能简单地传递给其他域.所以在搜索之后,我发现看起来像是一种方法:将lambda传递给新AppDomain的IL作为IL流 - 这让我想到了原始问题.
这是我尝试过的,但没有用(BadImageFormatException在尝试调用新委托时问题被抛出):
public delegate object AssemblyReflectorDelegate(Assembly reflectedAssembly);
public class AssemblyReflector : IDisposable
{
private AppDomain _domain;
private string _assemblyFile;
public AssemblyReflector(string fileName) { ... }
public void Dispose() { ... …Run Code Online (Sandbox Code Playgroud) 我正在尝试在appdomain中创建一个对象:
var type = typeof (CompiledTemplate);
var obj = (CompiledTemplate) domain.CreateInstanceAndUnwrap (
type.Assembly.FullName, type.FullName);
Run Code Online (Sandbox Code Playgroud)
但是,我总是收到以下错误:
无法转换透明代理以键入"Mono.TextTemplating.CompiledTemplate".
我运行的是.NET 4.0,而不是Mono,尽管命名空间可能会提示:)
据我所知,当.NET认为类型和程序集在两个域中不完全匹配时会发生此错误.但是,在调试时,FullName和Location是相同的.只有Assembly.Codebase属性不同 - 在子AppDomain中,由于某种原因,它的扩展名大写为"DLL".
我已经尝试将AssemblyResolve处理程序添加到AppDomain,它使用Assembly.LoadFrom显式加载文件名,但CodeBase的扩展仍然是大写的.由于原始程序集也加载了Assembly.LoadFrom(通过Mono.Addins),CodeBase值之间的差异似乎很奇怪.
有关修复或解决此问题的建议吗?
是否可以在我的.Net应用程序中运行IronPython解释器,但是在沙盒中?我想拒绝IP脚本访问文件系统,同时仍然允许应用程序本身访问.
这会涉及在第二个AppDomain中运行脚本引擎吗?我怎么能把它戴上手铐让它不能随便做什么呢?
我正在通过Microsoft .Net Framework - 应用程序开发基础培训工具包第8章第2课:配置应用程序域
ShowWinIni是我想要执行的程序的程序集名称
object[] hostEvidence = { new Zone(SecurityZone.MyComputer) };
Evidence e = new Evidence(hostEvidence, null);
// Create an AppDomain.
AppDomain d = AppDomain.CreateDomain("New Domain", e);
// Run the assembly
d.ExecuteAssemblyByName("ShowWinIni");
Run Code Online (Sandbox Code Playgroud)
当我执行:
AppDomain d = AppDomain.CreateDomain("New Domain", e);
Run Code Online (Sandbox Code Playgroud)
我收到以下消息:"此方法隐式使用CAS策略,已被.NET Framework废弃.为了兼容性原因启用CAS策略,请使用NetFx40_LegacySecurityPolicy配置开关.请参阅http://go.microsoft .com/fwlink /?LinkID = 155570了解更多信息."
当我创建一个没有Evidence对象的AppDomain时,我可以正常执行程序集.
当然,我访问过http://go.microsoft.com/fwlink/?LinkID=155570,但我仍然对如何创建具有指定权限的应用程序域感到困惑.
我找到的下一个最有用的网站是http://msdn.microsoft.com/en-us/library/bb763046.aspx但我的StrongName对象计算为NULL.
StrongName fullTrustAssembly =
typeof(Program).Assembly.Evidence.GetHostEvidence<StrongName>();
Run Code Online (Sandbox Code Playgroud)
程序是实现所有这些代码的类的名称.
提前感谢您的建议和提示!
我的印象是AppDomains彼此隔离.似乎在StackOverException的情况下,情况并非如此.
为了演示这个问题,我创建了一个简单的控制台应用程序,其唯一目的是生成一个新的AppDomain,我在其中加载一个非常简单的程序集并调用其中一个方法.此方法恰好抛出StackOverflowException.这导致我的控制台应用程序毫不客气地终止.
我希望的行为是"子"AppDomain崩溃并在这样的异常上刻录,但是保持我的控制台应用程序在"父"AppDomain中运行,没有受到损坏.
这可能吗?
更新:这是一些代码.两个异常处理程序都没有被命中.
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
// create app domain
var domain = AppDomain.CreateDomain("MyDomain");
// create a component
var component = (MyComponent)domain.CreateInstanceAndUnwrap(
"AppDomainMonitor.Component",
typeof(MyComponent).FullName);
// create a thread from a method on this component
var thread = new Thread(component.CauseStackOverflow);
// start the thread
thread.Start();
Console.ReadKey();
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// never hit
}
}
public class MyComponent : MarshalByRefObject
{
public void CauseStackOverflow()
{
try
{ …Run Code Online (Sandbox Code Playgroud) 我正在构建一个.net C#控制台程序,以将文件部署到Windows文件共享服务器(正在共享的文件夹).路径是::\\192.168.0.76\htdocs\public
在运行时我收到错误:
[09:35:29]: [Step 1/3] Unhandled Exception: System.UnauthorizedAccessException: Access to the path '\\192.168.0.76\htdocs\public' is denied.
[09:35:29]: [Step 1/3] at DeployFileShare.Program.CopyDir(String source, String dest, String[] exclude, Boolean overwrite)
[09:35:29]: [Step 1/3] at DeployFileShare.Program.Deploy(String num, String source)
[09:35:29]: [Step 1/3] at DeployFileShare.Program.Main(String[] args)
[09:35:29]: [Step 1/3] Process exited with code -532459699
Run Code Online (Sandbox Code Playgroud)
我想我需要对自己进行身份验证.我遇到过这个:
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsIdentity idnt = new WindowsIdentity(username, password);
WindowsImpersonationContext context = idnt.Impersonate();
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
AppDomain.CreateDomain("192.168.0.76").SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsIdentity idnt = new WindowsIdentity("user", "pass");
WindowsImpersonationContext context = idnt.Impersonate();
Run Code Online (Sandbox Code Playgroud)
我不知道如何使用它.当我运行应用程序时,我得到:
C:\Users\Administrator>DeployFileShare 1 R:\BuildOutput\_PublishedWebsites\Web 2 …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用插件进行应用程序.
我有MainLib.dll,我ICommon用1方法制作了一些commnon接口(让它成为).然后,我制作了2个.dll(插件),它们引用了MainLib.dll并ICommon在某些类中实现了.另外,我删除了这个.dll exept中的所有引用System.
然后,我创建了一个应用程序,它监视文件夹".\\Plugins"并加载所有.dll newDomain,检查.dll中的类型是否实现ICommon(因此该应用程序也引用MainLib.dll).如果是 - 在某些列表中添加.dll的名称.
现在问题出现了:在我尝试加载插件之前 - 我将MailLib.dll和System加载到newDomain,因为所有插件都依赖于此.dll.他们加载正确.然后,我开始加载插件,在这里我有:
FileNotFoundException,无法加载文件或程序集'PluginWithException,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'或其依赖项之一.系统找不到指定的文件.)字符串Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName);
PluginWithException程序集只有2个依赖项--System和MainLib.在我尝试加载PluginWithException之前,我检查了新域中的程序集,System和MainLib已加载到此域.所以我看不到任何依赖的问题.我读了这个主题,尝试了解决方案,ProxyDomain但异常是一样的.
我做错了什么?
这里的代码:
public static List<string> SearchPlugins(string[] names)
{
AppDomain domain = AppDomain.CreateDomain("tmpDomain");
domain.Load(Assembly.LoadFrom(@".\MainLib.dll").FullName);
domain.Load(@"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
MessageBox.Show(GetAssembies(domain)); // here I can see that System and MailLib exist in new domain
List<string> plugins = new List<string>();
foreach (string asm in names)
{
Assembly …Run Code Online (Sandbox Code Playgroud) 我的C#应用程序使用的本机代码不是线程安全的.
我可以运行该本机代码的多个进程,使用进程间通信来实现并发.
我的问题是,我是否可以使用App Domains,以便多个托管线程(每个托管在不同的应用域上)将调用本机代码并且它们不会相互干扰?
主要目标是防止过程分离.