Projektdateien hinzufügen.

This commit is contained in:
Jonathan Jenne
2022-12-01 16:37:39 +01:00
parent 622c632b65
commit c867e4e3a6
101 changed files with 5117 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>

View File

@@ -0,0 +1,11 @@
Imports DigitalData.Modules.Config.ConfigAttributes
Public Class Config
Public Property Debug As Boolean = False
<ConnectionString>
Public Property ConnectionString As String = String.Empty
Public Property Host As String = "localhost"
Public Property Port As Integer = 9000
Public Property Name As String = "JobRunner"
End Class

View File

@@ -0,0 +1,10 @@
Public Class Constants
Public Const SERVICE_NAME As String = "DDECMJOBRUNNERService"
Public Const SERVICE_DISPLAY_NAME As String = "Digital Data ECM JobRunner Service"
Public Class Scheduler
Public Const JOB_CONFIG_LOGCONFIG = "LogConfig"
Public Const JOB_CONFIG_ARGUMENTS = "Arguments"
Public Const JOB_CONFIG_DATABASE = "Database"
End Class
End Class

View File

@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2D8E3AD4-ABBB-49DB-8BCA-817DF6925275}</ProjectGuid>
<OutputType>WinExe</OutputType>
<StartupObject>ECM.JobRunner.Windows.Service</StartupObject>
<RootNamespace>ECM.JobRunner.Windows</RootNamespace>
<AssemblyName>ECM.JobRunner.Windows</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Console</MyType>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>ECM.JobRunner.Windows.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>ECM.JobRunner.Windows.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<Reference Include="DigitalData.Modules.Base">
<HintPath>..\..\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Config">
<HintPath>..\..\DDModules\Config\bin\Debug\DigitalData.Modules.Config.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Database">
<HintPath>..\..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Language, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\DDModules\Language\bin\Debug\DigitalData.Modules.Language.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Logging">
<HintPath>..\..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Messaging">
<HintPath>..\..\DDModules\Messaging\bin\Debug\DigitalData.Modules.Messaging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.5.1.0\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="Quartz, Version=3.5.0.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4, processorArchitecture=MSIL">
<HintPath>..\packages\Quartz.3.5.0\lib\net462\Quartz.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.IdentityModel" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Runtime.Remoting" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceModel.NetTcp, Version=4.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.ServiceModel.NetTcp.4.10.0\lib\net461\System.ServiceModel.NetTcp.dll</HintPath>
</Reference>
<Reference Include="System.ServiceModel.Primitives, Version=4.10.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.ServiceModel.Primitives.4.10.0\lib\net461\System.ServiceModel.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Include="Config.vb" />
<Compile Include="Constants.vb" />
<Compile Include="LogProvider.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Include="ProjectInstaller.Designer.vb">
<DependentUpon>ProjectInstaller.vb</DependentUpon>
</Compile>
<Compile Include="ProjectInstaller.vb">
<SubType>Component</SubType>
</Compile>
<Compile Include="Scheduler\JobConfig.vb" />
<Compile Include="Scheduler\JobHistory.vb" />
<Compile Include="Scheduler\JobListener.vb" />
<Compile Include="Scheduler\JobResult.vb" />
<Compile Include="Scheduler\JobScheduler.vb" />
<Compile Include="Scheduler\Jobs\DebugJob.vb" />
<Compile Include="Scheduler\Jobs\BaseJob.vb" />
<Compile Include="Scheduler\Jobs\FileImportJob.vb" />
<Compile Include="Scheduler\Jobs\FileIndexJob.vb" />
<Compile Include="Service.vb">
<SubType>Component</SubType>
</Compile>
<Compile Include="Service.Designer.vb">
<DependentUpon>Service.vb</DependentUpon>
</Compile>
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="My Project\Settings.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="State.vb" />
<Compile Include="WCF\IJobRunner.vb" />
<Compile Include="WCF\JobRunner.vb" />
<Compile Include="WCF\Methods\Base.vb" />
<Compile Include="WCF\Methods\GetJobConfig.vb" />
<Compile Include="WCF\Methods\GetJobHistory.vb" />
<Compile Include="WCF\ServiceHost.vb" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ProjectInstaller.resx">
<DependentUpon>ProjectInstaller.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Service.resx">
<DependentUpon>Service.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ECM.JobRunner.Common\ECM.JobRunner.Common.vbproj">
<Project>{7eacf04e-525b-40c8-9207-b83fb847b090}</Project>
<Name>ECM.JobRunner.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>

