直接贴代码了:

首先我们可以把所有的 Job 放到一个单独的 DLL 中,好处是可以共享这些业务 Job。比如我们新建一个 QuartzNetDemo.WinService.Jobs 的类库。

然后,我们再先定义一个 WriteTextToFileJob 的任务:

    public class WriteTextToFileJob : IJob
{
// Fields
private static readonly string TypeName = typeof(WriteTextToFileJob).FullName; // Methods
public virtual void Execute(IJobExecutionContext context)
{
FileUtil.AppendFormat("=================================任务开始:{0}=================================", new object[] { TypeName });
FileUtil.AppendFormat("当前时间:{0},正在运行...", new object[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });
if (context.JobDetail.JobDataMap.ContainsKey("UserName"))
{
string str = context.JobDetail.JobDataMap.GetString("UserName");
FileUtil.AppendFormat("当前时间:{0},接受到参数 \"{1}\" 的值等于 {2}", new object[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "UserName", str });
}
if (context.JobDetail.JobDataMap.ContainsKey("Msg"))
{
string str2 = context.JobDetail.JobDataMap.GetString("Msg");
FileUtil.AppendFormat("当前时间:{0},接受到参数 \"{1}\" 的值等于 {2}", new object[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "Msg", str2 });
}
FileUtil.AppendFormat("当前时间:{0},准备暂停 {1} 秒钟...", new object[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), });
Thread.Sleep(TimeSpan.FromSeconds(5.0));
FileUtil.AppendFormat("当前时间:{0},已经运行完毕!", new object[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });
FileUtil.AppendFormat("=================================任务结束:{0}=================================", new object[] { TypeName });
}
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- 注意:App.config 文件更改后,无须重新安装 Windows Services,只需要重启就可以了 -->
<configSections>
<!-- 注册 Quartz 节点 -->
<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- 注册 log4net -->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<!-- 配置 log4net -->
<log4net configSource="log4net.config" />
<appSettings>
<!-- 下面是配置 Windows 服务的相关参数 -->
<add key="quartz.server.serviceName" value="QuartzNetDemoWinService" />
<add key="quartz.server.serviceDisplayName" value="QuartzNetDemoWinService" />
<add key="quartz.server.serviceDescription" value="负责项目的定时调度任务" />
</appSettings>
<!-- Quartz 配置 -->
<quartz>
<!-- 基本参数配置 -->
<add key="quartz.scheduler.instanceName" value="QuartzNetDemo.WinService" />
<add key="quartz.scheduler.instanceId" value="AUTO" />
<add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
<add key="quartz.threadPool.threadCount" value="" />
<add key="quartz.threadPool.threadPriority" value="Normal" />
<!-- 下面是配置把 Quartz 相关的任务和触发器保存在数据库中 -->
<add key="quartz.jobStore.useProperties" value="true" />
<add key="quartz.jobStore.clustered" value="true" />
<add key="quartz.jobStore.misfireThreshold" value="" />
<add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
<add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
<add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz" />
<add key="quartz.jobStore.dataSource" value="myDS" />
<add key="quartz.dataSource.myDS.connectionString" value="Data Source=.;Initial Catalog=TestDB;User ID=sa;Password=123456;" />
<add key="quartz.dataSource.myDS.provider" value="SqlServer-20" />
<!-- 下面是配置可以远程访问
<add key="quartz.scheduler.exporter.type" value="Quartz.Simpl.RemotingSchedulerExporter, Quartz"/>
<add key="quartz.scheduler.exporter.port" value=""/>
<add key="quartz.scheduler.exporter.bindName" value="QuartzScheduler"/>
<add key="quartz.scheduler.exporter.channelType" value="tcp"/>
<add key="quartz.scheduler.exporter.channelName" value="httpQuartz"/>
<add key="quartz.scheduler.exporter.rejectRemoteRequests" value="true"/>
-->
<!-- 下面是 XML 注册任务(是否可以不配置) -->
<add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
<add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml" />
<!-- 下面是触发器历史记录插件 -->
<add key="quartz.plugin.triggHistory.type" value="Quartz.Plugin.History.LoggingJobHistoryPlugin" />
<!-- 下面是 XML 任务初始化 - 单位为秒 -->
<add key="quartz.plugin.jobInitializer.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin" />
<add key="quartz.plugin.jobInitializer.fileNames" value="quartz_jobs.xml" />
<add key="quartz.plugin.jobInitializer.failOnFileNotFound" value="true" />
<add key="quartz.plugin.jobInitializer.scanInterval" value="" />
</quartz>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

