定时启动关闭程序以及 C++ 相关时间函数

前言

最近在做项目的过程中需要实现定时启动/关闭程序的功能,网上查资料的过程中,发现大多都是通过 windows 创建计划任务的方式实现程序的定时启动,或者是通过写 bat 配合 sleep 关闭程序,感觉都不太行,最后还是采用了通过 C++ 写了一个监控窗口方式实现,在这里简单记录一下爬坑的过程。

启动/关闭程序

一开始只是想通过写一个 bat 脚本来实现启动、关闭程序,但发现还是不怎么靠谱,辗转之后还是通过 c++ 的 system 来实现。

总的来说,代码也很简单,就是命令行,实现如下:

1
system("start .\\Control.exe ");

在这里,命令打开了当前目录下一个名为 Control.exe 的程序,就像在 terminal 中一样。

这里有个问题需要注意:

如果直接写 system(".\\Control.exe "); 的话也可以执行程序,但是对于控制台程序来说,新打开的程序会在当前的黑框框中执行,如果你的程序不会自动关闭,那么也就无法通过监控窗口来关闭它。

更好的做法是加一句 start,也就是 system("start .\\Control.exe "); 这样,监控窗口就会新开一个窗口执行你选定的进程。

类似的,也有关闭程序的命令,直接杀死名为 GetData.exe 程序的进程:

1
system("taskkill /F /IM GetData.exe /fi \"pid gt 0\""); // pid gt 0一定要有,不然关不掉

核心的命令也就这两句,当然,想要定时启动、关闭程序还需要通过读取时间来配合。

c++ 时间函数

使用 time 函数获取当前时间戳

1
time_t time(time_t *time);

该函数返回系统的当前日历时间,返回的是自 1970 年 1 月 1 日以来所经过的秒数。

time_t 其实就是一个整数类型,是 int64_t 的重命名,该函数直接使用返回值就好,参数一般传空即可。

获取当前系统时间

可以使用 ctime 显示当前系统时间:

1
char* ctime(const time_t* time);

示例代码如下:

1
2
3
time_t now = time(NULL);
char* dt = ctime(&now);
cout << "cur time is: " << dt;

输出结果为:

cur time is: Fri Jul 16 14:19:30 2021

格式化

可以使用 tm 结构自定义显示当前时间的格式,示例如下:

1
2
3
4
5
time_t now = time(NULL);
struct tm* cur = localtime(&now);
int cur_hour = cur->tm_hour; // 小时,范围从 0 到 23
int cur_min = cur->tm_min; // 分,范围从 0 到 59
int cur_sec = cur->tm_sec; // 秒,正常范围从 0 到 59

tm 结构如下:

1
2
3
4
5
6
7
8
9
10
11
struct tm {
int tm_sec; // 秒,正常范围从 0 到 59,但允许至 61
int tm_min; // 分,范围从 0 到 59
int tm_hour; // 小时,范围从 0 到 23
int tm_mday; // 一月中的第几天,范围从 1 到 31
int tm_mon; // 月,范围从 0 到 11
int tm_year; // 自 1900 年起的年数
int tm_wday; // 一周中的第几天,范围从 0 到 6,从星期日算起
int tm_yday; // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
int tm_isdst; // 夏令时
};

也可以使用 strftime()函数,该函数可用于格式化日期和时间为指定的格式,如果产生的 C 字符串小于 size 个字符(包括空结束字符),则会返回复制到 str 中的字符总数(不包括空结束字符),否则返回零。

1
2
3
4
time_t cur = time(NULL);
char buf[256];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&cur));
cout << buf << endl;

定时启动/关闭程序

在讲完了上面两个模块之后,我们便可以把两个模块加以组合,实现定时启动/关闭程序的功能。

简单来说,就是通过 while(true) 不断监听时间,到达指定的时间节点或者时间段就启动程序。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <time.h>
#include <direct.h>
#include <windows.h>
using namespace std;

int main()
{
while (true)
{
// 获取当前程序路径
// char* buffer = _getcwd(NULL, 0);

time_t now = time(NULL); // 获取当前时间
char* dtime = ctime(&now);
dtime[strlen(dtime) - 1] = '\0'; // 去掉末尾的换行符
struct tm* cur = localtime(&now);
int cur_wday = cur->tm_wday; // 一周中的第几天,范围从 0 到 6,从星期日算起

string cur_time;
cur_time = string(dtime).substr(11, 8);

// 如果是周六周日,不执行
if (cur_wday == 0 || cur_wday == 6)
{
continue;
}

if (cur_time == "08:00:00")
{
system("start .\\Control.exe ");
cout << dtime << ": " << "启动 Control.exe 成功!" << endl;
}

if (cur_time == "09:00:00")
{
system("start .\\GetData.exe");
cout << dtime << ": " << "启动 GetData.exe 成功!" << endl;
}

if (cur_time == "16:00:00")
{
system("taskkill /F /IM GetData.exe /fi \"pid gt 0\""); // pid gt 0一定要有,不然关不掉
cout << dtime << ": " << "关闭 GetData.exe" << endl;
}

// 输出当前时间
printf("当前时间: %s ", dtime);
Sleep(1000);
printf("\r");
}
return 0;
}

参考资料