看起来你需要一个针对农场的功能,安装一个运行此作业的服务。以下是我是如何做到的(实际上使用了同事编写的代码,但他不在SO)。
创建一个具有功能事件接收器的feature.xml文件。
<Feature
Id="..."
Title="..."
Description="..."
Scope="Farm"
Version="1.0.0.0"
Hidden="FALSE"
ReceiverAssembly="XXX.FarmService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxx"
ReceiverClass="XXX.FarmService.XXXFarmFeatureEventReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/">
</Feature>
事件接收器内部:
public override void OnFeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPFarm farm = SPFarm.Local;
JobService myService = null;
foreach (SPService service in farm.Services)
{
if (String.Compare(service.Name, JobService.XXXServiceName, true) == 0)
{
myService = (service as JobService);
break;
}
}
if (cegService == null)
{
myService = new JobService(farm);
myService.Update();
JobServiceInstance myServiceInstance;
foreach (SPServer server in farm.Servers)
{
myServiceInstance = new JobServiceInstance(server, myService);
myServiceInstance.Update();
}
}
SPDailySchedule schedule = new SPDailySchedule();
schedule.BeginHour = 1;
schedule.EndHour = 1;
schedule.BeginMinute = 0;
schedule.EndMinute = 59;
JobCheckDocDates newJob = new JobCheckDocDates(cegService, null, SPJobLockType.Job);
newJob.Schedule = schedule;
newJob.Update();
myService.JobDefinitions.Add(newJob);
myService.Update();
}
catch (Exception e)
{
Logger.Error("[" + properties.Feature.Definition.DisplayName + "] Error during feature activation", e);
}
}
这将创建一个服务,可在农场中的每个服务器上使用。
以下是一些子类的更多细节:
public class JobCheckDocDates: Common.BaseJob
{
public static string JobName = "XXX job";
public JobCheckDocDates() : base() { }
public JobCheckDocDates(SPService service, SPServer server, SPJobLockType lockType)
: base(JobName, service, server, lockType) { }
当然还有Execute方法。
public class JobService : SPService
{
public static string XXXServiceName = "XXX Service";
public override string DisplayName
{
get
{
return XXXServiceName;
}
}
public override string TypeName
{
get
{
return "XXX Service Type";
}
}
public JobService() { }
public JobService(SPFarm farm)
: base(XXXServiceName, farm)
{
}
}
public class JobServiceInstance : SPServiceInstance
{
public static string XXXServiceInstanceName = "XXXServiceInstance";
private SPActionLink _manageLink;
private SPActionLink _provisionLink;
private SPActionLink _unprovisionLink;
private ICollection<string> _roles;
public override SPActionLink ManageLink
{
get
{
if (_manageLink == null)
{
_manageLink = new SPActionLink(SPActionLinkType.None);
}
return _manageLink;
}
}
public override SPActionLink ProvisionLink
{
get
{
if (_provisionLink == null)
{
_provisionLink = new SPActionLink(SPActionLinkType.ObjectModel);
}
return _provisionLink;
}
}
public override SPActionLink UnprovisionLink
{
get
{
if (_unprovisionLink == null)
{
_unprovisionLink = new SPActionLink(SPActionLinkType.ObjectModel);
}
return _unprovisionLink;
}
}
public override ICollection<string> Roles
{
get
{
if (_roles == null)
{
_roles = new string[1] { "Custom" };
}
return _roles;
}
}
public JobServiceInstance() : base() { }
public JobServiceInstance(SPServer server, JobService service)
: base(XXXServiceInstanceName, server, service)
{
}
现在,在中央管理界面,进入“操作/服务器服务”。选择所需的服务器并启动服务。
回答您的问题清单:
1. 只需一次部署解决方案,独立于WFE。
2. 由于该功能是针对整个农场的,应在中央管理界面中激活它。
3. SPJobLockType为SPJobLockType.Job。
这不完全是您想象的内容,但它具有一个优点,即让您轻松选择作业在哪里运行,即使在安装功能后很长时间(例如,如果一个服务器负载过重)。
OnFeatureActivated方法可能更加智能,并检查每个服务器是否存在该服务,如有需要则添加该服务。但是,在OnFeatureDeactivated中从每个服务中删除服务更简单。因此,如果您添加了新服务器,请先停用再重新激活该功能。