quartz_jobs.xml

<?xml version="1.0" encoding="utf-8" ?>
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"> <processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives> <schedule> <job>
<name>WriteTextToFileJob</name>
<group>jobGroup1</group>
<description>jobDesciption1</description>
<job-type>QuartzNetDemo.WinService.Jobs.WriteTextToFileJob, QuartzNetDemo.WinService.Jobs</job-type>
<durable>true</durable>
<recover>false</recover>
<job-data-map>
<entry>
<key>UserName</key>
<value>周星驰</value>
</entry>
<entry>
<key>Msg</key>
<value>Hello world,欢迎使用 Quartz.net 调度组件</value>
</entry>
</job-data-map>
</job> <trigger>
<simple>
<name>WriteTextToFileJobTrigger</name>
<group>triggerGroup1</group>
<description>SimpleTriggerDescription</description>
<job-name>WriteTextToFileJob</job-name>
<job-group>jobGroup1</job-group>
<start-time>--28T18::.0Z</start-time>
<end-time>--04T18::.0Z</end-time>
<misfire-instruction>SmartPolicy</misfire-instruction>
<repeat-count></repeat-count>
<repeat-interval></repeat-interval>
</simple>
</trigger> </schedule> </job-scheduling-data>

log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\log_" />
<param name="AppendToFile" value="true" />
<!-- <datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/> 这句是按照年月文件夹分类 -->
<param name="DatePattern" value="yyyy-MM-dd_HH&quot;.log&quot;" />
<param name="RollingStyle" value="Date" />
<param name="StaticLogFileName" value="false" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %x %m %n" />
<!--每条日志末尾的文字说明-->
<!--输出格式-->
<!--样例:-- ::, [] INFO Fujica.PackingPlatform.WebUI.MainClass [(null)] - info-->
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n出错类: %file 在第 %line 行 %n描述:%message%newline %n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender>
<!-- Admin 访问信息 -->
<appender name="AdminLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\admin_log_" />
<param name="AppendToFile" value="true" />
<!-- <datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/> 这句是按照年月文件夹分类 -->
<param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
<param name="RollingStyle" value="Date" />
<param name="StaticLogFileName" value="false" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %x %m %n" />
<!--每条日志末尾的文字说明-->
<!--输出格式-->
<!--样例:-- ::, [] INFO Fujica.PackingPlatform.WebUI.MainClass [(null)] - info-->
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n出错类: %file 在第 %line 行 %n描述:%message%newline %n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender>
<logger name="adminLogger" additivity="false">
<level value="ALL" />
<appender-ref ref="AdminLogFileAppender" />
</logger>
<root>
<level value="ALL" />
<appender-ref ref="AdminLogFileAppender" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>

SchedulerServer.cs

using log4net.Config;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace QuartzNetDemo.WinService
{
public class SchedulerServer
{
// Fields
private readonly StdSchedulerFactory _schedulerFactory = new StdSchedulerFactory(); // Methods
public void Start()
{
Console.WriteLine("Starting scheduler...");
XmlConfigurator.Configure();
this._schedulerFactory.GetScheduler().Start();
} public void Stop()
{
if (this._schedulerFactory != null) this._schedulerFactory.GetScheduler().Shutdown(false);
}
}
}