View File

@@ -0,0 +1,37 @@
Imports DigitalData.Modules.Logging
Imports Quartz.Logging
Public Class LogProvider
Implements ILogProvider
Private ReadOnly _Logger As DigitalData.Modules.Logging.Logger
Public Sub New(LogConfig As LogConfig)
MyBase.New()
_Logger = LogConfig.GetLogger()
End Sub
Private Function GetLogger(name As String) As Quartz.Logging.Logger Implements ILogProvider.GetLogger
Return Function(level, func, exception, parameters)
If exception IsNot Nothing Then
_Logger.Error(exception)
ElseIf level >= LogLevel.Debug AndAlso func IsNot Nothing Then
_Logger.Debug(func(), parameters)
ElseIf level >= LogLevel.Info AndAlso func IsNot Nothing Then
_Logger.Info(func(), parameters)
End If
Return True
End Function
End Function
Private Function OpenNestedContext(message As String) As IDisposable Implements ILogProvider.OpenNestedContext
_Logger.Warn("OpenNestedContext is not implemented")
Throw New NotImplementedException()
End Function
Public Function OpenMappedContext(key As String, value As Object, Optional destructure As Boolean = False) As IDisposable Implements ILogProvider.OpenMappedContext
_Logger.Warn("OpenMappedContext is not implemented")
Throw New NotImplementedException()
End Function
End Class

View File

@@ -0,0 +1,13 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>3</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -0,0 +1,35 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
' Allgemeine Informationen über eine Assembly werden über die folgenden
' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
' die einer Assembly zugeordnet sind.
' Werte der Assemblyattribute überprüfen
<Assembly: AssemblyTitle("ECM.JobRunner.Windows")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("ECM.JobRunner.Windows")>
<Assembly: AssemblyCopyright("Copyright © 2022")>
<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'Die folgende GUID wird für die typelib-ID verwendet, wenn dieses Projekt für COM verfügbar gemacht wird.
<Assembly: Guid("c1fae95f-b702-4171-82b4-ae2bdca90095")>
' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
'
' Hauptversion
' Nebenversion
' Buildnummer
' Revision
'
' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
' indem Sie "*" wie unten gezeigt eingeben:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -0,0 +1,62 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My.Resources
'This class was auto-generated by the StronglyTypedResourceBuilder
'class via a tool like ResGen or Visual Studio.
'To add or remove a member, edit your .ResX file then rerun ResGen
'with the /str option, or rebuild your VS project.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("ECM.JobRunner.Windows.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set(ByVal value As Global.System.Globalization.CultureInfo)
resourceCulture = value
End Set
End Property
End Module
End Namespace

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,73 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
#Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then
Private Shared addedHandler As Boolean
Private Shared addedHandlerLockObject As New Object
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
If My.Application.SaveMySettingsOnExit Then
My.Settings.Save()
End If
End Sub
#End If
#End Region
Public Shared ReadOnly Property [Default]() As MySettings
Get
#If _MyType = "WindowsForms" Then
If Not addedHandler Then
SyncLock addedHandlerLockObject
If Not addedHandler Then
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
addedHandler = True
End If
End SyncLock
End If
#End If
Return defaultInstance
End Get
End Property
End Class
End Namespace
Namespace My
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
Friend Module MySettingsProperty
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
Friend ReadOnly Property Settings() As Global.ECM.JobRunner.Windows.My.MySettings
Get
Return Global.ECM.JobRunner.Windows.My.MySettings.Default
End Get
End Property
End Module
End Namespace

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,46 @@
<System.ComponentModel.RunInstaller(True)> Partial Class ProjectInstaller
Inherits System.Configuration.Install.Installer
'Installer überschreibt den Löschvorgang zum Bereinigen der Komponentenliste.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Wird vom Komponenten-Designer benötigt.
Private components As System.ComponentModel.IContainer
'Hinweis: Die folgende Prozedur ist für den Komponenten-Designer erforderlich.
'Das Bearbeiten ist mit dem Komponenten-Designer möglich.
'Das Bearbeiten mit dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller()
Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller()
'
'ServiceProcessInstaller1
'
Me.ServiceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.NetworkService
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
'
'ServiceInstaller1
'
Me.ServiceInstaller1.DisplayName = "Digital Data ECM Job Runner"
Me.ServiceInstaller1.ServiceName = "DDECMJOBRUNNERService"
'
'ProjectInstaller
'
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
Friend WithEvents ServiceProcessInstaller1 As ServiceProcess.ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As ServiceProcess.ServiceInstaller
End Class

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="ServiceProcessInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="ServiceInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>197, 17</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -0,0 +1,16 @@
Imports System.ComponentModel
Imports System.Configuration.Install
Public Class ProjectInstaller
Public Sub New()
MyBase.New()
'Dieser Aufruf ist für den Komponenten-Designer erforderlich.
InitializeComponent()
'Initialisierungscode nach dem Aufruf von InitializeComponent hinzufügen
End Sub
End Class

