@@ -71,6 +71,10 @@ bool initial_configure()
71
71
* 键盘码参考这里 https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
72
72
* 大小写无关,顺序无关,如果多个非修饰符的按钮,最后的那个按钮会起作用。
73
73
* 热键注册失败,一般是与系统中存在的冲突了,换一个再试
74
+ * 8. crontab语法,秒 分 时 日期 月份 星期,比常规crontab多了个秒钟,具体语法使用搜索引擎
75
+ * 例子 0 0/10 * * * * 每10分钟运行一次
76
+ * 例子 0 1,11,21 * * * 每小时的1分 11分 21分运行一次
77
+ * 例子 0 2/10 12-14 * * * 12点到14点,每小时从2分钟开始每10分钟运行一次
74
78
*/
75
79
"configs": [
76
80
{
@@ -118,6 +122,14 @@ bool initial_configure()
118
122
"use_builtin_console": false,
119
123
"is_gui": false,
120
124
"enabled": false,
125
+ // 可选
126
+ "crontab_config": { // crontab配置
127
+ "crontab": "8 */2 15-16 29 2 *", // crontab语法具体参考上面8
128
+ "method": "start", // 支持的有 start restart stop
129
+ "count": 0, // 0 表示infinite不只限制,大于0的整数,表示运行多少次就不运行了
130
+ // 可选
131
+ "enabled": true,
132
+ },
121
133
},
122
134
{
123
135
"name": "cmd例子3",
@@ -199,6 +211,7 @@ bool initial_configure()
199
211
* 6. set "enable_cache": true to enable cache.
200
212
* 7. alt win shit ctrl 0-9 A-Z, seperated by space or +. You can also use "ALT+WIN+CTRL+0x20"
201
213
* https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
214
+ * 8. crontab is from https://github.com/staticlibs/ccronexpr
202
215
*/
203
216
"configs": [
204
217
{
@@ -244,6 +257,14 @@ bool initial_configure()
244
257
"use_builtin_console": false,
245
258
"is_gui": false,
246
259
"enabled": false,
260
+ // Optional
261
+ "crontab_config": {
262
+ "crontab": "8 */2 15-16 29 2 *",
263
+ "method": "start", // start restart stop
264
+ "count": 0, // times to run, 0 infinite
265
+ // Optional
266
+ "enabled": true,
267
+ },
247
268
},
248
269
{
249
270
"name": "cmd example 3",
@@ -627,6 +648,49 @@ int configure_reader(std::string& out)
627
648
{ " restart" , iStringType, true , lambda_config_hotkey, lambda_config_hotkey_items_idx },
628
649
{ " elevate" , iStringType, true , lambda_config_hotkey, lambda_config_hotkey_items_idx },
629
650
};
651
+ const RapidJsonObjectChecker config_crontab_items[] = {
652
+ { " enabled" , iBoolType,true ,nullptr ,[&allocator](Value& val, PCSTR name)->bool {
653
+ if (!val.HasMember (name))
654
+ {
655
+ val.AddMember (Value{}.SetString (name, allocator), true , allocator);
656
+ }
657
+ return true ;
658
+ } },
659
+ { " crontab" , iStringType,false ,[&allocator](Value& val, PCSTR name)->bool {
660
+ if (!val[" enabled" ].GetBool ())return true ;
661
+ if (val.HasMember (" cron_expr" ))return false ;
662
+ const char * crontab = val[name].GetString ();
663
+ if (crontab[0 ] == 0 )return false ;
664
+ cron_expr expr;
665
+ ZeroMemory (&expr, sizeof (expr)); // if not do this, always get incorrect result
666
+ const char * err = NULL ;
667
+ cron_parse_expr (crontab, &expr, &err);
668
+ if (err)
669
+ {
670
+ LOGMESSAGE (L" cron_parse_expr failed! %S\n " ,err);
671
+ return false ;
672
+ }
673
+ Value v;
674
+ v.SetString (reinterpret_cast <const char *>(&expr), sizeof (cron_expr), allocator);
675
+ val.AddMember (" cron_expr" , v, allocator);
676
+ return true ;
677
+ } },
678
+ { " method" , iStringType,false ,[](Value& val, PCSTR name)->bool {
679
+ if (!val[" enabled" ].GetBool ())return true ;
680
+ const char * method = val[name].GetString ();
681
+ if (0 == StrCmpA (method," restart" ) || 0 == StrCmpA (method, " start" ) || 0 == StrCmpA (method, " stop" ))
682
+ {
683
+ return true ;
684
+ }
685
+ return false ;
686
+ } },
687
+ { " count" , iIntType, false , [](Value& val, PCSTR name)->bool {
688
+ if (!val[" enabled" ].GetBool ())return true ;
689
+ int count = val[name].GetInt ();
690
+ if (count < 0 )return false ;
691
+ return true ;
692
+ } },
693
+ };
630
694
631
695
// type check for items in configs
632
696
const RapidJsonObjectChecker config_items[] = {
@@ -692,6 +756,16 @@ int configure_reader(std::string& out)
692
756
}
693
757
return true ;
694
758
}},
759
+ { " crontab_config" , iObjectType, true , [&config_crontab_items](Value& val, PCSTR name)->bool {
760
+ return check_rapidjson_object (
761
+ val[name],
762
+ config_crontab_items,
763
+ ARRAYSIZE (config_crontab_items),
764
+ L" : One of configs section crontab setting error!" ,
765
+ (utf8_to_wstring (name) + L" crontab_config Type Error" ).c_str (),
766
+ (utf8_to_wstring (val[" name" ].GetString ()) + L" config section" ).c_str (),
767
+ false );
768
+ } },
695
769
};
696
770
PCSTR const global_menu[][2 ] = {
697
771
// with hotkey
@@ -1031,6 +1105,8 @@ int configure_reader(std::string& out)
1031
1105
}
1032
1106
return ret;
1033
1107
}, lambda_menu_check },
1108
+ // { "enable_crontab", iBoolType, true, nullptr },
1109
+ // { "crontabs", iArrayType, true, nullptr }
1034
1110
};
1035
1111
1036
1112
if (false == check_rapidjson_object (
@@ -1718,6 +1794,85 @@ void update_hwnd_all()
1718
1794
}
1719
1795
}
1720
1796
1797
+ void handle_crontab (int idx)
1798
+ {
1799
+ auto & config_i_ref = (*global_configs_pointer)[idx]; // ["crontab_config"]
1800
+ if (json_object_has_member (config_i_ref, " crontab_config" ))
1801
+ {
1802
+ auto & crontab_ref = config_i_ref[" crontab_config" ];
1803
+ extern HWND hWnd;
1804
+ KillTimer (hWnd, VM_TIMER_BASE + idx);
1805
+
1806
+ std::string crontab_method = crontab_ref[" method" ];
1807
+ extern HANDLE ghJob;
1808
+ bool enable_cache_backup = enable_cache;
1809
+ enable_cache = false ;
1810
+ if (crontab_method == " start" )
1811
+ {
1812
+ bool to_start = true ;
1813
+
1814
+ if (config_i_ref[" running" ])
1815
+ {
1816
+ int64_t handle = config_i_ref[" handle" ];
1817
+ DWORD lpExitCode;
1818
+ BOOL retValue = GetExitCodeProcess (reinterpret_cast <HANDLE>(handle), &lpExitCode);
1819
+ if (retValue != 0 && lpExitCode == STILL_ACTIVE)
1820
+ {
1821
+ to_start = false ;
1822
+ }
1823
+ }
1824
+ if (to_start)
1825
+ {
1826
+ config_i_ref[" enabled" ] = true ;
1827
+ create_process (config_i_ref, ghJob);
1828
+ }
1829
+ }
1830
+ /* else if (crontab_method == "restart")
1831
+ {
1832
+
1833
+ }
1834
+ else if (crontab_method == "stop")*/
1835
+ else
1836
+ {
1837
+ if (config_i_ref[" enabled" ] && config_i_ref[" running" ] && config_i_ref[" en_job" ])
1838
+ {
1839
+ disable_enable_menu (config_i_ref, ghJob);
1840
+ }
1841
+ if (crontab_method == " restart" )
1842
+ {
1843
+ disable_enable_menu (config_i_ref, ghJob);
1844
+ }
1845
+ }
1846
+ enable_cache = enable_cache_backup;
1847
+
1848
+ int crontab_count = crontab_ref[" count" ];
1849
+
1850
+ if (crontab_count != 1 )
1851
+ {
1852
+ cron_expr c;
1853
+ time_t next_t = 0 ;
1854
+ next_t = cron_next (&c, time (NULL )); // return -1 when failed
1855
+ if (next_t > 0 )
1856
+ {
1857
+ next_t *= 1000 ;
1858
+ if (next_t > USER_TIMER_MAXIMUM)next_t = USER_TIMER_MAXIMUM;
1859
+ SetTimer (hWnd, VM_TIMER_BASE + idx, static_cast <UINT>(next_t ), NULL );
1860
+ if (crontab_count > 1 )
1861
+ {
1862
+ crontab_ref[" count" ] = crontab_count - 1 ;
1863
+ }
1864
+ }
1865
+ }
1866
+ }
1867
+ else
1868
+ {
1869
+ msg_prompt (L" Crontab has no crontab_config! Please report this windows screenshot to author!" ,
1870
+ L" Crontab Error" ,
1871
+ MB_OK
1872
+ );
1873
+ }
1874
+ }
1875
+
1721
1876
void start_all (HANDLE ghJob, bool force)
1722
1877
{
1723
1878
// int cmd_idx = 0;
@@ -1737,6 +1892,26 @@ void start_all(HANDLE ghJob, bool force)
1737
1892
i[" enabled" ] = true ;
1738
1893
}
1739
1894
}
1895
+ else
1896
+ {
1897
+ if (json_object_has_member (i, " crontab_config" ) && i[" crontab_config" ][" count" ][" enabled" ])
1898
+ {
1899
+ cron_expr c;
1900
+ if (nullptr != get_cron_expr (i, c))
1901
+ {
1902
+ // int cront_cnt = i["crontab_config"]["count"];
1903
+ extern HWND hWnd;
1904
+ time_t next_t = 0 ;
1905
+ next_t = cron_next (&c, time (NULL )); // return -1 when failed
1906
+ if (next_t > 0 )
1907
+ {
1908
+ next_t *= 1000 ;
1909
+ if (next_t > USER_TIMER_MAXIMUM)next_t = USER_TIMER_MAXIMUM;
1910
+ SetTimer (hWnd, VM_TIMER_BASE + cache_config_cursor, static_cast <UINT>(next_t ), NULL );
1911
+ }
1912
+ }
1913
+ }
1914
+ }
1740
1915
bool is_enabled = i[" enabled" ];
1741
1916
if (is_enabled)
1742
1917
{
@@ -2350,7 +2525,8 @@ void create_process(
2350
2525
void disable_enable_menu (nlohmann::json& jsp, HANDLE ghJob, bool runas_admin)
2351
2526
{
2352
2527
bool is_enabled = jsp[" enabled" ];
2353
- if (false == runas_admin && is_enabled) {
2528
+ if (false == runas_admin && is_enabled)
2529
+ {
2354
2530
bool is_running = jsp[" running" ];
2355
2531
if (is_running)
2356
2532
{
0 commit comments