一个windows计划任务库demo
后面想法是要做成类似sql的可以增删改查的语法。
```rust
use std::ffi::{OsStr, OsString}; use std::path::Path;
use comedy::HResult; use log::warn;
use taskschd::oleutils::{BString,trytobstring}; use taskschd::taskschd::{hrisnotfound, TaskService};
fn foldername() -> Result
fn register(name: &OsStr) -> Result<(), failure::Error>{
let name = try_to_bstring!(name)?;
let folder_name = folder_name()?;
let mut service = TaskService::connect_local()?;
// Get or create the folder
let mut folder = service.get_folder(&folder_name).or_else(|e| {
if hr_is_not_found(&e) {
service
.get_root_folder()
.and_then(|mut root| root.create_folder(&folder_name))
} else {
Err(e)
}
})?;
let start_time = folder
.get_task(&name)
.ok()
.and_then(|mut task| task.get_definition().ok())
.and_then(|mut def| def.get_daily_triggers().ok())
.and_then(|mut triggers| {
// Currently we are only using 1 daily trigger.
triggers
.get_mut(0)
.and_then(|trigger| trigger.get_StartBoundary().ok())
});
folder.delete_task(&name).unwrap_or_else(|e| {
// Don't even warn if the task didn't exist.
if !hr_is_not_found(&e) {
warn!("delete task failed: {}", e);
}
});
let mut task_def = service.new_task_definition()?;
{
let mut task_args = vec![OsString::from(cmd::DO_TASK)];
task_args.extend_from_slice(args);
let mut action = task_def.add_exec_action()?;
action.put_Path(exe)?;
action.put_Arguments(task_args.as_slice())?;
// TODO working directory?
}
{
let mut settings = task_def.get_settings()?;
settings.put_DisallowStartIfOnBatteries(false)?;
settings.put_StopIfGoingOnBatteries(false)?;
settings.put_StartWhenAvailable(true)?;
settings.put_ExecutionTimeLimit(chrono::Duration::minutes(5))?;
}
{
let mut info = task_def.get_registration_info()?;
info.put_Author(&try_to_bstring!("author")?)?;
info.put_Description(&try_to_bstring!("task test")?)?;
}
// A daily trigger starting 5 minutes ago.
{
let mut daily_trigger = task_def.add_daily_trigger()?;
if let Some(ref start_time) = start_time {
daily_trigger.put_StartBoundary_BString(start_time)?;
} else {
daily_trigger.put_StartBoundary(chrono::Utc::now() - chrono::Duration::minutes(5))?;
}
daily_trigger.put_DaysInterval(1)?;
// TODO: 12-hourly trigger? logon trigger?
}
let service_account = Some(try_to_bstring!("NT AUTHORITY\\LocalService")?);
let mut registered_task = task_def.create(&mut folder, &name, service_account.as_ref())?;
let sddl = try_to_bstring!(concat!(
"D:(", // DACL
"A;", // ace_type = Allow
";", // ace_flags = none
"GRGX;", // rights = Generic Read, Generic Execute
";;", // object_guid, inherit_object_guid = none
"BU)" // account_sid = Built-in users
))?;
registered_task.set_sd(&sddl)?;
}
Ok(())
}
fn unregister(name: &OsStr) -> Result<(), failure::Error> { let name = trytobstring!(name)?; let foldername = foldername()?;
let mut service = TaskService::connect_local()?;
let maybe_folder = service.get_folder(&folder_name);
let mut folder = match maybe_folder {
Err(e) => {
if hr_is_not_found(&e) {
// Just warn and exit if the folder didn't exist.
warn!("failed to unregister: task folder didn't exist");
return Ok(());
} else {
// Other errors are fatal.
return Err(e.into());
}
}
Ok(folder) => folder,
};
folder.delete_task(&name).or_else(|e| {
if hr_is_not_found(&e) {
// Only warn if the task didn't exist, still try to remove the folder below.
warn!("failed to unregister task that didn't exist");
Ok(())
} else {
// Other errors are fatal.
Err(e)
}
})?;
let count = folder.get_task_count(true).unwrap_or_else(|e| {
warn!("failed getting task count: {}", e);
1
});
if count == 0 {
let result = service
.get_root_folder()
.and_then(|mut root| root.delete_folder(&folder_name));
if let Err(e) = result {
warn!("failed deleting folder: {}", e);
}
}
Ok(())
}
fn runondemand(name: &OsStr) -> Result<(), failure::Error> { let name = trytobstring!(name)?; let foldername = foldername()?;
let mut service = TaskService::connect_local()?;
let task = service.get_folder(&folder_name)?.get_task(&name)?;
task.run()?;
Ok(())
}
```