View File

@@ -0,0 +1,10 @@
Namespace Scheduler
Public Class JobConfig
Public Property Enabled As Boolean = False
Public Property StartWithoutDelay As Boolean = False
Public Property Name As String = "Unnamed Job"
Public Property CronSchedule As String = ""
Public Property Arguments As New Dictionary(Of String, String)
End Class
End Namespace

View File

@@ -0,0 +1,35 @@
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Imports ECM.JobRunner.Common
Namespace Scheduler
Public Class JobHistory
Inherits BaseClass
Public ReadOnly Entries As New List(Of HistoryItem)
Public Sub New(pLogConfig As LogConfig)
MyBase.New(pLogConfig)
End Sub
Public Sub AddSuccess(pName As String, pMessage As String)
Entries.Add(New HistoryItem With {
.CreatedAt = Now,
.JobName = pName,
.Successful = True,
.ErrorMessage = Nothing,
.Message = pMessage
})
End Sub
Public Sub AddError(pName As String, ErrorMessage As String)
Entries.Add(New HistoryItem With {
.CreatedAt = Now,
.JobName = pName,
.Successful = False,
.ErrorMessage = ErrorMessage,
.Message = ""
})
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,40 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports Quartz
Imports Quartz.Listener
Namespace Scheduler
Public Class JobListener
Inherits JobListenerSupport
Public Overrides ReadOnly Property Name As String = "JobListener"
Private ReadOnly Logger As Logger
Private ReadOnly LogConfig As LogConfig
Private ReadOnly History As JobHistory
Public Sub New(pLogConfig As LogConfig, pJobHistory As JobHistory)
MyBase.New()
LogConfig = pLogConfig
Logger = pLogConfig.GetLogger()
History = pJobHistory
End Sub
Public Overrides Function JobWasExecuted(context As IJobExecutionContext, jobException As JobExecutionException, Optional cancellationToken As Threading.CancellationToken = Nothing) As Task
If jobException Is Nothing Then
If TypeOf context.Result Is JobResult Then
Dim oResult As JobResult = context.Result
History.AddSuccess(context.JobDetail.Key.Name, oResult.Description)
Else
History.AddSuccess(context.JobDetail.Key.Name, "Job Successful!")
End If
Else
History.AddError(context.JobDetail.Key.Name, jobException.Message)
End If
Return MyBase.JobWasExecuted(context, jobException, cancellationToken)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,3 @@
Public Class JobResult
Public Property Description As String
End Class

View File

