当前位置: 首页 > news >正文

接口开发之使用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

相关文章:

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

C#制作定时任务工具执行CMD命令 概要准备知识点实现原理thinkphp配置winform执行CMD命令读取ini配置文件定时任务Quartz.Net 完整代码Job.csIniFunc.csForm1.csconfig.ini简易定时任务工具雏形 概要 很多时候写接口上线后还会遇到很多修改&#xff0c;类似JAVA,C#,delphi制作的…...

XSS脚本(存储型xss获取肉鸡的cookies)

XSS脚本&#xff08;存储型xss获取肉鸡的cookies&#xff09; 存储型XSS就是在能够提交上传的文本框中提交一些标签代码&#xff0c;这段代码被插入到页面中&#xff0c;肉鸡每次点击这个页面时都会有弹框弹出。&#xff08;只要点击就会弹框&#xff09; 反射性XSS顾名思义插入…...

【React】04.MVC模式和MVVM模式

React是Web前端框架 1、目前市面上比较主流的前端框架 ReactAngular&#xff08;NG框架&#xff09;Vue 主流的思想&#xff1a; 不在直接去操作DOM&#xff0c;而是改为“数据驱动思想” 操作DOM思想&#xff1a; 操作DOM比较消耗性能[主要原因就是&#xff0c;可能会导…...

调试代码0

dev_update_off () * read_image (Image, C:/Users/Public/Documents/MVTec/HALCON-12.0/examples/images/smd/smd_on_chip_01.png) read_image (Image, D:/图像文件/图片/图片/基板/20230609-103004-0.bmp) get_image_size (Image, Width, Height) * dev_close_window () * de…...

【C++心愿便利店】No.12---C++之探索string底层实现

文章目录 前言一、写实拷贝&#xff08;了解&#xff09;二、string类常用接口实现2.1 成员变量2.2 默认构造函数2.3 拷贝构造函数2.4 operator2.5 operator[]2.6 c_str2.7 size()2.8 capacity() 三、迭代器的实现3.1 begin()和end()3.2 范围for 四、string类增删查改4.1 reser…...

Android Studio(列表视图ListView)

前言 前面在适配器章节&#xff0c;已经介绍了ListView的作用(干什么的)&#xff0c;这节将主要介绍如何去设计ListView页面视图。 思考 列表视图需要些什么&#xff1f; 1. 列表项容器&#xff08;装载各列表项的容器&#xff09;&#xff1a;<ListView/> 2. 列表项布局…...

让深度神经网络绘画以了解它们是如何工作的

一、说明 深度学习如此有效&#xff0c;这真是一个谜。尽管有一些关于深度神经网络为何如此有效的线索&#xff0c;但事实是没有人完全确定&#xff0c;并且深度学习的理论理解是一个非常活跃的研究领域。 在本教程中&#xff0c;我们将以一种不寻常的方式触及问题的一个小方面…...

https://www.jianshu.com/p/34bf240b85a9

https://www.jianshu.com/p/34bf240b85a9 https://www.eccee.com/soft-platform/991.html...

如何导出PPT画的图为高清图片?插入到world后不压缩图像的设置方法?

期刊投稿的时候&#xff0c;需要图片保持一定的清晰度数&#xff0c;那么我们怎么才能从PPT中导出符合要求的图片呢&#xff1f; 对于矢量图绘图软件所画的图&#xff0c;直接导出即可。 而PPT导出的图片清晰度在60pi&#xff0c;就很模糊。 整体思路&#xff1a; PPT绘图——…...

【Spring】Spring IOC DI

Spring IOC & DI IOC DI入门什么是Spring什么是容器什么是IOC IOC介绍传统程序开发解决方案 DI IOC详解Bean的存储Controller(控制器存储)Service(服务存储)Repository(仓库存储)Component(组件存储)Configuration(配置存储) 为什么需要这么多类注解类注解之间的关系方法注…...

一招解密网络流量瓶颈!

前言 我们曾介绍过观测云提供全面的基础设施监测方案&#xff08;参见《全方位监控基础设施&#xff0c;坚实守护您的业务稳定&#xff01;》&#xff09;&#xff0c;能够高效全面地帮助您实时观测所有的基础设施对象及云产品等&#xff0c;赋能您的业务稳定发展。今天我们将…...

某校帮签到小程序m 加密参数解析

小程序解密清参考我以前的文章 VX小程序逆向 js版本 function n(e, a) {var t (65535 & e) (65535 & a);return (e >> 16) (a >> 16) (t >> 16) << 16 | 65535 & t };function i(e, a, t, n, r, i, s) {return o(a & n | t &…...

Node.js |(六)express框架 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;express使用&#x1f407;初体验&#x1f407;express路由⭐️路由的使用⭐️获取请求参数⭐️获取路由参数&#x1f525;练习&#xff1a;根据路由参数响应歌手信息…...

包教包会:Mysql主从复制搭建

笑小枫的专属目录 一、无聊的理论知识1. 主从复制原理2. 主从复制的工作过程3. MySQL四种同步方式 二、docker下安装、启动mysql1. 安装主库2. 安装从库 三、配置Master(主)四、配置Slave(从)五、链接Master(主)和Slave(从)六、主从复制排错1. 错误&#xff1a;error connectin…...

Subset Selection

白话解释&#xff1a;https://www.geeksforgeeks.org/feature-subset-selection-process/ 貌似有一种比较常见的方法&#xff0c;称为多元逐步回归有3种筛选自变量的方法 &#xff08;1&#xff09;向前法&#xff1a;n个因变量情况&#xff0c;慢慢增加因变量到方程中&#x…...

【测开求职】面试题:计算机网络 精简版整理

本篇文章整理的是在秋招过程中遇到的计算机网络高频面试题,应付部分中小厂的测试开发工程师面试完全没有问题,如果时间充足的话,建议再看一下笔者的另外一篇文章:【测开求职】面试题:计算机网络 详细版整理,会让你对整个计算机网络有足够全面深刻的理解,亲测应付各个大厂…...

设计模式-代理模式(delegate)

什么是代理&#xff1f; 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方…...

MongoDB 安装与配置

MongoDB 安装与配置 MongoDB 是一个高性能、开源的 NoSQL 数据库&#xff0c;它提供了丰富的查询功能和高可用性。本文将详细讲解 MongoDB 的安装与配置过程。 1. MongoDB 安装 1.1 Windows 平台安装 下载 MongoDB 安装包 访问 MongoDB 官方下载页面&#xff08;https://w…...

rabbitMq创建交换机,以及路由键绑定队列教程

创建交换机&#xff1a; 创建队列&#xff1a; 创建路由&#xff0c;绑定到交换机&#xff1a;...

odoo16前端框架源码阅读——ormService.js

odoo16前端框架源码阅读——ormService.js 路径&#xff1a;addons\web\static\src\core\orm_service.js 简单翻译一下代码中的注释&#xff1a; ORM服务是js代码和python的ORM层通信的标准方法。 然后讲了One2many and Many2many特使的指令格式&#xff0c;每个指令都是3元…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...