接口开发之使用C#插件Quartz.Net定时执行CMD任务工具

C#制作定时任务工具执行CMD命令

  • 概要
  • 准备
  • 知识点
    • 实现原理
    • thinkphp配置
    • winform
    • 执行CMD命令
    • 读取ini配置文件
    • 定时任务Quartz.Net
  • 完整代码
    • Job.cs
    • IniFunc.cs
    • Form1.cs
    • config.ini
    • 简易定时任务工具雏形

概要

  • 很多时候写接口上线后还会遇到很多修改,类似JAVA,C#,delphi制作的接口上线后难以修改,测试也有困难。
  • 为了接口便于制作和修改,采用动态语言编写接口+定时任务基座的处理方法,例如:PHP写的接口内容,使用定时任务工具定时执行,这样即使接口上线后也可以随意修改PHP这种解释性脚本,方便修改和定位错误。
  • 定时任务工具+python也是很好的解决方案
  • 定时任务可以采用JAVA或者C#来构建,目前采用C#构建定时任务桌面工具

准备

  • vs2019+C# winform
  • phpstudy2016+thinkphp3.2.3
  • quartz.net 3.7.2

知识点

实现原理

  • thinkphp启用cmd执行程序
  • C#利用定时任务框架quartz.net去执行CMD命令

thinkphp配置

  • 开发阶段可以使用phpstudy环境,部署阶段采用cmd命令可以不使用网络容器
  • thinkphp开启cli模式:入库文件index.php添加一句就可以了
if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');
//添加这一句就可以了
define('MODE_NAME', 'cli');
...其他不变
  • 配置后网络容器和CMD都可以执行thinkphp,CMD执行语句:
D:\phpStudy\php\php-7.0.12-nts\php.exe  D:\phpStudy\WWW\tp3\index.php Home/Index/queryAndWrite

说明:绝对路径找到php.exe,去执行thinkphp中的方法
另外,如果不采用自定义基座(定时任务工具),可以使用win自带的计划任务也行,但是计划任务会弹出cmd框,所以在cmd命令旁添加一个vb命令,执行这个vb命令就不会有弹窗了:

Set ws = CreateObject("Wscript.Shell")    
ws.run "cmd /c times.bat",vbhide

在这里插入图片描述

winform

  • 项目结构:
    在这里插入图片描述
    说明:
    引用:类似java的maven包
    Form1.cs:窗口1,其中Form1.Designer.cs是编译器自动生成的布局代码,和Form是分步类,等同一个类分成2个文件
    IniFunc.cs:读取ini配置文件
    Job.cs:具体任务,这里只有一个任务,但是通过不同的触发器传值形成不同任务分身
    Promgram.cs:程序入口

  • 任务类中调用Form1的控件

  1. From1定义为静态类
 		public static Form1 form1;public Form1(){InitializeComponent();form1 = this;}
  1. 控件设置成public
    在这里插入图片描述

  2. Job通过静态类访问From1控件

var c = Form1.form1.textBox1.Text;
MessageBox.Show(c);

执行CMD命令