@@ -0,0 +1,147 @@
Imports System.Collections.Specialized
Imports System.Threading
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports Quartz
Imports Quartz.Logging.OperationName
Namespace Scheduler
Public Class JobScheduler
Private ReadOnly Settings As New NameValueCollection From {
{"quartz.serializer.type", "binary"},
{"quartz.threadPool.threadCount", 10}
}
Private ReadOnly LogConfig As LogConfig
Private ReadOnly Logger As Logger
Private ReadOnly Database As MSSQLServer
Private ReadOnly Factory As Quartz.Impl.StdSchedulerFactory
Private ReadOnly State As State
Private Scheduler As IScheduler
Private Const JOB_TYPE_IMPORT As Integer = 1
Private Const JOB_TYPE_INDEX As Integer = 2
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State)
LogConfig = pLogConfig
Logger = pLogConfig.GetLogger()
Factory = New Impl.StdSchedulerFactory(Settings)
Database = pDatabase
State = pState
End Sub
Public Async Function Start() As Task(Of Boolean)
Try
' Log all quartz events into our standard log files
Logging.LogProvider.SetCurrentLogProvider(New LogProvider(LogConfig))
' initialize the scheduler
Scheduler = Await Factory.GetScheduler()
Scheduler.ListenerManager.AddJobListener(New JobListener(LogConfig, State.JobHistory))
' start the scheduler
Await Scheduler.Start()
' load job Config and setup job schedules
Logger.Info("Loading [{0}] Job Definitions..", State.JobDefinitions.Count)
For Each oJob In State.JobDefinitions
Logger.Debug("Loading Job Definition [{0}]", oJob.Name)
Select Case oJob.TypeId
Case JOB_TYPE_IMPORT
Await ScheduleJob(Of Jobs.FileImportJob)(New JobConfig With {
.Name = oJob.Name,
.Enabled = True,
.Arguments = New Dictionary(Of String, String) From {
{"Name", oJob.Name}
},
.CronSchedule = oJob.CronSchedule
})
Case JOB_TYPE_INDEX
Await ScheduleJob(Of Jobs.FileIndexJob)(New JobConfig With {
.Name = oJob.Name,
.Enabled = True,
.Arguments = New Dictionary(Of String, String) From {
{"Name", oJob.Name}
},
.CronSchedule = oJob.CronSchedule
})
End Select
Next
' setup debug job
Await ScheduleJob(Of Jobs.DebugJob)(New JobConfig With {
.Name = "Debug Job",
.Enabled = True,
.Arguments = New Dictionary(Of String, String) From {{"Arg1", "My awesome argument"}},
.CronSchedule = "0 * * * * ?"
})
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Public Async Function Shutdown() As Task
Await Scheduler.Shutdown()
End Function
Public Async Function ScheduleJob(Of T As IJob)(pJobConfig As JobConfig) As Task
Dim oJobName As String = pJobConfig.Name
Dim oTriggerName As String = $"{oJobName}-TRIGGER"
pJobConfig.Name = oJobName
Dim oJobData As New JobDataMap From {
{Constants.Scheduler.JOB_CONFIG_LOGCONFIG, LogConfig},
{Constants.Scheduler.JOB_CONFIG_ARGUMENTS, pJobConfig.Arguments},
{Constants.Scheduler.JOB_CONFIG_DATABASE, Database}
}
Dim oJob = JobBuilder.Create(Of T)().
WithIdentity(oJobName).
UsingJobData(oJobData).
Build()
Dim oTrigger = TriggerBuilder.Create().
WithIdentity(oTriggerName).
StartNow().
WithCronSchedule(pJobConfig.CronSchedule).
Build()
If pJobConfig.Enabled Then
Await Scheduler.ScheduleJob(oJob, oTrigger)
Logger.Info("Job {0} scheduled.", oJobName)
Else
Logger.Info("Job {0} is disabled.", oJobName)
End If
If pJobConfig.StartWithoutDelay Then
Dim oDebugJob = JobBuilder.Create(Of T)().
WithIdentity(oJobName & "-DEBUG").
UsingJobData(oJobData).
Build()
Dim oDebugTrigger = TriggerBuilder.Create().
WithIdentity(oTriggerName & "-DEBUG").
StartAt(DateBuilder.FutureDate(10, IntervalUnit.Second)).
Build()
Logger.Info("Job {0} will start in 10 Seconds.", oJobName)
Await Scheduler.ScheduleJob(oDebugJob, oDebugTrigger)
End If
End Function
End Class
End Namespace

View File