Configuration.cs

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Text; namespace QuartzNetDemo.WinService
{
public class Configuration
{
// Fields
private static readonly NameValueCollection configuration = ((NameValueCollection) ConfigurationManager.GetSection("appSettings"));
private const string DefaultServiceDescription = "负责项目的定时调度任务";
private const string DefaultServiceDisplayName = "QuartzNetDemoWinService";
private const string DefaultServiceName = "QuartzNetDemoWinService";
private const string KeyServiceDescription = "quartz.server.serviceDescription";
private const string KeyServiceDisplayName = "quartz.server.serviceDisplayName";
private const string KeyServiceName = "quartz.server.serviceName";
private const string PrefixServerConfiguration = "quartz.server"; // Methods
private static string GetConfigurationOrDefault(string configurationKey, string defaultValue)
{
string retValue = null;
if (configuration != null) retValue = configuration[configurationKey];
if (retValue == null || retValue.Trim().Length == ) retValue = defaultValue;
return retValue;
} // Properties
public static string ServiceDescription
{
get
{
return GetConfigurationOrDefault(KeyServiceDescription, DefaultServiceDescription);
}
} public static string ServiceDisplayName
{
get
{
return GetConfigurationOrDefault(KeyServiceDisplayName, DefaultServiceDisplayName);
}
} public static string ServiceName
{
get
{
return GetConfigurationOrDefault(KeyServiceName, DefaultServiceName);
}
}
}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Topshelf;
using Topshelf.HostConfigurators;
using Topshelf.ServiceConfigurators; namespace QuartzNetDemo.WinService
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(delegate(HostConfigurator x)
{
x.Service<SchedulerServer>( (ServiceConfigurator<SchedulerServer> s) =>
{
s.ConstructUsing(name => new SchedulerServer());
s.WhenStarted<SchedulerServer>(tc => tc.Start());
s.WhenStopped<SchedulerServer>(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDescription(Configuration.ServiceDescription);
x.SetDisplayName(Configuration.ServiceDisplayName);
x.SetServiceName(Configuration.ServiceName);
});
}
}
}

Quartz.NET 官方的 tables_sqlServer.sql

-- this script is for SQL Server and Azure SQL

USE [enter_db_name_here]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
GO IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]'))
ALTER TABLE [dbo].[QRTZ_JOB_LISTENERS] DROP CONSTRAINT [FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS] IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]'))
ALTER TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] DROP CONSTRAINT [FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS] IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_CALENDARS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]') AND type in (N'U'))
DROP TABLE [dbo].[QRTZ_JOB_LISTENERS] IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_LOCKS]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]') AND type in (N'U'))
DROP TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].QRTZ_SIMPROP_TRIGGERS
GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_TRIGGERS]
GO CREATE TABLE [dbo].[QRTZ_CALENDARS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[CALENDAR_NAME] [NVARCHAR] (200) NOT NULL ,
[CALENDAR] [VARBINARY](MAX) NOT NULL
)
GO CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[CRON_EXPRESSION] [NVARCHAR] (120) NOT NULL ,
[TIME_ZONE_ID] [NVARCHAR] (80)
)
GO CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[ENTRY_ID] [NVARCHAR] (140) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[INSTANCE_NAME] [NVARCHAR] (200) NOT NULL ,
[FIRED_TIME] [BIGINT] NOT NULL ,
[SCHED_TIME] [BIGINT] NOT NULL ,
[PRIORITY] [INTEGER] NOT NULL ,
[STATE] [NVARCHAR] (16) NOT NULL,
[JOB_NAME] [NVARCHAR] (150) NULL ,
[JOB_GROUP] [NVARCHAR] (150) NULL ,
[IS_NONCONCURRENT] BIT NULL ,
[REQUESTS_RECOVERY] BIT NULL
)
GO CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL
)
GO CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[INSTANCE_NAME] [NVARCHAR] (200) NOT NULL ,
[LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
[CHECKIN_INTERVAL] [BIGINT] NOT NULL
)
GO CREATE TABLE [dbo].[QRTZ_LOCKS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[LOCK_NAME] [NVARCHAR] (40) NOT NULL
)
GO CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[JOB_NAME] [NVARCHAR] (150) NOT NULL ,
[JOB_GROUP] [NVARCHAR] (150) NOT NULL ,
[DESCRIPTION] [NVARCHAR] (250) NULL ,
[JOB_CLASS_NAME] [NVARCHAR] (250) NOT NULL ,
[IS_DURABLE] BIT NOT NULL ,
[IS_NONCONCURRENT] BIT NOT NULL ,
[IS_UPDATE_DATA] BIT NOT NULL ,
[REQUESTS_RECOVERY] BIT NOT NULL ,
[JOB_DATA] [VARBINARY](MAX) NULL
)
GO CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[REPEAT_COUNT] [INTEGER] NOT NULL ,
[REPEAT_INTERVAL] [BIGINT] NOT NULL ,
[TIMES_TRIGGERED] [INTEGER] NOT NULL
)
GO CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[STR_PROP_1] [NVARCHAR] (512) NULL,
[STR_PROP_2] [NVARCHAR] (512) NULL,
[STR_PROP_3] [NVARCHAR] (512) NULL,
[INT_PROP_1] [INT] NULL,
[INT_PROP_2] [INT] NULL,
[LONG_PROP_1] [BIGINT] NULL,
[LONG_PROP_2] [BIGINT] NULL,
[DEC_PROP_1] [NUMERIC] (13,4) NULL,
[DEC_PROP_2] [NUMERIC] (13,4) NULL,
[BOOL_PROP_1] BIT NULL,
[BOOL_PROP_2] BIT NULL,
[TIME_ZONE_ID] [NVARCHAR] (80) NULL
)
GO CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[BLOB_DATA] [VARBINARY](MAX) NULL
)
GO CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME] [NVARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
[TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
[JOB_NAME] [NVARCHAR] (150) NOT NULL ,
[JOB_GROUP] [NVARCHAR] (150) NOT NULL ,
[DESCRIPTION] [NVARCHAR] (250) NULL ,
[NEXT_FIRE_TIME] [BIGINT] NULL ,
[PREV_FIRE_TIME] [BIGINT] NULL ,
[PRIORITY] [INTEGER] NULL ,
[TRIGGER_STATE] [NVARCHAR] (16) NOT NULL ,
[TRIGGER_TYPE] [NVARCHAR] (8) NOT NULL ,
[START_TIME] [BIGINT] NOT NULL ,
[END_TIME] [BIGINT] NULL ,
[CALENDAR_NAME] [NVARCHAR] (200) NULL ,
[MISFIRE_INSTR] [INTEGER] NULL ,
[JOB_DATA] [VARBINARY](MAX) NULL
)
GO ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[CALENDAR_NAME]
)
GO ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[ENTRY_ID]
)
GO ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[INSTANCE_NAME]
)
GO ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[LOCK_NAME]
)
GO ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].QRTZ_BLOB_TRIGGERS WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_BLOB_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
)
GO ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
)
GO CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP)
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME)
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE)
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE)
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE)
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME)
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME)
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME)
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE)
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE) CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME)
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY)
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP)
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
GO

