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