From 6c6e4acf33492d3e24e5d1aeabd9c91d19c5a48d Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Tue, 19 May 2020 17:56:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TopshelfStudy.NetCoreDemo/App.config | 14 + TopshelfStudy.NetCoreDemo/NLog.xsd | 3538 +++++++++++++++++ TopshelfStudy.NetCoreDemo/Program.cs | 42 + .../QuartzNet/CustomJobListener.cs | 53 + .../QuartzNet/CustomSchedulerListener.cs | 193 + .../QuartzNet/CustomTriggerListener.cs | 72 + .../QuartzNet/JobDemo.cs | 23 + .../QuartzNet/QuartzNetExtensions.cs | 70 + .../QuartzNet/QuartzNetHelper.cs | 24 + TopshelfStudy.NetCoreDemo/ReadMe.txt | 4 + .../Service/TopshelfService.cs | 62 + .../TopshelfStudy.NetCoreDemo.csproj | 30 + .../Utils/RuntimeUtil.cs | 25 + TopshelfStudy.NetCoreDemo/nlog.config | 57 + TopshelfStudy.NetCoreDemo/quartz.config | 34 + TopshelfStudy.sln | 25 + 16 files changed, 4266 insertions(+) create mode 100644 TopshelfStudy.NetCoreDemo/App.config create mode 100644 TopshelfStudy.NetCoreDemo/NLog.xsd create mode 100644 TopshelfStudy.NetCoreDemo/Program.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/CustomJobListener.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/CustomSchedulerListener.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/CustomTriggerListener.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/JobDemo.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetExtensions.cs create mode 100644 TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetHelper.cs create mode 100644 TopshelfStudy.NetCoreDemo/ReadMe.txt create mode 100644 TopshelfStudy.NetCoreDemo/Service/TopshelfService.cs create mode 100644 TopshelfStudy.NetCoreDemo/TopshelfStudy.NetCoreDemo.csproj create mode 100644 TopshelfStudy.NetCoreDemo/Utils/RuntimeUtil.cs create mode 100644 TopshelfStudy.NetCoreDemo/nlog.config create mode 100644 TopshelfStudy.NetCoreDemo/quartz.config create mode 100644 TopshelfStudy.sln diff --git a/TopshelfStudy.NetCoreDemo/App.config b/TopshelfStudy.NetCoreDemo/App.config new file mode 100644 index 0000000..ad31865 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/App.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TopshelfStudy.NetCoreDemo/NLog.xsd b/TopshelfStudy.NetCoreDemo/NLog.xsd new file mode 100644 index 0000000..05684bd --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/NLog.xsd @@ -0,0 +1,3538 @@ + + + + + + + + + + + + + + + Watch config file for changes and reload automatically. + + + + + Print internal NLog messages to the console. Default value is: false + + + + + Print internal NLog messages to the console error output. Default value is: false + + + + + Write internal NLog messages to the specified file. + + + + + Log level threshold for internal log messages. Default value is: Info. + + + + + Global log level threshold for application log messages. Messages below this level won't be logged. + + + + + Throw an exception when there is an internal error. Default value is: false. Not recommend to set to true in production! + + + + + Throw an exception when there is a configuration error. If not set, determined by throwExceptions. + + + + + Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false. + + + + + Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false. + + + + + Write timestamps for internal NLog messages. Default value is: true. + + + + + Use InvariantCulture as default culture instead of CurrentCulture. Default value is: false. + + + + + Perform message template parsing and formatting of LogEvent messages (true = Always, false = Never, empty = Auto Detect). Default value is: empty. + + + + + + + + + + + + + + Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes). + + + + + + + + + + + + + + + + + Prefix for targets/layout renderers/filters/conditions loaded from this assembly. + + + + + Load NLog extensions from the specified file (*.dll) + + + + + Load NLog extensions from the specified assembly. Assembly name should be fully qualified. + + + + + + + + + + Name of the logger. May include wildcard characters ('*' or '?'). + + + + + Comma separated list of levels that this rule matches. + + + + + Minimum level that this rule matches. + + + + + Maximum level that this rule matches. + + + + + Level that this rule matches. + + + + + Comma separated list of target names. + + + + + Ignore further rules if this one matches. + + + + + Rule identifier to allow rule lookup with Configuration.FindRuleByName and Configuration.RemoveRuleByName. + + + + + + + + + + + + + + + Default action if none of the filters match. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file. + + + + + Ignore any errors in the include file. + + + + + + + + Variable value. Note, the 'value' attribute has precedence over this one. + + + + + + Variable name. + + + + + Variable value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events that should be processed in a batch by the lazy writer thread. + + + + + Whether to use the locking queue, instead of a lock-free concurrent queue The locking queue is less concurrent when many logger threads, but reduces memory allocation + + + + + Limit of full s to write before yielding into Performance is better when writing many small batches, than writing a single large batch + + + + + Action to be taken when the lazy writer thread request queue count exceeds the set limit. + + + + + Limit on the number of requests in the lazy writer thread request queue. + + + + + Time in milliseconds to sleep between batches. (1 or less means trigger on new activity) + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + Delay the flush until the LogEvent has been confirmed as written + + + + + Condition expression. Log events who meet this condition will cause a flush on the wrapped target. + + + + + Name of the target. + + + + + Only flush when LogEvent matches condition. Ignore explicit-flush, config-reload-flush and shutdown-flush + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events to be buffered. + + + + + Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes. + + + + + Action to take if the buffer overflows. + + + + + Indicates whether to use sliding timeout. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + Maximum queue size. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + NDLC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Renderer for log4j:event logger-xml-attribute (Default ${logger}) + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Viewer parameter name. + + + + + Whether an attribute with empty value should be included in the output + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + Enables output using ANSI Color Codes + + + + + The encoding for writing messages to the . + + + + + Indicates whether the error stream (stderr) should be used instead of the output stream (stdout). + + + + + Indicates whether to auto-check if the console has been redirected to file - Disables coloring logic when System.Console.IsOutputRedirected = true + + + + + Indicates whether to use default row highlighting rules. + + + + + Indicates whether to auto-flush after + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Condition that must be met in order to set the specified foreground and background color. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used. + + + + + Indicates whether to ignore case when comparing texts. + + + + + Regular expression to be matched. You must specify either text or regex. + + + + + Text to be matched. You must specify either text or regex. + + + + + Indicates whether to match whole words only. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Indicates whether to send the log messages to the standard error instead of the standard output. + + + + + Indicates whether to auto-flush after + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. + + + + + Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string. + + + + + Name of the database provider. + + + + + Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string. + + + + + Indicates whether to keep the database connection open between the log events. + + + + + Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string. + + + + + Name of the connection string (as specified in <connectionStrings> configuration section. + + + + + Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase. + + + + + Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string. + + + + + Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Text of the SQL command to be run on each log level. + + + + + Type of the SQL command to be run on each log level. + + + + + + + + + + + + + + + + + + + + + + + Type of the command. + + + + + Connection string to run the command against. If not provided, connection string from the target is used. + + + + + Indicates whether to ignore failures. + + + + + Command text. + + + + + + + + + + + + + + + + + + Database parameter name. + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Database parameter DbType. + + + + + Database parameter size. + + + + + Database parameter precision. + + + + + Database parameter scale. + + + + + Type of the parameter. + + + + + Convert format of the database parameter value . + + + + + Culture used for parsing parameter string-value for type-conversion + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Layout that renders event Category. + + + + + Optional entrytype. When not set, or when not convertible to then determined by + + + + + Layout that renders event ID. + + + + + Name of the Event Log to write to. This can be System, Application or any user-defined name. + + + + + Name of the machine on which Event Log service is running. + + + + + Maximum Event log size in kilobytes. + + + + + Message length limit to write to the Event Log. + + + + + Value to be used as the event Source. + + + + + Action to take if the message is larger than the option. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether to return to the first target after any successful write. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + File encoding. + + + + + Line ending mode. + + + + + Indicates whether to compress archive files into the zip archive format. + + + + + Way file archives are numbered. + + + + + Name of the file to be used for an archive. + + + + + Is the an absolute or relative path? + + + + + Indicates whether to automatically archive log files every time the specified time passes. + + + + + Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: + + + + + Maximum number of archive files that should be kept. + + + + + Indicates whether the footer should be written only when the file is archived. + + + + + Maximum number of log filenames that should be stored as existing. + + + + + Is the an absolute or relative path? + + + + + Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation. + + + + + Indicates whether file creation calls should be synchronized by a system global mutex. + + + + + Indicates whether to replace file contents on each write instead of appending log message at the end. + + + + + Indicates whether to write BOM (byte order mark) in created files + + + + + Indicates whether to enable log file(s) to be deleted. + + + + + Name of the file to write to. + + + + + Value specifying the date format to use when archiving files. + + + + + Indicates whether to archive old log file on startup. + + + + + Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. + + + + + Indicates whether to create directories if they do not exist. + + + + + Indicates whether to delete old log file on startup. + + + + + File attributes (Windows only). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Indicates whether concurrent writes to the log file by multiple processes on different network hosts. + + + + + Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. + + + + + Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). + + + + + Indicates whether to keep log file open instead of opening and closing it on each logging event. + + + + + Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write + + + + + Indicates whether concurrent writes to the log file by multiple processes on the same host. + + + + + Number of times the write is appended on the file before NLog discards the log message. + + + + + Delay in milliseconds to wait before attempting to write to the file again. + + + + + Log file buffer size in bytes. + + + + + Maximum number of seconds before open files are flushed. If this number is negative or zero the files are not flushed by timer. + + + + + Indicates whether to automatically flush the file buffers after each log message. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will be forwarded to the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Windows domain name to change context to. + + + + + Required impersonation level. + + + + + Type of the logon provider. + + + + + Logon Type. + + + + + User account password. + + + + + Indicates whether to revert to the credentials of the process instead of impersonating another user. + + + + + Username to change context to. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Interval in which messages will be written up to the number of messages. + + + + + Maximum allowed number of messages written per . + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Endpoint address. + + + + + Name of the endpoint configuration in WCF configuration file. + + + + + Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply) + + + + + Client ID. + + + + + Indicates whether to include per-event properties in the payload sent to the server. + + + + + Indicates whether to use binary message encoding. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Name of the parameter. + + + + + Type of the parameter. + + + + + Type of the parameter. Obsolete alias for + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether NewLine characters in the body should be replaced with tags. + + + + + Priority used for sending mails. + + + + + Encoding to be used for sending e-mail. + + + + + BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Indicates whether to add new lines between log entries. + + + + + Indicates whether to send message as HTML instead of plain text. + + + + + Sender's email address (e.g. joe@domain.com). + + + + + Mail message body (repeated for each log message send in one mail). + + + + + Mail subject. + + + + + Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Indicates the SMTP client timeout. + + + + + SMTP Server to be used for sending. + + + + + SMTP Authentication mode. + + + + + Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server. + + + + + Port number that SMTP Server is listening on. + + + + + Indicates whether the default Settings from System.Net.MailSettings should be used. + + + + + Folder where applications save mail messages to be processed by the local SMTP server. + + + + + Specifies how outgoing email messages will be handled. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Max number of items to have in memory + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Class name. + + + + + Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Maximum queue size. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + Maximum queue size. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + NDLC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Renderer for log4j:event logger-xml-attribute (Default ${logger}) + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to perform layout calculation. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether performance counter should be automatically created. + + + + + Name of the performance counter category. + + + + + Counter help text. + + + + + Name of the performance counter. + + + + + Performance counter type. + + + + + The value by which to increment the counter. + + + + + Performance counter instance name. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Default filter to be applied when no specific rule matches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + Condition to be tested. + + + + + Resulting filter to be applied when the condition matches. + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of times to repeat each log message. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of retries that should be attempted on the wrapped target in case of a failure. + + + + + Time to wait between retries in milliseconds. + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Always use independent of + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Should we include the BOM (Byte-order-mark) for UTF? Influences the property. This will only work for UTF-8. + + + + + Web service method name. Only used with Soap. + + + + + Web service namespace. Only used with Soap. + + + + + Protocol to be used when calling web service. + + + + + Custom proxy address, include port separated by a colon + + + + + Encoding. + + + + + Web service URL. + + + + + Value whether escaping be done according to the old NLog style (Very non-standard) + + + + + Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs) + + + + + Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in parameters) + + + + + Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see and ). + + + + + (optional) root namespace of the XML document, if POST of XML document chosen. (see and ). + + + + + Proxy configuration when calling web service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom'). + + + + + Column delimiter. + + + + + Quote Character. + + + + + Quoting mode. + + + + + Indicates whether CVS should include header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout of the column. + + + + + Name of the column. + + + + + Override of Quoting mode + + + + + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as JSON) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the JSON serializer follow object references before backing off + + + + + Option to render the empty object value {} + + + + + Option to suppress the extra spaces in the output json + + + + + + + + + + + + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + Determines whether or not this attribute will be Json encoded. + + + + + Indicates whether to escape non-ascii characters + + + + + Whether an attribute with empty value should be included in the output + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + + + + + + + + + + + + + + + + + Option to include all properties from the log events + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + + + + + + + + + + Layout text. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as XML) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the XML serializer follow object references before backing off + + + + + XML element name to use for rendering IList-collections items + + + + + XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included + + + + + XML element name to use when rendering properties + + + + + XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value + + + + + Name of the root XML element + + + + + Value inside the root XML element + + + + + Whether a ElementValue with empty value should be included in the output + + + + + Auto indent and create new lines + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + + + + + + + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + Whether an attribute with empty value should be included in the output + + + + + + + + + + + + + + + + + + + + + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + Name of the element + + + + + Value inside the element + + + + + Whether a ElementValue with empty value should be included in the output + + + + + Auto indent and create new lines + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as XML) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the XML serializer follow object references before backing off + + + + + XML element name to use for rendering IList-collections items + + + + + XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included + + + + + XML element name to use when rendering properties + + + + + XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Condition expression. + + + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Default number of unique filter values to expect, will automatically increase if needed + + + + + Applies the configured action to the initial logevent that starts the timeout period. Used to configure that it should ignore all events until timeout. + + + + + Layout to be used to filter log messages. + + + + + Max number of unique filter values to expect simultaneously + + + + + Max length of filter values, will truncate if above limit + + + + + How long before a filter expires, and logging is accepted again + + + + + Default buffer size for the internal buffers + + + + + Reuse internal buffers, and doesn't have to constantly allocate new buffers + + + + + Append FilterCount to the when an event is no longer filtered + + + + + Insert FilterCount value into when an event is no longer filtered + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TopshelfStudy.NetCoreDemo/Program.cs b/TopshelfStudy.NetCoreDemo/Program.cs new file mode 100644 index 0000000..9606b1b --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/Program.cs @@ -0,0 +1,42 @@ +using System; +using Topshelf; + +using System.Security.Cryptography.X509Certificates; + +namespace TopshelfStudy.NetCoreDemo +{ + class Program + { + static void Main(string[] args) + { + var topshelfExitCode = HostFactory.Run(config => + { + //使用NLog日志 + config.UseNLog(NLog.LogManager.LogFactory); + + //服务配置 + config.Service(s => + { + s.ConstructUsing(name => new TopshelfService()); + s.WhenStarted(tc => tc.Start()); + s.WhenStopped(tc => tc.Stop()); + }); + + //运行服务帐户 + config.RunAsLocalSystem(); + + //服务名(所有服务中唯一) + config.SetServiceName("AIoT.Service.Demo"); + + //服务显示名 + config.SetDisplayName("AIoT服务测试"); + + //服务描述 + config.SetDescription("这是一个AIoT服务测试例子,使用Topshelf类库方便调试!"); + }); + + //退出码 + Environment.ExitCode = (int)Convert.ChangeType(topshelfExitCode, topshelfExitCode.GetTypeCode()); + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/CustomJobListener.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomJobListener.cs new file mode 100644 index 0000000..bab9376 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomJobListener.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Quartz; +using Quartz.Listener; + +namespace TopshelfStudy.NetCoreDemo +{ + /// + /// Quartz作业监听器 + /// + public class CustomJobListener : IJobListener + { + public readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + public virtual string Name => nameof(CustomJobListener); + + public CustomJobListener() + { + } + + /// + /// 执行前 + /// + public Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) + { + logger.Info("作业,执行前!"); + return Task.CompletedTask; + } + + /// + /// 执行后 + /// + public Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken)) + { + logger.Info($"作业{context.JobDetail.Key.Name},执行后!"); + return Task.CompletedTask; + } + + /// + /// 被否决执行 + /// + public Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) + { + logger.Info("作业,被否决执行!"); + + return Task.CompletedTask; + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/CustomSchedulerListener.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomSchedulerListener.cs new file mode 100644 index 0000000..ae8520f --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomSchedulerListener.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Threading; + +using Quartz; +using Quartz.Core; +using Quartz.Listener; +using Quartz.Impl; +using Quartz.Impl.Matchers; + + +namespace TopshelfStudy.NetCoreDemo +{ + /// + /// Quarzt调度监听器 + /// + public class CustomSchedulerListener : ISchedulerListener + { + private IScheduler _scheduler; + + public CustomSchedulerListener(IScheduler scheduler) + { + _scheduler = scheduler; + } + + public Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{jobDetail.Key} 作业:被添加,成功启用"); + return Task.CompletedTask; + } + + /// + /// 作业被删除 + /// 删除前一次,删除后一次 + /// + public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) + { + if (_scheduler.CheckExists(jobKey).Result) + { + Console.WriteLine($"{jobKey} 作业:即将删除"); + } + else + { + Console.WriteLine($"{jobKey} 作业:完成删除"); + } + + return Task.CompletedTask; + } + + /// + /// 作业被中断 + /// + public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{jobKey} 作业:被中断"); + + return Task.CompletedTask; + } + + /// + /// 作业被暂停 + /// + public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{jobKey} 作业:被暂停"); + + return Task.CompletedTask; + } + + /// + /// 作业被继续(取消暂停) + /// + public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{jobKey} 作业:被继续"); + + return Task.CompletedTask; + } + + /// + /// 作业被添加到Scheduler + /// + public Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{trigger.Key} 触发器:添加到 调度器"); + return Task.CompletedTask; + } + + /// + /// 当一组Quartz.IJobDetails被暂停时由Quartz.IScheduler调用。 + /// 如果所有组都已暂停,则jobName参数将为空。 + /// 如果所有作业都已暂停,则两个参数都将为空。 + /// + /// + /// + /// + public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default(CancellationToken)) + { + var jobKeys = _scheduler.GetJobKeys(GroupMatcher.GroupEquals(jobGroup)).Result; + foreach (var jobKey in jobKeys) + { + + } + Console.WriteLine($"{jobGroup} 作业组:被暂停"); + + return Task.CompletedTask; + } + + public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default(CancellationToken)) + { + var jobKeys = _scheduler.GetJobKeys(GroupMatcher.GroupEquals(jobGroup)).Result; + Console.WriteLine($"{jobGroup} 作业组:被继续"); + return Task.CompletedTask; + } + + /// + /// 作业从Scheduler中删除 + /// + public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{triggerKey.Name} 触发器:Unscheduled"); + return Task.CompletedTask; + } + + public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"Scheduler出现错误:{msg}"); + return Task.CompletedTask; + } + + public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task SchedulerShutdown(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task SchedulerShuttingdown(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task SchedulerStarted(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task SchedulerStarting(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task SchedulingDataCleared(CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.CompletedTask; + } + + public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{trigger.Key.Name}:TriggerFinalized"); + return Task.CompletedTask; + } + + public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{triggerKey.Name}:TriggerPaused"); + return Task.CompletedTask; + } + + public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{triggerKey.Name}:TriggerResumed"); + return Task.CompletedTask; + } + + public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{triggerGroup}:TriggersPaused"); + return Task.CompletedTask; + } + + public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine($"{triggerGroup}:TriggersResumed"); + return Task.CompletedTask; + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/CustomTriggerListener.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomTriggerListener.cs new file mode 100644 index 0000000..78087c6 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/CustomTriggerListener.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Quartz; +using Quartz.Core; +using Quartz.Impl; +using Quartz.Listener; + +namespace TopshelfStudy.NetCoreDemo +{ + /// + /// Quarzt触发监听器 + /// + public class CustomTriggerListener : ITriggerListener + { + public string Name { get; } = nameof(CustomTriggerListener); + + public CustomTriggerListener() + { + } + + /// + /// 在Quartz.ITrigger触发时由Quartz.IScheduler调用 + /// 它的关联Quartz.IJobDetail已执行 + /// 它的Quartz.Spi.IOperableTrigger.trigged(Quartz.ICalendar)方法已调用 + /// + public Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine("触发器执行后"); + return Task.CompletedTask; + } + + /// + /// 触发器启动时执行 + /// 当Quartz.ITrigger启动时由Quartz.IScheduler调用,它的关联Quartz.IJobDetail即将执行。 + /// 它在VetoJobExecution()方法之前调用 + /// + public Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine("触发器执行前"); + return Task.CompletedTask; + } + + /// + /// 错过触发时调用 + /// 当Quartz.ITrigger错过触发时(线程池不够且等待超时)调用时,由Quartz.IScheduler调用。 + /// 应该考虑这个方法花费了多少时间,因为将影响所有错过触发的触发器。 + /// 如果你有很多的触发器错过触发,这可能是这个方法做了很多事情。 + /// + public Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine("错过触发时间,本次任务丢失."); + return Task.CompletedTask; + } + + /// + /// 在Quartz.ITrigger触发时由Quartz.IScheduler调用 + /// 它的关联Quartz.IJobDetail已执行,它的Quartz.Spi.IOperableTrigger.trigged(Quartz.ICalendar)方法已调用 + /// + /// + /// true表示否决Job继续执行,false同意继续执行 + /// + public Task VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken)) + { + Console.WriteLine("触发器审核通过,继续执行."); + return Task.FromResult(false); + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/JobDemo.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/JobDemo.cs new file mode 100644 index 0000000..9a4c51a --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/JobDemo.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using Quartz; +using Quartz.Core; + +namespace TopshelfStudy.NetCoreDemo +{ + public class JobDemo : IJob + { + public async Task Execute(IJobExecutionContext context) + { + //模拟业务操作 + string jobName = "测试作业"; + Console.WriteLine($"{jobName} 开始执行"); + Console.WriteLine($"{jobName} 执行中..."); + await Task.Delay(0*1000); + Console.WriteLine($"{jobName} 执行完毕."); + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetExtensions.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetExtensions.cs new file mode 100644 index 0000000..b8e4842 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetExtensions.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +using Quartz; +using Quartz.Core; +using Quartz.Impl; + +namespace TopshelfStudy.NetCoreDemo +{ + public static class QuartzNetExtensions + { + public static IServiceCollection AddCustomQuartz(this IServiceCollection services) + { + var config = services.BuildServiceProvider().GetRequiredService(); + + //配置 + var option = new NameValueCollection + { + //实例名 + ["quartz.scheduler.instanceName"] = "MissionQuartzScheduler", + //线程数 + ["quartz.threadPool.threadCount"] = "10", + //线程超时 + ["quartz.jobStore.misfireThreshold"] = "60000", + //Job数据可以使用序列化数据,而非只能使用字符串 + ["quartz.serializer.type"] = "json", + + //配置以使用作业StoreTx + ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz", + //将 AdoJobStore 配置为使用驱动程序委托 + ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz", + //使用表前缀配置 AdoJobStore + ["quartz.jobStore.tablePrefix"] = "QRTZ_", + //使用“要使用的数据源名称”配置 AdoJobStore + ["quartz.jobStore.dataSource"] = "quarztDS", + //设置数据源的连接字符串 + ["quartz.dataSource.quarztDS.connectionString"] = config.GetConnectionString("SolutionConnection"), + //设置数据库提供程序 + ["quartz.dataSource.quarztDS.provider"] = "MySql", + //将 AdoJobStore 配置为将字符串用作作业数据映射值(建议) + ["quartz.jobStore.useProperties"] = "false", + + // 负载均衡 + ["quartz.jobStore.clustered"] = "true", + ["quartz.scheduler.instanceId"] = "AUTO", + }; + + //使用quartz.config配置文件 + var factory = new StdSchedulerFactory(); + + //或者:使用程序配置项 + //var factory = new StdSchedulerFactory(option); + var scheduler = factory.GetScheduler().Result; + + services.AddSingleton(factory); + services.AddSingleton(scheduler); + + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + return services; + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetHelper.cs b/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetHelper.cs new file mode 100644 index 0000000..29d65c2 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/QuartzNet/QuartzNetHelper.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +using Quartz; + +namespace TopshelfStudy.NetCoreDemo +{ + public static class QuartzNetHelper + { + /// + /// 是否是有效的 cron 字符串 + /// + public static bool IsValidExpression(string cron) + { + return CronExpression.IsValidExpression(cron); + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/ReadMe.txt b/TopshelfStudy.NetCoreDemo/ReadMe.txt new file mode 100644 index 0000000..5318896 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/ReadMe.txt @@ -0,0 +1,4 @@ +EF Core 模型生成器 + +Scaffold-DbContext -Connection "server=47.102.46.73;port=3306;user=root;password=213464;database=wi_cloud" -Provider "MySql.Data.EntityFrameworkCore" -Context "CloudContext" -OutputDir "Models" -force +Scaffold-DbContext -Connection "server=47.103.96.35;port=3306;user=root;password=213464;database=wi_cloud" -Provider "MySql.Data.EntityFrameworkCore" -Context "CloudContext" -OutputDir "Models" -force \ No newline at end of file diff --git a/TopshelfStudy.NetCoreDemo/Service/TopshelfService.cs b/TopshelfStudy.NetCoreDemo/Service/TopshelfService.cs new file mode 100644 index 0000000..7fdb66b --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/Service/TopshelfService.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.Logging; +using Quartz; +using Quartz.Impl; +using Quartz.Impl.Matchers; + +namespace TopshelfStudy.NetCoreDemo +{ + public class TopshelfService + { + public readonly IScheduler Scheduler = new StdSchedulerFactory().GetScheduler().Result; + + public readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + public void Start() + { + logger.Info("服务启动"); + + //注册监听器 + Scheduler.ListenerManager.AddSchedulerListener(new CustomSchedulerListener(Scheduler)); + Scheduler.ListenerManager.AddJobListener(new CustomJobListener(), GroupMatcher.AnyGroup()); + Scheduler.ListenerManager.AddTriggerListener(new CustomTriggerListener()); + + //添加作业 + JobKey jobKey = new JobKey("demo_job", "demo_job_group"); + TriggerKey triggerKey = new TriggerKey("demo_trigger", "demo_trigger_group"); + JobDataMap dataMape = new JobDataMap(); + + IJobDetail jobDetail = JobBuilder.Create() + .SetJobData(dataMape) + .WithIdentity(jobKey) + .Build(); + + //触发器 + ITrigger trigger = TriggerBuilder.Create() + .WithIdentity(triggerKey) + .StartNow() + .WithCronSchedule("0/10 * * * * ? ") + .Build(); + + //添加到调度器 + Scheduler.ScheduleJob(jobDetail, trigger); + + //启动Scheduler + Scheduler.Start(); + } + + public void Stop() + { + if (Scheduler != null && !Scheduler.IsShutdown) + { + Scheduler.Shutdown(); + } + + logger.Info("Quarzt.Net 后台服务已关闭"); + + logger.Info("Windows 服务停止"); + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/TopshelfStudy.NetCoreDemo.csproj b/TopshelfStudy.NetCoreDemo/TopshelfStudy.NetCoreDemo.csproj new file mode 100644 index 0000000..845409e --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/TopshelfStudy.NetCoreDemo.csproj @@ -0,0 +1,30 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/TopshelfStudy.NetCoreDemo/Utils/RuntimeUtil.cs b/TopshelfStudy.NetCoreDemo/Utils/RuntimeUtil.cs new file mode 100644 index 0000000..2e2d841 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/Utils/RuntimeUtil.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TopshelfStudy.NetCoreDemo +{ + public static class RuntimeUtil + { + /// + /// 是否运行在Debug模式 + /// + public static bool IsDebug + { + get + { + #pragma warning disable +#if DEBUG + return true; +#endif + return false; +#pragma warning restore + } + } + } +} diff --git a/TopshelfStudy.NetCoreDemo/nlog.config b/TopshelfStudy.NetCoreDemo/nlog.config new file mode 100644 index 0000000..8b164c0 --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/nlog.config @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TopshelfStudy.NetCoreDemo/quartz.config b/TopshelfStudy.NetCoreDemo/quartz.config new file mode 100644 index 0000000..852784b --- /dev/null +++ b/TopshelfStudy.NetCoreDemo/quartz.config @@ -0,0 +1,34 @@ +quartz.scheduler.instanceName = DemoScheduler + +quartz.threadPool.threadCount = 10 + +quartz.jobStore.misfireThreshold = 60000 + +quartz.serializer.type = json + +# 数据库配置 +# 配置以使用作业StoreTx +# quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz + +# 将 AdoJobStore 配置为使用驱动程序委托 +# quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz + +# 使用表前缀配置 AdoJobStore +# quartz.jobStore.tablePrefix = QRTZ_ + +# 使用“要使用的数据源名称”配置 AdoJobStore +# quartz.jobStore.dataSource = myDS + +# 设置数据源的连接字符串 +# quartz.dataSource.myDS.connectionString = server=127.0.0.1;port=3306;user=root;password=yt-461400;database=wi_solution;Sslmode=None;Character Set=utf8; + +# 设置数据库提供程序 +# quartz.dataSource.myDS.provider = MySql + +# 将 AdoJobStore 配置为将字符串用作作业数据映射值(建议) +# quartz.jobStore.useProperties = false + + +# 负载均衡 +quartz.jobStore.clustered = false +quartz.scheduler.instanceId = AUTO \ No newline at end of file diff --git a/TopshelfStudy.sln b/TopshelfStudy.sln new file mode 100644 index 0000000..17ac05b --- /dev/null +++ b/TopshelfStudy.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30104.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopshelfStudy.NetCoreDemo", "TopshelfStudy.NetCoreDemo\TopshelfStudy.NetCoreDemo.csproj", "{CDBC7EDE-2C69-4DC4-8D7E-E5540F2689F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CDBC7EDE-2C69-4DC4-8D7E-E5540F2689F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDBC7EDE-2C69-4DC4-8D7E-E5540F2689F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDBC7EDE-2C69-4DC4-8D7E-E5540F2689F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDBC7EDE-2C69-4DC4-8D7E-E5540F2689F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9AEE3FEB-F60C-4A22-9692-49B04B1F0DA5} + EndGlobalSection +EndGlobal