运行后生成的日志比如:admin_log_2018-09-21.log

记录时间:2018-09-21 15:52:22,249
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务开始:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:22,295
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:22,正在运行... 记录时间:2018-09-21 15:52:22,296
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:22,接受到参数 "UserName" 的值等于 周星驰 记录时间:2018-09-21 15:52:22,296
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:22,接受到参数 "Msg" 的值等于 Hello world,欢迎使用 Quartz.net 调度组件 记录时间:2018-09-21 15:52:22,297
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:22,准备暂停 5 秒钟... 记录时间:2018-09-21 15:52:25,192
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务开始:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:25,193
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:25,正在运行... 记录时间:2018-09-21 15:52:25,196
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:25,接受到参数 "UserName" 的值等于 周星驰 记录时间:2018-09-21 15:52:25,197
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:25,接受到参数 "Msg" 的值等于 Hello world,欢迎使用 Quartz.net 调度组件 记录时间:2018-09-21 15:52:25,198
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:25,准备暂停 5 秒钟... 记录时间:2018-09-21 15:52:27,298
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:27,已经运行完毕! 记录时间:2018-09-21 15:52:27,300
线程ID:[QuartzNetDemo.WinService_Worker-2]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务结束:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:28,191
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务开始:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:28,193
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:28,正在运行... 记录时间:2018-09-21 15:52:28,194
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:28,接受到参数 "UserName" 的值等于 周星驰 记录时间:2018-09-21 15:52:28,195
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:28,接受到参数 "Msg" 的值等于 Hello world,欢迎使用 Quartz.net 调度组件 记录时间:2018-09-21 15:52:28,197
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:28,准备暂停 5 秒钟... 记录时间:2018-09-21 15:52:30,200
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:30,已经运行完毕! 记录时间:2018-09-21 15:52:30,202
线程ID:[QuartzNetDemo.WinService_Worker-3]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务结束:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:31,191
线程ID:[QuartzNetDemo.WinService_Worker-5]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务开始:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob================================= 记录时间:2018-09-21 15:52:31,193
线程ID:[QuartzNetDemo.WinService_Worker-5]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:31,正在运行... 记录时间:2018-09-21 15:52:31,194
线程ID:[QuartzNetDemo.WinService_Worker-5]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:31,接受到参数 "UserName" 的值等于 周星驰 记录时间:2018-09-21 15:52:31,197
线程ID:[QuartzNetDemo.WinService_Worker-5]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:31,接受到参数 "Msg" 的值等于 Hello world,欢迎使用 Quartz.net 调度组件 记录时间:2018-09-21 15:52:31,198
线程ID:[QuartzNetDemo.WinService_Worker-5]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:31,准备暂停 5 秒钟... 记录时间:2018-09-21 15:52:33,199
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:当前时间:2018-09-21 15:52:33,已经运行完毕! 记录时间:2018-09-21 15:52:33,201
线程ID:[QuartzNetDemo.WinService_Worker-4]
日志级别: INFO
出错类: D:\WorkSpace\QuartzNetDemo.WinService\QuartzNetDemo.WinService.Jobs\FileUtil.cs 在第 22 行
描述:=================================任务结束:QuartzNetDemo.WinService.Jobs.WriteTextToFileJob=================================