@@ -0,0 +1,21 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports Quartz
Namespace Scheduler.Jobs
Public Class BaseJob
Friend LogConfig As LogConfig
Friend Logger As Logger
Friend Database As MSSQLServer
Public Function InitializeJob(context As IJobExecutionContext) As Dictionary(Of String, String)
Dim oJobData = context.MergedJobDataMap
LogConfig = oJobData.Item(Constants.Scheduler.JOB_CONFIG_LOGCONFIG)
Database = oJobData.Item(Constants.Scheduler.JOB_CONFIG_DATABASE)
Logger = LogConfig.GetLogger()
Return oJobData.Item(Constants.Scheduler.JOB_CONFIG_ARGUMENTS)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,25 @@
Imports DigitalData.Modules.Logging
Imports Quartz
Namespace Scheduler.Jobs
Public Class DebugJob
Inherits BaseJob
Implements IJob
Private Function IJob_Execute(context As IJobExecutionContext) As Task Implements IJob.Execute
Dim oArgs = MyBase.InitializeJob(context)
Dim oArg1 = oArgs.Item("Arg1")
Logger.Info("I'm a debug Job!")
Logger.Info("Arg1: [{0}]", oArg1)
Dim oResult = New JobResult() With {
.Description = $"I'm a debug job and my result was [{Guid.NewGuid}]."
}
context.Result = oResult
Return Task.FromResult(True)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,26 @@
Imports ECM.JobRunner.Windows.Scheduler.Jobs
Imports Quartz
Namespace Scheduler.Jobs
Public Class FileImportJob
Inherits BaseJob
Implements IJob
Public Function Execute(context As IJobExecutionContext) As Task Implements IJob.Execute
Dim oArgs = MyBase.InitializeJob(context)
Dim oName = oArgs.Item("Name")
Logger.Info("Running File Import [{0}]", oName)
Dim oResult = New JobResult() With {
.Description = $"File Import Job [{oName}] completed!"
}
context.Result = oResult
Return Task.FromResult(True)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,24 @@
Imports ECM.JobRunner.Windows.Scheduler.Jobs
Imports Quartz
Namespace Scheduler.Jobs
Public Class FileIndexJob
Inherits BaseJob
Implements IJob
Public Function Execute(context As IJobExecutionContext) As Task Implements IJob.Execute
Dim oArgs = MyBase.InitializeJob(context)
Dim oName = oArgs.Item("Name")
Logger.Info("Running File Index [{0}]", oName)
Dim oResult = New JobResult() With {
.Description = $"File Index Job [{oName}] completed!"
}
context.Result = oResult
Return Task.FromResult(True)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,50 @@
Imports System.ServiceProcess
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Service
Inherits System.ServiceProcess.ServiceBase
'UserService überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
' Der Haupteinstiegspunkt für den Prozess
<MTAThread()>
<System.Diagnostics.DebuggerNonUserCode()>
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
' Innerhalb eines Prozesses können mehrere NT-Dienste ausgeführt werden. Um einen
' weiteren Dienst zu diesem Prozess hinzuzufügen, ändern Sie die folgende Zeile,
' um ein zweites Dienstobjekt zu erstellen. Zum Beispiel
'
' ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
'
ServicesToRun = New System.ServiceProcess.ServiceBase() {New Service}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
'Wird vom Komponenten-Designer benötigt.
Private components As System.ComponentModel.IContainer
' Hinweis: Die folgende Prozedur ist für den Komponenten-Designer erforderlich.
' Das Bearbeiten ist mit dem Komponenten-Designer möglich.
' Das Bearbeiten mit dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
'
'Service
'
Me.ServiceName = "Digital Data ECM Job Runner"
End Sub
End Class

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -0,0 +1,85 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Config
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Messaging.WCF
Public Class Service
Private ReadOnly ServicePath As String = My.Application.Info.DirectoryPath
Private ReadOnly LogPath As String = IO.Path.Combine(ServicePath, "Log")
Private LogConfig As LogConfig
Private Logger As Logger
Private ConfigManager As ConfigManager(Of Config)
Private Config As Config
Private ServiceHost As WCF.ServiceHost(Of WCF.JobRunner)
Private Scheduler As Scheduler.JobScheduler
Private Database As MSSQLServer
Private State As State
Protected Overrides Async Sub OnStart(ByVal args() As String)
' Code zum Starten des Dienstes hier einfügen. Diese Methode sollte Vorgänge
' ausführen, damit der Dienst gestartet werden kann.
Try
' intialize logging
LogConfig = New LogConfig(LogConfig.PathType.CustomPath, LogPath, CompanyName:="Digital Data", ProductName:="ECM Job Runner")
Logger = LogConfig.GetLogger()
Logger.Info("Service [{0}] is starting.", ServiceName)
' initialize config
ConfigManager = New ConfigManager(Of Config)(LogConfig, ServicePath)
Config = ConfigManager.Config
' initialize database
Database = New MSSQLServer(LogConfig, Config.ConnectionString)
' set logging debug flag from config
LogConfig.Debug = Config.Debug
' initialize global state
State = New State(LogConfig, Database)
' start the scheduler
Scheduler = New Scheduler.JobScheduler(LogConfig, Database, State)
If Await Scheduler.Start() Then
Logger.Info("Scheduler started!")
Else
Logger.Warn("Scheduler could not be started!")
End If
' configure job runner
WCF.JobRunner.State = State
WCF.JobRunner.LogConfig = LogConfig
WCF.JobRunner.Database = Database
' start the service
Dim oAddresses() As Uri = {Binding.GetAddress(Config.Host, Config.Port, Config.Name)}
ServiceHost = New WCF.ServiceHost(Of WCF.JobRunner)(oAddresses)
ServiceHost.EnableMetadataExchange(True)
ServiceHost.Open()
Logger.Info("WCF Endpoint started!")
Catch ex As Exception
Logger.Warn("Service [{0}] could not be started!", ServiceName)
Logger.Error(ex)
End Try
End Sub
Protected Overrides Async Sub OnStop()
' Hier Code zum Ausführen erforderlicher Löschvorgänge zum Beenden des Dienstes einfügen.
Try
Logger.Info("Service [{0}] is stopping.", ServiceName)
Await Scheduler.Shutdown()
Catch ex As Exception
Logger.Warn("Service [{0}] could not be stopped!", ServiceName)
Logger.Error(ex)
End Try
End Sub
End Class