//需要引入using System.Diagnostics;
private void cmd(String t){var p = new Process();p.StartInfo.FileName = "cmd.exe";p.StartInfo.RedirectStandardInput = true;p.StartInfo.UseShellExecute = false;p.StartInfo.CreateNoWindow = true;p.Start();p.StandardInput.WriteLine(t);//p.StandardInput.WriteLine("exit");p.StandardInput.Flush();}

读取ini配置文件

  1. Debug目录下新建config.ini
[Information]
job1=D:\phpStudy\php\php-7.0.12-nts\php.exe  D:\phpStudy\WWW\tp3\index.php Home/Index/queryAndWrite
job2=D:\phpStudy\php\php-7.0.12-nts\php.exe  D:\phpStudy\WWW\tp3\index.php Home/Index/queryAndWrite2
  1. 定义文件路径,在Form1事件load中选择Form1_Load,然后按钮1点击后获取配置文件内容,job1和job2是两个定时任务,去执行thinkphp中的数据库操作
		private string filename = null;private void Form1_Load(object sender, EventArgs e){filename = Application.StartupPath + "\\config.ini";//MessageBox.Show(filename);}private void button1_Click(object sender, EventArgs e){//this.textBox1.Text = "777";string job1 = IniFunc.getString("Information", "job1", null, filename);string job2 = IniFunc.getString("Information", "job2", null, filename);textBox1.Text = job1;textBox2.Text = job2;//Task(job1,job2);}

定时任务Quartz.Net

  • 安装:
  1. 右键项目,点击管理NuGet
  2. 浏览中搜索quartz,点击安装
  3. 安装成功后在项目引用中会有quartz.dll
  • 构建定时任务大概分为4步:
  1. 构建scheduler(任务管理器)并开启
  2. 创建job,添加job
  3. 构建触发器
  4. scheduler中添加job

完整代码

Job.cs

using Quartz;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;namespace WindowsFormsApp1
{public class Job : IJob{//public static readonly JobKey Key = new JobKey("customer-process", "group");//这里是定义job唯一keypublic async Task Execute(IJobExecutionContext context){var customerId = context.MergedJobDataMap.GetString("CustomerId");//获取trggier传来的值,同一个job通过trggier值不同而执行不同任务await Task.Run(() =>{//Random rd = new Random();try{//MessageBox.Show($"CustomerId={customerId}");cmd(customerId);}catch (System.Exception e){MessageBox.Show(e.Message);}//try//{//    var c = Form1.form1.textBox1.Text;//获取界面文本值//    cmd(c);//}//catch (System.Exception e)//{//    MessageBox.Show(e.Message);//}});}//执行一个cmd命令private void cmd(String t){var p = new Process();p.StartInfo.FileName = "cmd.exe";p.StartInfo.RedirectStandardInput = true;p.StartInfo.UseShellExecute = false;p.StartInfo.CreateNoWindow = true;//不显示窗口p.Start();p.StandardInput.WriteLine(t);//p.StandardInput.WriteLine("exit");//执行退出,可以不要p.StandardInput.Flush();}}
}

IniFunc.cs

using System.Runtime.InteropServices;
using System.Text;
//https://blog.csdn.net/qq_38693757/article/details/121675847
namespace WindowsFormsApp1
{public static class IniFunc{/// <summary>/// 获取值/// </summary>/// <param name="section">段落名</param>/// <param name="key">键名</param>/// <param name="defval">读取异常是的缺省值</param>/// <param name="retval">键名所对应的的值,没有找到返回空值</param>/// <param name="size">返回值允许的大小</param>/// <param name="filepath">ini文件的完整路径</param>/// <returns></returns>[DllImport("kernel32.dll")]private static extern int GetPrivateProfileString(string section,string key,string defval,StringBuilder retval,int size,string filepath);/// <summary>/// 写入/// </summary>/// <param name="section">需要写入的段落名</param>/// <param name="key">需要写入的键名</param>/// <param name="val">写入值</param>/// <param name="filepath">ini文件的完整路径</param>/// <returns></returns>[DllImport("kernel32.dll")]private static extern int WritePrivateProfileString(string section,string key,string val,string filepath);/// <summary>/// 获取数据/// </summary>/// <param name="section">段落名</param>/// <param name="key">键名</param>/// <param name="def">没有找到时返回的默认值</param>/// <param name="filename">ini文件完整路径</param>/// <returns></returns>public static string getString(string section, string key, string def, string filename){StringBuilder sb = new StringBuilder(1024);GetPrivateProfileString(section, key, def, sb, 1024, filename);return sb.ToString();}/// <summary>/// 写入数据/// </summary>/// <param name="section">段落名</param>/// <param name="key">键名</param>/// <param name="val">写入值</param>/// <param name="filename">ini文件完整路径</param>public static void writeString(string section, string key, string val, string filename){WritePrivateProfileString(section, key, val, filename);}}
}

Form1.cs

using Quartz;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading.Tasks;
using Quartz.Impl;namespace WindowsFormsApp1
{public partial class Form1 : Form{//定义静态类,便于外部访问,类似单例public static Form1 form1;public Form1(){InitializeComponent();form1 = this;}private string filename = null;//获取ini文件路径private void Form1_Load(object sender, EventArgs e){filename = Application.StartupPath + "\\config.ini";//MessageBox.Show(filename);}//按钮点击后,显示ini,同时执行定时任务private void button1_Click(object sender, EventArgs e){//获取ini值string job1 = IniFunc.getString("Information", "job1", null, filename);string job2 = IniFunc.getString("Information", "job2", null, filename);//显示在界面上textBox1.Text = job1;textBox2.Text = job2;//执行定时任务Task(job1,job2);}//执行定时任务public async void Task(string cmd1,string cmd2) {//构建scheduler管理器StdSchedulerFactory factory = new StdSchedulerFactory();IScheduler scheduler = await factory.GetScheduler();await scheduler.Start();//3.7.2版本官网是先执行,再加入任务,意思是可以动态添加,老博客都是后执行//定义任务:WithIdentity("a")是任务的识别码Key,这个主要和trigger关联用,可以是KV,也可以是KIJobDetail job = JobBuilder.Create<Job>().WithIdentity("a").Build();//这里的模式是一个job对于若干个trigger,所以需要先添加job,然后trigger去关联这个jobawait scheduler.AddJob(job, replace: true, storeNonDurableWhileAwaitingScheduling: true);//定义trigger,并关联job,并使用JobData(JobDataMap)传值ITrigger trigger = TriggerBuilder.Create().WithIdentity("trigger1")//.StartNow().ForJob("a").UsingJobData("CustomerId", cmd1).WithSimpleSchedule(x => x.WithIntervalInSeconds(5)//5秒一次.RepeatForever()).Build();ITrigger trigger2 = TriggerBuilder.Create().WithIdentity("trigger2")//.StartNow().ForJob("a").UsingJobData("CustomerId", cmd2).WithSimpleSchedule(x => x.WithIntervalInSeconds(7)//7秒一次.RepeatForever()).Build();//添加触发器,普通多任务是这样的await scheduler.ScheduleJob(job,trigger),但是这里是单任务多触发await scheduler.ScheduleJob(trigger);await scheduler.ScheduleJob(trigger2);MessageBox.Show("任务开始");}}
}

config.ini

[Information]
job1=D:\phpStudy\php\php-7.0.12-nts\php.exe  D:\phpStudy\WWW\tp3\index.php Home/Index/queryAndWrite
job2=D:\phpStudy\php\php-7.0.12-nts\php.exe  D:\phpStudy\WWW\tp3\index.php Home/Index/queryAndWrite2

简易定时任务工具雏形

在这里插入图片描述

官网的例子才是经典的,去看看:

  • quartz.net:https://www.quartz-scheduler.net/documentation/best-practices.html#static-job-key
  • API:https://quartznet.sourceforge.io/apidoc/3.0/html/
  • 参考:https://blog.csdn.net/qq_46104221/article/details/130578236

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/186876.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试字节测开岗失败后,被面试官在朋友圈吐槽了......(心累)

在和朋友吃夜宵的时候&#xff0c;朋友向我吐槽说自己在参加某大厂测试面试的时候被面试官怼得哑口无言&#xff0c;场面让他一度十分尴尬 印象最深的就是下面几个问题&#xff1a; 根据你以前的工作经验和学习到的测试技术&#xff0c;说说你对质量保证的理解&#xff1f; 非…

动态规划-构建乘积数组

** 描述 给定一个数组 A[0,1,…,n-1] ,请构建一个数组 B[0,1,…,n-1] ,其中 B 的元素 B[i]A[0]A[1]…*A[i-1]A[i1]…*A[n-1]&#xff08;除 A[i] 以外的全部元素的的乘积&#xff09;。程序中不能使用除法。&#xff08;注意&#xff1a;规定 B[0] A[1] * A[2] * … * A[n-1…

GeoGebra:数学动画制作工具重磅来袭

【线性代数】线性代数可视化工具&#xff1a;manim manim是之前我跟大家分享的一个线性代数动画制作工具。 但我之前的描述有些许偏差&#xff0c;这里要更正一下&#xff0c;manim不仅限于制作线性代数动画&#xff0c;也可以制作数学其他学科的动画&#xff0c;例如微积分&…

[极客大挑战 2019]BuyFlag 1(两种解法)

题目环境&#xff1a; FLAG NEED YOUR 100000000 MONEY flag需要你的100000000元 F12瞅瞅源代码&#xff1a; if (isset($_POST[password])){ $password $_POST[password]; if (is_numeric($password)) { echo "password cant be number" } elseif ($pas…

理解MySQL的日志 Redo、Undo

理解MySQL的Redo日志和Undo日志 1、MySQL 日志文件解决的问题2、redo 日志2.1、redo log 的组成2.2、redo log 刷盘策略2.3、MySQL 的 redo log解决了哪些问题 3、undo 日志3.1、undo 日志作用3.2、undo log 的类型3.3、undo log 的生命周期3.4、事务回滚相关的几个隐藏字段 1、…

使用easyui前端框架快速构建一个crud应用

本篇文章将会详细介绍jquery easyui前端框架的使用&#xff0c;通过创建一个crud应用来带大家快速掌握easyui的使用。 easyui是博主最喜欢的前端框架&#xff0c;没有之一&#xff0c;因为它提供了多种主题&#xff0c;而且有圆润的各种组件。 目录 一、快速开始 二、准备工作…

JS逆向爬虫---请求参数加密③【比特币交易爬虫】

查询参数确定 t无加密 请求头参数加密 X-Apikey参数加密确定 X-Apikey逆向 const API_KEY "a2c903cc-b31e-4547-9299-b6d07b7631ab" function encryptApiKey(){ var t API_KEY, e t.split(""), n e.splice(0, 8);return t e.concat(n).join("&…

利用Ansible实现批量Linux服务器安全配置

1.摘要 在上一篇<<初步利用Ansible实现批量服务器自动化管理>>文章中, 我初步实现了通过编写清单和剧本来实现多台服务器的自动化管理,在本章节中, 我将利用Ansible的剧本来实现更实用、更复杂一点的功能, 主要功能包括三个:1.同时在三台服务器中增加IP访问控制,只…

万宾科技智能井盖,实现对井盖的监测

随着人工智能和物联网技术的不断变化&#xff0c;各种适用于市政府提高管理能力和公共服务水平的高科技产品不断更新。在道路基础设施建设过程中&#xff0c;智能井盖传感器的出现时刻保护着城市地下生命线&#xff0c;而且可以对地下水道井盖进行实时的监测并完成数据上传等工…

Excel下拉填充时,如何使得数字不递增?

问题描述&#xff1a;Excel下拉填充时&#xff0c;如何使得数字不递增&#xff1f; 解决办法&#xff1a;先下拉填充数据之后&#xff0c;看到最后一个单元格的右下角有个填充设置的符号&#xff0c;右键选择复制单元格即可。其中这里的填充序列就是递增数字的操作。

使用Pytorch的一些小细节(一)

文章目录 前言数据结构-张量max函数索引函数赋值函数拼接函数 前言 由于不经常动手写代码&#xff0c;所以对于python语言中的常见数据结构的用法也不是很熟悉&#xff0c;对于pytorch中的数据结构就更加不熟悉了。之前的代码基础是基于C语言的&#xff0c;属性都是自己定义&a…

Selenium是什么,带你了解自动化测试的神奇之处

一、使用测试工具 工欲善其事&#xff0c;必先利其器。在开始具体的自动化测试之前&#xff0c;我们需要做好更多的准备&#xff0c;包括以下几个方面&#xff1a; 认识自动化测试 准备自动化测试工具 使用有效的方式 针对具体的测试对象 接下来的第一部分内容&#xff0c;我…

什么是数据库?数据库有哪些基本分类和主要特点?

数据库是以某种有组织的方式存储的数据集合。本文从数据库的基本概念出发&#xff0c;详细解读了数据库的主要类别和基本特点&#xff0c;并就大模型时代备受瞩目的数据库类型——向量数据库进行了深度剖析&#xff0c;供大家在了解数据库领域的基本概念时起到一点参考作用。 …

【chat】2:vs2022 连接远程ubuntu服务器远程cmake开发

大神们是使用vs远程连接和调试的:C++搭建集群聊天室(三):配置远程代码编辑神器 VScode我尝试过vs++ 和 clion 都不错。在 Visual Studio 中配置 Linux CMake 项目 比较麻烦的就是要配置CMakeSettings.json ,而且会自动做复制指定远程 Linux 目标,则会将源复制到远程系统 …

19、Flink 的Table API 和 SQL 中的自定义函数及示例(3)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

如何实现Debian工控电脑USB接口安全管控

Debian 作为工控电脑操作系统具有稳定性、安全性、自定义性和丰富的软件包等优势&#xff0c;适用于要求高度可靠性和安全性的工控应用。 Debian 作为工控电脑操作系统在工业控制领域有很大优势&#xff0c;包括&#xff1a; 稳定性&#xff1a;Debian 的发布版以其稳定性而闻…

小程序多文件上传 Tdesign

众所周知&#xff0c;小程序文件上传还是有点麻烦的&#xff0c;其实主要还是小程序对的接口有诸多的不便&#xff0c;比如说&#xff0c;文件不能批量提交&#xff0c;只能一个个的提交&#xff0c;小程序的上传需要专门的接口。 普通的小程序的页面也比普通的HTML复杂很多 现…

centos中安装的goland配置sdk报错:所选的目录不是Go SDK的有效主路经

选中目录后一直报错&#xff1a; 正确的位置&#xff1a; 原因竟然是使用 解压go1.21.4.linux-amd64.tar.gz 包出来&#xff0c;少了scr和test目录&#xff0c;重新解压后可以正确设定SDK主目录。 有同样问题的可以确认一下。 tar -C /usr/local -zxvf go1.19.2.linux-amd64.…

java项目之高校奖学金管理系统(ssm框架+源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的高校奖学金管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 管理员&#xff1a;首…

NodeJS 入门笔记

文档地址 课程地址 源码 提取码&#xff1a;963h hello wrold console.log(hello, world);node hello.jsnodejs 中不能使用 DOM(document) 和 BOM(window) 的 API&#xff1a; documentwindowhistorynavigatorlocation 但是下面的 API 是相通的&#xff1a; consoletimer…