Create scheduled task programmatically without using management portal "Task Scheduler Wizard"
Is it possible to create a scheduled task programmatically without using the management portal "Task Scheduler Wizard"?
Once created the scheduled task would then be editable in the Wizard as normal for other users.
Thanks,
Conor
Yes, it's possible. You can use %SYS.Task for a Task API. Its methods and properties are well documented in its superclass %SYS.TaskSuper.
Thanks, I'll have a look
Yes, it's possible. For this you need to create class of the task. I used it to create server-monitoring sheduled task, that send me eamil. For example, i have class, that contains parameters of futured monitoring tasks (like task-name, period, timestart, timefinish, activity, description and so on), and contain method to create task:
{
#define crlf $c(13,10)
#define quote $C(34)
s err = ""
try {
s className = ..#taskPath_"."_##this.Name
i ##class(%ClassDefinition).%ExistsId(className){
s ObjClass = ##class(%Dictionary.ClassDefinition).%OpenId(className) ; Если такая задача есть - открываем и чистим
d ObjClass.Parameters.Clear(),ObjClass.Properties.Clear(),ObjClass.Methods.Clear()
}
else {
s ObjClass = ##class(%Dictionary.ClassDefinition).%New(className) ; иначе создаем новую
}
s ObjClass.Super = "%SYS.Task.Definition" s Param = ##class(%Dictionary.ParameterDefinition).%New(ObjClass.Name_":TaskName") ; Параметр: имя задачи
s Param.Default = ##this.Name
s Param.Description = "Имя задачи"
d ObjClass.Parameters.Insert(Param) s Prop = ##class(%Dictionary.PropertyDefinition).%New(ObjClass.Name_":Active") ; Свойство: активность
s Prop.Type ="%Boolean"
s Prop.Description = "Флаг активности задачи"
s Prop.Required = 1
d ObjClass.Properties.Insert(Prop) s Prop = ##class(%Dictionary.PropertyDefinition).%New(ObjClass.Name_":Email") ; Свойство: Почтовые адреса для рассылки
s Prop.Type = "%String"
s Prop.Description = "Почтовые адреса для рассылки"
d Prop.Parameters.SetAt(200,"MAXLEN")
d ObjClass.Properties.Insert(Prop)
s Prop = ##class(%Dictionary.PropertyDefinition).%New(ObjClass.Name_":MethodName") ; Свойство: Метод для запуска
s Prop.Type = "%String"
s Prop.Description = "Метод Cache из класса для запуска"
d ObjClass.Properties.Insert(Prop) s Prop = ##class(%Dictionary.PropertyDefinition).%New(ObjClass.Name_":ClassName") ; Свойство: Класс Cache с методом для запуска
s Prop.Type = "%String"
s Prop.Description = "Класс Cache с методом для запуска"
d ObjClass.Properties.Insert(Prop) s Prop = ##class(%Dictionary.PropertyDefinition).%New(ObjClass.Name_":Params") ; Свойство: Параметры запускаемого метода
s Prop.Type = "%String"
s Prop.Description = "Параметры запускаемого метода"
d ObjClass.Properties.Insert(Prop) s method = ##class(%Dictionary.MethodDefinition).%New(className_":OnTask") ; Метод. Основной метод задачи
s method.Name = "OnTask"
s method.ReturnType = "%Status"
s code = ##class(%Stream.TmpCharacter).%New()
d code.Rewind()
d code.Write(" #define quote $C(34)"_$$$crlf)
d code.Write(" q:'..Active $$$OK"_$$$crlf)
d code.Write(" s st=$$$OK"_$$$crlf)
d code.Write(" try {"_$$$crlf)
d code.Write(" s err="""""_$$$crlf)
d code.Write(" s msg="""""_$$$crlf)
d code.Write(" ;формирование параметров выполнения метода:_____"_$$$crlf)
d code.Write(" s jstring=""{"""_$$$crlf)
d code.Write(" for i=1:1:$l(..Params,""~"") {"_$$$crlf)
d code.Write(" s buf=$p(..Params,""~"",i)"_$$$crlf)
d code.Write(" i i<$l(..Params,""~""){"_$$$crlf)
d code.Write(" s:buf'="""" jstring=jstring_$$$quote_($p(buf,""="",1))_$$$quote_"":""_$p(buf,""="",2)_"","" "_$$$crlf)
d code.Write(" }else{"_$$$crlf)
d code.Write(" s:buf'="""" jstring=jstring_$$$quote_($p(buf,""="",1))_$$$quote_"":""_$p(buf,""="",2)"_$$$crlf)
d code.Write(" }"_$$$crlf)
d code.Write(" }"_$$$crlf)
d code.Write(" s jstring=jstring_""}"""_$$$crlf)
d code.Write(" s in={}.%FromJSON(jstring)"_$$$crlf)
d code.Write(" s out={""error"":"""",""message"":"""",""subject"":""""}"_$$$crlf)
d code.Write(" d $CLASSMETHOD(..ClassName,..MethodName,.in,.out)"_$$$crlf)
d code.Write(" ;отправка письма:________________________________"_$$$crlf)
d code.Write(" i ..Email'="""" {"_$$$crlf)
d code.Write(" s mailIn={}"_$$$crlf)
d code.Write(" s mailIn.subject= """""_$$$crlf)
d code.Write(" s mailIn.to = ..Email"_$$$crlf)
d code.Write(" s mailIn.message= ""<h3>Статус выполнения задачи по расписанию ""_..#TaskName_"" : ""_$Case(out.error,"""":""Выполнено"",$$$OK:""Выполнено"",:""Выполнено с ошибками"")_"" </h3>"""_$$$crlf)
d code.Write(" s:(out.message'="""") mailIn.message=mailIn.message_""Результат: </br>""_out.message"_$$$crlf)
d code.Write(" s mailIn.message= mailIn.message_""Класс: ""_..ClassName_"", метод: ""_..MethodName_""</br>"""_$$$crlf)
d code.Write(" s:((out.error'="""")&(out.error'=$$$OK)) mailIn.message=mailIn.message_""Ошибка: ""_out.error_""</br>"""_$$$crlf)
d code.Write(" s:(out.subject'="""") mailIn.subject=out.subject"_$$$crlf)
d code.Write(" s:(out.from'="""") mailIn.from=out.from"_$$$crlf)
d code.Write(" s mailIn.isHTML = 1"_$$$crlf)
d code.Write(" s mailIn.attach = """""_$$$crlf)
d code.Write(" d ##class(Lib.Util.Email).Send(.mailIn,.out)"_$$$crlf)
d code.Write(" }"_$$$crlf)
d code.Write(" } // try"_$$$crlf)
d code.Write(" catch {s err=$ze}"_$$$crlf)
d code.Write(" if err'="""" {s st=$$$ERROR($$$GeneralError,err)}"_$$$crlf)
d code.Write(" q st"_$$$crlf)
s method.Implementation=code
d ObjClass.Methods.Insert(method) d ObjClass.%Save() s status = $system.OBJ.Compile(className,"UBR-D",.errlog,1)
s:$System.Status.IsError(status) err=$SYSTEM.Status.GetErrorText(status)
}
catch exp {
s err = ..ErrorDetect(.exp)
}
s out.error = err
q
}
Thanks
Alexandr,
why did you prefer generating the task class instead of just writing it in some text editor? Looks like overkill for such a small task.
Because it is a part of admin-panel of our web-application, that could generate any task.
I guessed it was not ad hoc writing ;)
Even with some universal tool like your admin panel, you can generate only those tasks which code you preliminary prepared with d code.Write() commands. The reasons of preparing code this way in this very case are still unclear for me: I can hardly imagine extra functionality you can add to the traditional approach demonstrated in Evgeny's reply.
Another example which I use in Covid-19 online dashboard to update the data:
But you need to have the class, Covid19.UpdateTask in this case:
HTH
One question,
If my %SYS.Task.Definition class needs a parameter, how to add it in the %SYS.Task definition?
this is my task
Regards,
Francisco Lopez
I've found the solution.
ClassMethod CreateTask() As %Status { Set task=##class(%SYS.Task).%New() Set task.Name = "Check laboratory process" Set task.NameSpace=$Namespace Set task.TimePeriod=0 // Daily Set task.TimePeriodEvery=1 // Every 1 day Set task.DailyFrequency=0 // Run once Set taskdef = ##class(MyTasks.LabsTask).%New() Do task.AssignSettings(taskdef) Set task.TaskClass=$classname(taskdef) Set task.Settings=$lb("Laboratory","LABS1") Set st = task.%Save() Return:$$$ISERR(st) st Return ##class(%SYS.Task).RunNow(task.%Id()) }
BTW, this project could help you schedule a task programmatically via cron expression.
Social networks
InterSystems resources
Log in or sign up
Log in or create a new account to continue
Log in or sign up
Log in or create a new account to continue
Log in or sign up
Log in or create a new account to continue