我有一个WCF服务库(MyWCFService
),它使用MEF
加载插件并由Windows服务托管(All .NET 4.0)。我现在尝试在新的AppDomain
中运行它并启用ShadowCopyFiles
,希望我可以在运行时更新插件。这是Windows服务项目中的代码。
Program.cs的
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
}
MyService.cs
public partial class MyService: ServiceBase
{
internal static ServiceHost MyServiceHost = null;
public MyService()
{
// this works but is deprecated..
AppDomain.CurrentDomain.SetShadowCopyFiles();
//this is not working.. DLLs still get locked. Require for a new AppDomain
//AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles = "true";
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if(MyServiceHost !=null)
{
MyServiceHost.Close();
}
try
{
MyServiceHost= new ServiceHost(typeof(MyWCFService));
MyServiceHost.Open();
}
catch(Exception)
{
}
}
protected override void OnStop()
{
if (MyServiceHost!= null)
{
MyServiceHost.Close();
MyServiceHost= null;
}
}
}
有没有办法呢?我做了很多搜索,但仍然不知道如何使用我当前的设置(或者我无法理解......)
我尝试在AppDomain
内创建一个新的Main()
并使用
domain.DoCallBack(new CrossAppDomainDelegate(() => { ServiceBase.Run(ServicesToRun); }))
启动服务,但我无法启动服务并继续"Error 1053: The service did not respond to the start or control request in a timely fashion"
。
然后我尝试在AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles = "true";
MyWCFService.cs
InitializeComponent();
之前AppDomain.CurrentDomain.SetShadowCopyFiles();
启用服务但是dll仍处于锁定状态,从而为当前appdomain启用了Shadow copy。但是,如果我使用{{1}}(一种已弃用的方法)来启用卷影副本,一切正常。我更困惑了。
答案 0 :(得分:1)
好的,我最终创建了一个继承自MarshalByRefObject
的shell / proxy类,并从那里启动服务,这里是代码:
ServiceShell.cs
public class ServiceShell:MarshalByRefObject
{
internal static ServiceHost MyServiceHost = null;
public void Run()
{
if (MyServiceHost != null)
{
MyServiceHost.Close();
}
try
{
MyServiceHost = new ServiceHost(typeof(MyWCFService));
MyServiceHost.Open();
}
catch (Exception)
{
}
}
public void Stop()
{
if (MyServiceHost!= null)
{
MyServiceHost.Close();
MyServiceHost = null;
}
}
}
MyService.cs
public partial class MyService: ServiceBase
{
AppDomain domain;
ServiceShell runner;
public MyService()
{
var setup = new AppDomainSetup
{
ShadowCopyFiles = "true"
};
domain = AppDomain.CreateDomain("MyServiceHostDomain", AppDomain.CurrentDomain.Evidence, setup);
runner = (ServiceShell)domain.CreateInstanceAndUnwrap
(typeof(ServiceShell).Assembly.FullName, typeof(ServiceShell).FullName);
InitializeComponent();
}
protected override void OnStart(string[] args)
{
runner.Run();
}
protected override void OnStop()
{
runner.Stop();
AppDomain.Unload(domain);
}
}