运行效果图:

这个一个利用 Windows Service 挂载 Quartz (定时调度,也叫定时任务)的例子。

1. Windows Service 的名称和描述可以在 App.config 中的 appSettings 中配置。

2. 该 Windows Service 中的 Quartz 已经配置了持久化任务(即把任务信息保存到数据库),所以需要提前建立好数据库(建库脚本参考 Quartz.net 官方说明),并且配置连接字符串。

3. App.config 文件更改后,无须重新安装 Windows Services,只需要重启就可以了。

4. 通过在 quartz_jobs.xml 文件中注册任务,即可以不通过修改代码来完成“动态”注册任务,比如增加一个类库,编译后把 DLL 复制到 Windows Service 所在的目录下,可以不重启 Windows 服务。

5. 可以观察,当改变了 quartz_jobs.xml 文件中的配置后,打印出的日志信息的变化。

6. 我们在 quartz_jobs.xml 配置的 repeat-interval=3000,即 3 秒执行一次,但在 WriteTextToFileJob 中我们通过 Thread.Sleep(TimeSpan.FromSeconds(5)); 延迟了 5 秒,那么就会存在多个实例交错执行的情况,请观察日志。

7. 在 Quartz 的官方示例 example12 中有一个 RemoteServerExample、RemoteClientExample 例子,即可以远程注册任务,但要注意,需要把 Client 项目的 Job 所引用的所有程序集复制到 Server 所在的 Bin 目录,要不然会运行时会抛出无法找到 DLL 异常。且服务端和客户端所引用的 Quartz 的版本必须一致。Quartz 内部是通过 .NET Remoting 来实现的,把 Client 中的 Job 的元数据序列化给 Server 端,然后 Server 端再去反射、调用。

谢谢浏览!