View File

@@ -0,0 +1,104 @@
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Language
Imports ECM.JobRunner.Common
Imports ECM.JobRunner.Windows.Scheduler
Imports System.Runtime.InteropServices
Public Class State
Inherits BaseClass
Private ReadOnly Database As MSSQLServer
Public ReadOnly JobHistory As JobHistory
Public ReadOnly Property JobTypes As New List(Of JobType)
Public ReadOnly Property JobDefinitions As New List(Of JobDefinition)
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer)
MyBase.New(pLogConfig)
Database = pDatabase
JobHistory = New JobHistory(pLogConfig)
_JobTypes = GetJobTypes()
_JobDefinitions = GetJobDefinitions(_JobTypes)
End Sub
Public Sub Reload()
_JobTypes = GetJobTypes()
_JobDefinitions = GetJobDefinitions(_JobTypes)
End Sub
Private Function GetJobTypes() As List(Of JobType)
Dim oTypes As New List(Of JobType)
Try
Logger.Info("Loading Job Types..")
Dim oSQL As String = "SELECT * FROM TBECM_JR_TYPE WHERE ACTIVE = 1"
Dim oTable As DataTable = Database.GetDatatable(oSQL)
If oTable Is Nothing Then
Logger.Warn("Database Error while loading Job Types!")
Return oTypes
End If
Logger.Info("[{0}] Job Types loaded!", oTable.Rows.Count)
For Each oRow As DataRow In oTable.Rows
Dim oType As New JobType With {
.Id = oRow.ItemEx("GUID", 0),
.Name = oRow.ItemEx("JOB_TYPE", ""),
.Active = oRow.ItemEx("ACTIVE", 0)
}
oTypes.Add(oType)
Logger.Debug("Adding Job Type [{0}]", oType.Name)
Next
Return oTypes
Catch ex As Exception
Logger.Error(ex)
Return oTypes
End Try
End Function
Private Function GetJobDefinitions(pJobTypes As List(Of JobType)) As List(Of JobDefinition)
Dim oJobs As New List(Of JobDefinition)
Try
Dim oSQL As String = "SELECT * FROM TBECM_JR_JOB"
Dim oTable As DataTable = Database.GetDatatable(oSQL)
If oTable Is Nothing Then
Logger.Warn("Database Error while loading Jobs!")
Return oJobs
End If
Logger.Info("[{0}] Jobs loaded!", oTable.Rows.Count)
For Each oRow As DataRow In oTable.Rows
Dim oTypeId = oRow.ItemEx("JOB_TYPE_ID", 0)
Dim oJob As New JobDefinition With {
.Id = oRow.ItemEx("GUID", 0),
.TypeId = oTypeId,
.Type = pJobTypes.Where(Function(t) t.Id = oTypeId).SingleOrDefault,
.Name = oRow.ItemEx("TITLE", ""),
.Active = oRow.ItemEx("ACTIVE", 0),
.CronSchedule = oRow.ItemEx("QUARTZ_DEF", "")
}
oJobs.Add(oJob)
Logger.Debug("Adding Job [{0}]", oJob.Name)
Next
Return oJobs
Catch ex As Exception
Logger.Error(ex)
Return oJobs
End Try
End Function
End Class

