开发代码过程中,可能需要定时执行一些操作,如重新启动计算机,备份数据库等;这些简单操作可以通过使用WINDOWS的计划任务设置完成。但其他较复杂任务,如根据参数进行数据库数据整理,根据数据库指定时间执行特定操作,计划任务往往力不从心了。SQL SERVER的调度任务也提供了定时执行的功能,但对于动态执行DLL也无能为力。
为此,我开发一可定时执行指定代码dll的服务类,为防止执行异常影响其他代码,我使用的新建独立应用程序域作为DLL代码执行的应用程序域。

定时服务配置文件保存了程序集的配置项,采用DATASET直接生成XML文件形式。定时服务配置器用于编辑定时服务配置文件。程序集为标准.NET DLL或EXE文件。通过使用服务配置器,可在不修改任何已有代码的前提下,定时执行指定代码。

核心代码如下

ClassProcess
Imports System.Reflection.Assembly
Imports System.Reflection
Imports System.Security.Policy


'===========================================================
'类名:ClassProcess
'功能:在其他程序域中执行程序
'时间:2005-9-25
'===========================================================


Public Class ClassProcessClass ClassProcess

'文件名称,类名称,方法名称
Private sfile As String, sClassname As String, sMethodname As String
Private log As ClassLog


Public Sub CallDll()Sub CallDll()

Try
Dim setup As New AppDomainSetup

Dim fi As New System.IO.FileInfo(sfile)
setup.ApplicationBase = fi.DirectoryName

'此语句居然无用
setup.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory

'配置文件名称为文件名称加上后缀
setup.ConfigurationFile = sfile & ".config"
'应用程序名称为类名称
setup.ApplicationName = sClassname

setup.ShadowCopyFiles = True
setup.ShadowCopyDirectories = AppDomain.CurrentDomain.BaseDirectory

Dim adevidence As System.Security.Policy.Evidence = AppDomain.CurrentDomain.Evidence

'设置本程序集在本机运行
adevidence.AddHost(New Zone(Security.SecurityZone.MyComputer))

Dim domain As AppDomain = AppDomain.CreateDomain(sClassname, adevidence, setup)

Dim obj As ClassLoad.ClassRem = CType(domain.CreateInstanceAndUnwrap( _
"ClassLoad", "ClassLoad.ClassRem"), ClassLoad.ClassRem)

obj.CallDll(sfile, sClassname, sMethodname)

AppDomain.Unload(domain)

Catch ex As Exception
log.WriteFtpFiles(ex.ToString)
End Try

End Sub


Public Sub New()Sub New(ByVal s1 As String, ByVal s2 As String, ByVal s3 As String)

log = New ClassLog
sfile = s1
sClassname = s2
sMethodname = s3

End Sub
End Class


ClassRem
Imports System.Reflection.Assembly
Imports System.Reflection


'===========================================================
'类名:ClassLoa.ClassRem
'功能:程序集自动加载类
'时间:2005-9-25
'===========================================================


Public Class ClassRemClass ClassRem

'必须继承,确保引用封送
Inherits MarshalByRefObject


Public Sub New()Sub New()

End Sub

'_______________________________________________________
'函数:CallDll
'功能:执行程序集
'参数:[in] sfile dll文件名称
'参数:[in] sClassname dll类型名称
'参数:[in] sMethodname dll方法名称
'时间:2005-9-14
'_______________________________________________________

Public Sub CallDll()Sub CallDll(ByVal sfile As String, ByVal sClassname As String, ByVal sMethodname As String)

'记录日志
Dim log As New ClassLog

If sfile = "" OrElse sClassname = "" OrElse sMethodname = "" Then Return

Try
log.WriteFtpFiles("加载DLL" & sfile)
Dim a1 As [Assembly] = [Assembly].LoadFrom(sfile)

If a1 Is Nothing Then Return

log.WriteFtpFiles("加载类" & sClassname)
Dim t As Type = a1.GetType(sClassname)

If t Is Nothing Then Return

log.WriteFtpFiles("实例化类OBJ" & sClassname)
Dim obj As Object = Activator.CreateInstance(t)
Dim mi As MethodInfo = t.GetMethod(sMethodname)

If mi Is Nothing Then Return

log.WriteFtpFiles("执行OBJ")
mi.Invoke(obj, Nothing)

obj = Nothing

log.WriteFtpFiles("回收OBJ")
GC.Collect()

Catch ex As Exception
log.WriteFtpFiles(ex.ToString)

End Try
Return
End Sub


End Class

其中,ClassProcess用于在其他程序域中执行程序集,
setup.ApplicationBase 用于设定应用程序起始路径,
setup.PrivateBinPath 用于设定可执行文件路径。
这里出现了一个问题,如果把setup.ApplicationBase设置为CLASSCONFIG的路径,也就是服务执行的当前路径,就会出现动态执行程序集不能读取程序集配置文件的问题。如需要调用程序集为c:\test.dll其配置文件名为c:\test.dll.config这时需要把配置文件test.dll.config放在setup.ApplicationBas路径下方可正常运行,引起程序配置的不便。修改setup.PrivateBinPath没有任何作用。
如果把setup.ApplicationBase设置为待执行程序集的路径,则回出现找不到程序加载器CLASSLOAD的错误,必须把CLASSLOAD.DLL复制到程序集路径下方可正常运行。修改setup.PrivateBinPath没有任何作用。还请各位指教。
/Files/Daling/m5.rar