Topshelf + QuartzNet 实现挂载在 WIndows Services 中的定时任务的更多相关文章

  1. Windows 系统文件夹目录挂载到 Linux服务器中

    在Windows系统文件上传到Linux服务器时有时候很麻烦,因为Linux无界面的系统不像Windows系统一样,可以直接复制粘贴,下面方法可以解决Windows系统文件拷贝到Linux服务器. 1 ...

  2. 用C#创建Windows服务(Windows Services)

    用C#创建Windows服务(Windows Services) 学习:  第一步:创建服务框架 创建一个新的 Windows 服务项目,可以从Visual C# 工程中选取 Windows 服务(W ...

  3. 当程序以Windows Services形式启动时当前路径不对

    当程序以Windows Services形式启动时当前路径不对 @(操作系统)[博客|dotNet] 很多时候我们需要将我们的程序写成利用Windows服务的形式来让它能够自启动.今天遇到一个问题,当 ...

  4. 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离

        在某国外大型汽车公司BI项目中,有一个子项目,需要通过大屏幕展示销售报表,程序需要自动启动和关闭.开发人员在开发过程中,发现在Win7的service中不能直接操作UI进程,调查过程中,发现如 ...

  5. [转]解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离

    服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的“开启-关闭”而“开始-停止”其工作内容,在这期间无需任何 ...

  6. Windows Services Windows Services的操作

    Windows Services的操作 一.服务的创建: 1.新建项目——Windows服务 2.这是每个人都会犯的错误,新建一个项目后,都会按F5(运行),就会出现如下错误: 3.安装服务有很多种方 ...

  7. linux挂载本地windows分区或目录

    linux挂载本地windows分区或目录 一.linux挂载本地windows硬盘分区 向虚拟机Centos添加本地windows硬盘 注:(添加物理硬盘后,在centos操作会直接写入本地硬盘) ...

  8. 使用Topshelf组件构建简单的Windows服务

    很多时候都在讨论是否需要了解一个组件或者一个语言的底层原理这个问题,其实我个人觉得,对于这个问题,每个人都有自己的看法,个人情况不同,选择的方式也就会不同了.我个人觉得无论学习什么,都应该尝试着去了解 ...

  9. windows 服务中托管asp.net core

    在windows 服务中托管asp.net core SDK 2.1.300 官方示例 1.添加运行标识符 xml <PropertyGroup> <TargetFramework& ...

随机推荐

  1. GO 函数的参数

    一.函数 函数的参数 1.1 参数的使用 形式参数:定义函数时,用于接收外部传入的数据,叫做形式参数,简称形参. 实际参数:调用函数时,传给形参的实际的数据,叫做实际参数,简称实参. 函数调用: ​ ...

  2. 调试接口你还在用postman吗

    作者 | 陈凯玲 来源 | my.oschina.net/keking/blog/3104972 接口调试是每个软件开发从业者必不可少的一项技能,一个项目的的完成,可能接口测试调试的时间比真正开发写代 ...

  3. python基础(12):函数(二)

    1. 函数参数 之前我们说过了传参,如果我们需要给⼀个函数传参,⽽参数⼜是不确定的,或者我给⼀个函数传很多参数,我的形参就要写很多,很⿇烦,怎么办呢,我们可以考虑使⽤动态参数. 形参的第三种: 动态参 ...

  4. 如何让Python爬虫一天抓取100万张网页

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王平 源自:猿人学Python PS:如有需要Python学习资料的 ...

  5. JavaWeb之Servlet(3)

    Servlet(3) HttpServletRequest 该类的对象封装了所以客户端提交过来的数据 获取所有请求头数据 public java.util.Enumeration<E> g ...

  6. javafx笔记----非javafx线程Platform.runLater赋值不生效情况

    Platform.runLater(() -> { // }); Platform.runLater一些情况下没有赋值到fx页面上 采用task方式 Task<SB> task = ...

  7. layui常用的验证

    var LayVerifyExtend = { notnullNonnegativeInteger: function (value, item) { //value:表单的值.item:表单的DOM ...

  8. 微信小程序简单个人信息表单页面

    wxml部分:这里引用的icon小图标可以自主更换 <view> <view class="titleCss"> <text class=" ...

  9. 【JavaScript】使用document.write输出覆盖HTML问题

    您只能在 HTML 输出中使用 document.write.如果您在文档加载后使用该方法,会覆盖整个文档. 分析 HTML输出流是指当前数据形式是HTML格式的数据,这部分数据正在被导出.传输或显示 ...

  10. linux系统管理-输入输出

    目录 linux系统管理-输入输出 参数传递xargs linux系统管理-输入输出 重定向 将原本要输出到屏幕上的数据信息,重新定向到指定的文件中 运行程序,或者输入一个命令:默认打开4个文件描述符 ...