我试图将一个DLL加载到控制台应用程序,然后卸载它并完全删除该文件.我遇到的问题是,在自己的AppDomain中加载dll的行为会在Parent AppDomain中创建一个引用,因此不允许我销毁dll文件,除非我完全关闭程序.有关使此代码有效的任何想法?
string fileLocation = @"C:\Collector.dll";
AppDomain domain = AppDomain.CreateDomain(fileLocation);
domain.Load(@"Services.Collector");
AppDomain.Unload(domain);
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我也尝试过这段代码而且没有运气
string fileLocation = @"C:\Collector.dll";
byte[] assemblyFileBuffer = File.ReadAllBytes(fileLocation);
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = Environment.CurrentDirectory;
domainSetup.ShadowCopyFiles = "true";
domainSetup.CachePath = Environment.CurrentDirectory;
AppDomain tempAppDomain = AppDomain.CreateDomain("Services.Collector", AppDomain.CurrentDomain.Evidence, domainSetup);
//Load up the temp assembly and do stuff
Assembly projectAssembly = tempAppDomain.Load(assemblyFileBuffer);
//Then I'm trying to clean up
AppDomain.Unload(tempAppDomain);
tempAppDomain = null;
File.Delete(fileLocation);
Run Code Online (Sandbox Code Playgroud) 我想在AppDomains中使用一个对象.
为此,我可以使用[Serializeable]属性:
[Serializable]
class MyClass
{
public string GetSomeString() { return "someString" }
}
Run Code Online (Sandbox Code Playgroud)
或MarshalByRefObject的子类:
class MyClass: MarshalByRefObject
{
public string GetSomeString() { return "someString" }
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我都可以使用这样的类:
AppDomain appDomain = AppDomain.CreateDomain("AppDomain");
MyClass myObject = (MyClass)appDomain.CreateInstanceAndUnwrap(
typeof(MyClass).Assembly.FullName,
typeof(MyClass).FullName);
Console.WriteLine(myObject.GetSomeString());
Run Code Online (Sandbox Code Playgroud)
为什么两种方法似乎都有相同的效果?两种方法有什么不同?我什么时候应该支持另一种方法呢?
编辑:从表面上看,我知道两种机制之间存在差异,但如果有人跳出丛林并问我这个问题,我无法给他一个正确的答案.问题是非常开放的问题.我希望有人可以比我能做的更好地解释它.
我有一个应用程序从一个appdomain初始化log4net,需要在另一个appdomain中使用它.是否支持?
如果没有,我应该从每个appdomain初始化log4net吗?在同一个应用程序中进行多次初始化是否存在风险?我应该使用相同的log4net.config吗?
更新 - 复制问题的过程:
1)在c:\ projects\restart-demo创建一个网站项目
2)添加默认的web.config和一个虚拟的aspx页面test.aspx
3)映射IIS以指向根文件夹c:\ projects\restart-demo
4)使用perfmon,运行状况监视,global.asax Application_End等跟踪监视应用程序重启.
5)浏览器http://localhost/test.aspx中的请求页面
申请开始
6)创建新文件夹c:\ projects\restart-demo\asdf
申请结束
7)浏览器http://localhost/test.aspx中的请求页面
申请开始
8)将文件夹c:\ projects\restart-demo\asdf重命名 为 c:\ projects\restart-demo\asdf1
申请结束
结束更新
我们使用后端CMS在ASP.NET站点中生成文件和文件夹.
用户可以创建/修改/删除文件并将其推送到Web场.
我们注意到的一个问题:
当用户创建,重命名或删除文件夹时,会导致App Domain重新启动.结果,会话,缓存等都丢失了.
请注意,它不需要是/ bin或/ App_Code之类的特殊文件夹.
有什么方法可以防止这种行为吗?
它实际上阻碍了性能,原因有两个:
asp.net appdomain application-pool content-management-system
我正在使用第三方程序集,不幸的是我现在需要将他们的最新版本和以前的版本加载到我的项目中,所以在运行时我可以决定加载哪一个.我只需要一个,而不是两个.
考虑到这一点,我也依赖于组件提供的类型,因此我不能每次为我想要使用的方法/事件/接口从反射和查询加载.我已经看到一些提到通过AppDomains 处理这个,但我不知道如何继续.
该过程是针对组件的一个版本进行编码,然后在运行时(使用AppDomain)交换我想要使用的正确DLL吗?所以我只会在启动时处理这个问题?
我的目标是创建一个可启动影子复制应用程序的可执行文件.诀窍是,我希望这个入门程序没有外部依赖关系,并且不必包含任何有关它必须启动的程序的知识.
我也希望它是目录中唯一的可执行文件.换句话说,我希望它"运行".dll程序集而不是.exe程序集.(我可以要求每次加载到新AppDomain中的.dll文件的名称都是相同的,比如Main.dll或类似的东西.)
它看起来像AppDomain.ExecuteAssembly将完全按照我的意愿行事.它表示它将在".NET Framework标头中指定的入口点"开始执行.
当我尝试使用该功能时,我收到错误"在程序集中找不到入口点'DllApp'".
我有启动程序,只是试图运行程序集:
static void Main()
{
AppDomain domain = AppDomain.CreateDomain( "DllApp" );
domain.ExecuteAssembly( "DllApp.dll" );
}
Run Code Online (Sandbox Code Playgroud)
应用程序代码,在.dll文件中,带有默认入口点:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
Application.Run( new Form1() );
}
}
Run Code Online (Sandbox Code Playgroud)
Main()函数的这个页面说"库和服务不需要Main方法作为入口点".它并没有说它们也没有默认入口点.
我已经尝试了public/private static void main的所有各种排列,int返回类型,string [] args作为参数,带有命名空间,没有命名空间,静态/非静态类等.
我能够将我的代码更改为继承MarshalByRefObject,然后使用CreateInstance创建一个对象,但这似乎会将启动器更紧密地耦合到它应该启动的程序.如果我可以使用ExecuteAssembly,那么正在启动的应用程序只需要一个静态的void Main,这非常简单而且很难搞乱.
.dll程序集是否有可能具有默认入口点,并且ExecuteAssembly可以找到它,或者我是否只需要让自己去另一条路径?
我有一个我使用的库,它使用WCF调用http服务来获取设置.通常,第一次调用需要约100毫秒,后续调用只需几毫秒.但是我发现当我创建一个新的AppDomain时,来自该AppDomain的第一个WCF调用需要2.5秒.
有没有人解释或解决为什么在新的AppDomain中首次创建WCF频道需要这么长时间?
这些是基准测试结果(当在64位版本中没有附带调试器的情况下运行时),请注意第二组数字中的第一个连接如何延长25倍
Running in initial AppDomain
First Connection: 92.5018 ms
Second Connection: 2.6393 ms
Running in new AppDomain
First Connection: 2457.8653 ms
Second Connection: 4.2627 ms
Run Code Online (Sandbox Code Playgroud)
这不是一个完整的例子,但显示了我生成这些数字的大部分内容:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Running in initial AppDomain");
new DomainRunner().Run();
Console.WriteLine();
Console.WriteLine("Running in new thread and AppDomain");
DomainRunner.RunInNewAppDomain("test");
Console.ReadLine();
}
}
class DomainRunner : MarshalByRefObject
{
public static void RunInNewAppDomain(string runnerName)
{
var newAppDomain = AppDomain.CreateDomain(runnerName);
var runnerProxy = (DomainRunner)newAppDomain.CreateInstanceAndUnwrap(typeof(DomainRunner).Assembly.FullName, typeof(DomainRunner).FullName);
runnerProxy.Run();
}
public void Run()
{
AppServSettings.InitSettingLevel(SettingLevel.Production); …Run Code Online (Sandbox Code Playgroud) 我在哪里可以购买.app顶级域名(TLD)?
我去过Network Solutions,GoDaddy等,找不到销售.app域名的人(例如http://example.app).
我们有一个大型的.NET解决方案,其中包含相互引用的C#和C++/CLI项目.我们还有几个单元测试项目.我们最近从Visual Studio 2010和.NET 4.0升级到Visual Studio 4.5和.NET 4.5,现在当我们尝试运行单元测试时,在测试期间加载某些DLL似乎存在问题.
问题似乎发生,因为单元测试是在单独的AppDomain上执行的.单元测试过程(例如nunit-agent.exe)创建一个新的AppDomain,AppBase设置为测试项目的位置,但是根据Fusion Log,一些DLL加载了nunit的可执行文件目录作为AppBase而不是AppDomain的AppBase .
我设法用一个更简单的场景重现问题,它创建了一个新的AppDomain并尝试在那里运行测试.这是它的外观(我更改了单元测试类的名称,方法和dll的位置以保护无辜者):
class Program
{
static void Main(string[] args)
{
var setup = new AppDomainSetup {
ApplicationBase = "C:\\DirectoryOfMyUnitTestDll\\"
};
AppDomain domain = AppDomain.CreateDomain("MyDomain", null, setup);
ObjectHandle handle = Activator.CreateInstanceFrom(domain, typeof(TestRunner).Assembly.CodeBase, typeof(TestRunner).FullName);
TestRunner runner = (TestRunner)handle.Unwrap();
runner.Run();
AppDomain.Unload(domain);
}
}
public class TestRunner : MarshalByRefObject
{
public void Run()
{
try
{
HtmlTransformerUnitTest test = new HtmlTransformerUnitTest();
test.SetUp();
test.Transform_HttpEquiv_Refresh_Timeout();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我尝试执行单元测试时遇到的异常.正如您所看到的,问题发生在C++ dll初始化并尝试加载C#dll(我将所涉及的DLL的名称更改为CPlusPlusDll和CSharpDll):
System.TypeInitializationException: …
首先,问题是:CLR规范是否保证在同一进程中的多个应用程序域中执行的代码将共享相同的地址空间?通过"共享地址空间",我的意思是指向在一个应用程序域中分配的内存的指针对于在同一进程内托管的所有应用程序域中进行读写是有效的.
请考虑这个自包含的示例来说明问题:程序Worker在单独的应用程序域中分配对象.该Worker分配10000个整数一个内存块,并用数据填充进去.然后,程序调用app域边界以获取指向已分配块的指针,并验证它是否可以读取10,000个项目中的每一个.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace crossapp {
public class Worker : MarshalByRefObject {
private readonly IntPtr myData;
public const int DataLength = 10000;
public Worker() {
Console.Error.WriteLine(
"Memory allocation happens in app domain '{0}'"
, Assembly.GetExecutingAssembly().FullName
);
myData = Marshal.AllocHGlobal(sizeof(int) * DataLength);
unsafe {
var ptr = (int*) myData.ToPointer();
for (var i = 0 ; i != DataLength ; i++) {
ptr[i] = 2*i + 1;
}
}
}
public IntPtr GetData() …Run Code Online (Sandbox Code Playgroud) appdomain ×10
c# ×6
.net ×2
assemblies ×2
.app ×1
.net-4.5 ×1
asp.net ×1
c#-4.0 ×1
c++-cli ×1
dns ×1
domain-name ×1
entry-point ×1
log4net ×1
memory ×1
performance ×1
pointers ×1
remoting ×1
tld ×1
unit-testing ×1
wcf ×1