View File

@@ -0,0 +1,18 @@
Imports System.ServiceModel
Imports ECM.JobRunner.Common
Namespace WCF
<ServiceContract(Name:="IEDMIService", [Namespace]:="http://DigitalData.Services.EDMIService")>
Public Interface IJobRunner
<OperationContract>
Function GetHeartbeat() As Date
<OperationContract>
Function GetJobHistory() As GetJobHistory.GetJobHistoryResponse
<OperationContract>
Function GetJobConfig() As GetJobConfig.GetJobConfigResponse
End Interface
End Namespace

View File

@@ -0,0 +1,49 @@
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Messaging.WCF
Imports ECM.JobRunner.Common
Namespace WCF
Public Class JobRunner
Implements IJobRunner
Public Shared State As State
Public Shared LogConfig As LogConfig
Public Shared Database As MSSQLServer
''' <summary>
''' See: https://stackoverflow.com/questions/42327988/addserviceendpoint-throws-key-is-null
''' </summary>
''' <param name="Config"></param>
Public Shared Sub Configure(Config As ServiceConfiguration)
Dim oBaseAddress = Config.BaseAddresses.Item(0)
Dim oBinding = Binding.GetBinding()
Dim oAddress = New EndpointAddress(oBaseAddress)
Dim oDescription = ContractDescription.GetContract(GetType(IJobRunner), GetType(JobRunner))
Dim oEndpoint As New ServiceEndpoint(oDescription, oBinding, oAddress)
Config.AddServiceEndpoint(oEndpoint)
Config.Description.Behaviors.Add(New ServiceDebugBehavior With {
.IncludeExceptionDetailInFaults = True
})
End Sub
Public Function GetHeartbeat() As Date Implements IJobRunner.GetHeartbeat
Return Now
End Function
Public Function GetJobHistory() As GetJobHistory.GetJobHistoryResponse Implements IJobRunner.GetJobHistory
Dim oMethod As New GetJobHistory.GetJobHistoryMethod(LogConfig, Database, State)
Return oMethod.Run()
End Function
Public Function GetJobConfig() As GetJobConfig.GetJobConfigResponse Implements IJobRunner.GetJobConfig
Dim oMethod As New GetJobConfig.GetJobConfigMethod(LogConfig, Database, State)
Return oMethod.Run()
End Function
End Class
End Namespace

View File

@@ -0,0 +1,48 @@
Imports System.Runtime.Serialization
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Public Class Base
Public Class BaseMethod
Inherits BaseClass
Friend ReadOnly Database As MSSQLServer
Friend ReadOnly State As State
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State)
MyBase.New(pLogConfig)
Database = pDatabase
State = pState
End Sub
End Class
Public MustInherit Class BaseResponse
<DataMember>
Public Property OK As Boolean
<DataMember>
Public Property ErrorMessage As String
<DataMember>
Public Property ErrorDetails As String
Public Sub New()
OK = True
End Sub
Public Sub New(Message As String)
OK = False
ErrorMessage = Message
End Sub
Public Sub New(Exception As Exception)
OK = False
ErrorMessage = Exception.Message
End Sub
Public Sub New(Exception As Exception, Details As String)
OK = False
ErrorMessage = Exception.Message
ErrorDetails = Details
End Sub
End Class
End Class

View File

@@ -0,0 +1,36 @@
Imports System.Runtime.Serialization
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Language
Imports ECM.JobRunner.Common
Public Class GetJobConfig
Public Class GetJobConfigMethod
Inherits Base.BaseMethod
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State)
MyBase.New(pLogConfig, pDatabase, pState)
End Sub
Public Function Run() As GetJobConfigResponse
Return New GetJobConfigResponse With {
.JobTypes = State.JobTypes,
.JobDefinitions = State.JobDefinitions
}
End Function
End Class
Public Class GetJobConfigResponse
Inherits Base.BaseResponse
<DataMember>
Public Property JobTypes As List(Of JobType)
<DataMember>
Public Property JobDefinitions As List(Of JobDefinition)
End Class
End Class

View File

@@ -0,0 +1,25 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports ECM.JobRunner.Common
Imports System.Runtime.Serialization
Public Class GetJobHistory
Public Class GetJobHistoryMethod
Inherits Base.BaseMethod
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State)
MyBase.New(pLogConfig, pDatabase, pState)
End Sub
Public Function Run() As GetJobHistoryResponse
Return New GetJobHistoryResponse With {.Items = State.JobHistory.Entries}
End Function
End Class
Public Class GetJobHistoryResponse
Inherits Base.BaseResponse
<DataMember>
Public Property Items As List(Of HistoryItem)
End Class
End Class

View File

@@ -0,0 +1,73 @@
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Description
Namespace WCF
Public Class ServiceHost(Of T)
Inherits ServiceHost
Public Sub New(baseAddresses As Uri())
MyBase.New(GetType(T), baseAddresses)
End Sub
Public Sub New(singletonInstance As Object, baseAddresses As Uri())
MyBase.New(singletonInstance, baseAddresses)
End Sub
Public Sub EnableMetadataExchange(ByVal Optional EnableHttpGet As Boolean = True)
If State = CommunicationState.Opened Then
Throw New InvalidOperationException("Host is already opened")
End If
Dim oMetadataBehavior As ServiceMetadataBehavior = Description.Behaviors.Find(Of ServiceMetadataBehavior)()
If oMetadataBehavior Is Nothing Then
oMetadataBehavior = New ServiceMetadataBehavior()
Description.Behaviors.Add(oMetadataBehavior)
If BaseAddresses.Any(Function(uri) uri.Scheme = "http") Then
oMetadataBehavior.HttpGetEnabled = EnableHttpGet
Else
oMetadataBehavior.HttpGetEnabled = False
End If
End If
AddAllMexEndPoints()
End Sub
Public ReadOnly Property HasMexEndpoint As Boolean
Get
Return Description.Endpoints.Any(Function(endpoint) endpoint.Contract.ContractType = GetType(IMetadataExchange))
End Get
End Property
Public Sub AddAllMexEndPoints()
Debug.Assert(HasMexEndpoint = False)
For Each baseAddress As Uri In BaseAddresses
Dim oBinding As Binding = Nothing
Select Case baseAddress.Scheme
Case "net.tcp"
oBinding = MetadataExchangeBindings.CreateMexTcpBinding()
Exit Select
Case "net.pipe"
oBinding = MetadataExchangeBindings.CreateMexNamedPipeBinding()
Exit Select
Case "http"
oBinding = MetadataExchangeBindings.CreateMexHttpBinding()
Exit Select
Case "https"
oBinding = MetadataExchangeBindings.CreateMexHttpsBinding()
Exit Select
End Select
If oBinding IsNot Nothing Then
AddServiceEndpoint(GetType(IMetadataExchange), oBinding, "mex")
End If
Next
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net462" />
<package id="NLog" version="5.1.0" targetFramework="net462" />
<package id="Quartz" version="3.5.0" targetFramework="net462" />
<package id="System.ServiceModel.NetTcp" version="4.10.0" targetFramework="net462" />
<package id="System.ServiceModel.Primitives" version="4.10.0" targetFramework="net462" />
</packages>

View File

@@ -0,0 +1 @@
Backup created at 1669814881 (30.11.2022 13:28:01 +00:00)