Jump to content

Would you like to see a brushed up Task Scheduler UDF (inlcuding help files, examples ...)?  

41 members have voted

  1. 1. Would you like to see such a brushed up UDF?

    • Yes
    • Don't mind
    • Maybe later
      0
    • No
      0


Recommended Posts

Posted

IIRC #RequireAdmin restarts the script with elevated permissions and hence gets a new PID.

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted (edited)

I did the test, with this one liner:

MsgBox(0, "", IsAdmin())

Compiled code to exe , run from desktop.

I get always 1

Someone can explain why?

NOTE:
There was no request for confirmation of the program execution to increase its system privileges.

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted

Seems your user has full administrator privileges (according to the help file).

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted
  On 10/17/2021 at 12:13 PM, water said:

IIRC #RequireAdmin restarts the script with elevated permissions and hence gets a new PID.

Expand  

Do you mean that the list in TaskScheduler has a parent PID and the result @AutoItPID is a child PID (descendant of the former)?
Or the other way around?

 

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted

Don't know- I just grab the information Windows provides. Details can be found here: https://docs.microsoft.com/en-us/windows/win32/taskschd/runningtask-enginepid
Maybe the function should use the Int function on the EnginePID property as described in the MS docu?
Couly you please modify the function accordingly and post the result?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted
  On 10/17/2021 at 2:54 PM, water said:

Couly you please modify the function accordingly and post the result?

Expand  


Sure.

But next few days.
Today I had other things to do.

 

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted (edited)

I found some spare time to dig into this problem.
I had a good feeling when I wrote

  On 10/17/2021 at 1:07 PM, mLipok said:

Do you mean that the list in TaskScheduler has a parent PID and the result @AutoItPID is a child PID (descendant of the former)?

Expand  

I just do this test:

  Quote

--> IsAdmin()=1
--> @AutoItPID=11404
--> _WinAPI_GetParentProcess()=12272
--> ### Running Task List - START
--> C:\Users\Administrator\Desktop\ML_Downloader.exe|12272|{469191DA-DE86-458D-BB60-4021B2B8C1A6}|ML_Downloader|\MICHAELO\ML_Downloader|4
Wininet Cache task object|10492|{46C9DB83-0119-436D-BD44-55E10E945600}|CacheTask|\Microsoft\Windows\Wininet\CacheTask|4
--> ### Running Task List - END
 

Expand  

 

But in a few instances, I was compliant without getting the parent PID.

So finally I did small modification to my _TS_IsRunFromTaskScheduler()

Global Const $TASK_LIST_0_CurrentAction = 0
Global Const $TASK_LIST_1_EnginePID = 1
Global Const $TASK_LIST_2_InstanceGUID = 2
Global Const $TASK_LIST_3_Name = 3
Global Const $TASK_LIST_4_Path = 4
Global Const $TASK_LIST_5_State = 5
....
....
....
; #FUNCTION# ====================================================================================================================
; Name ..........: _TS_IsRunFromTaskScheduler
; Description ...: check if process is run form Task Scheduler
; Syntax ........: _TS_IsRunFromTaskScheduler($oService[, $iPID = @AutoItPID[, $bCheckPath = False]])
; Parameters ....: $oService            - Task Scheduler Service object as returned by _TS_Open
;                  $iPID                - [optional] an integer value. Default is @AutoItPID (current process).
;                  $bCheckPath          - [optional] a boolean value. Default is False. Determines whether to check the path as well, not just the PID.
; Return values .: True / False
; Author ........: mLipok
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _TS_IsRunFromTaskScheduler($oService, $iPID = @AutoItPID, $bCheckPath = False)
    Local $aRunningTasks = _TS_RunningTaskList($oService, 1)
    Local $iParentPID = _WinAPI_GetParentProcess($iPID)
    Local $bTestingPath = False
    For $IDX_Task = 0 To UBound($aRunningTasks) - 1
        $bTestingPath = ($bCheckPath = False) Or ($aRunningTasks[$IDX_Task][$TASK_LIST_0_CurrentAction] = @ScriptFullPath)
        If $aRunningTasks[$IDX_Task][$TASK_LIST_1_EnginePID] = $iPID And $bTestingPath Then Return True
        If $aRunningTasks[$IDX_Task][$TASK_LIST_1_EnginePID] = $iParentPID And $bTestingPath Then Return True
    Next
    Return False
EndFunc   ;==>_TS_IsRunFromTaskScheduler
....
....
....


And this solve my problem.

@water What you currently think about: _TS_IsRunFromTaskScheduler() 
Is it worth to add to the _TS_* UDF in this current form ?

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted (edited)

 

When I try and change the _TS_Wrapper_TaskCreate Example 2  file to add in logon details I'm getting error message.

 The line I modified _TS_Wrapper_TaskRegister($oService, "Test", "Test-DateTime-Daily", $oTaskDefinition, Default, Default, $TASK_LOGON_INTERACTIVE_TOKEN)

Changed it to _TS_Wrapper_TaskRegister($oService, "Test", "Test-DateTime-Daily", $oTaskDefinition, "Domain\User Name", "user password", $TASK_LOGON_SERVICE_ACCOUNT)

 

What am I missing ?

_; *****************************************************************************
; Example 2
; Create task "Test-DateTime-Daily" in folder "\Test" to run Notepad every second day in
; the boundary defined by $sStartDateTime and $sEndDateTime
; *****************************************************************************
$oTaskDefinition = _TS_Wrapper_TaskCreate($oService, "Test-Description", "Test-Doku" & @CRLF & "Line 2")
If @error Then Exit MsgBox($MB_ICONERROR, "_TS_Wrapper_TaskCreate", "_TS_Wrapper_TaskCreate returned @error=" & @error & ", @extended=" & @extended & @CRLF & @CRLF & _TS_ErrorText(@error))
_TS_Wrapper_PrincipalSet($oTaskDefinition, $TASK_LOGON_INTERACTIVE_TOKEN)
If @error Then Exit MsgBox($MB_ICONERROR, "_TS_Wrapper_TaskCreate", "_TS_Wrapper_PrincipalSet returned @error=" & @error & ", @extended=" & @extended & @CRLF & @CRLF & _TS_ErrorText(@error))
_TS_Wrapper_TriggerDateTime($oTaskDefinition, $TASK_TRIGGER_DAILY, 0, 2, $sStartDateTime, $sEndDateTime)
If @error Then Exit MsgBox($MB_ICONERROR, "_TS_Wrapper_TaskCreate", "DateTime returned @error=" & @error & ", @extended=" & @extended & @CRLF & @CRLF & _TS_ErrorText(@error))
_TS_Wrapper_ActionCreate($oTaskDefinition, "Notepad")
If @error Then Exit MsgBox($MB_ICONERROR, "_TS_Wrapper_TaskCreate", "_TS_Wrapper_ActionCreate returned @error=" & @error & ", @extended=" & @extended & @CRLF & @CRLF & _TS_ErrorText(@error))


;~ _TS_Wrapper_TaskRegister($oService, "Test", "Test-DateTime-Daily", $oTaskDefinition, Default, Default, $TASK_LOGON_INTERACTIVE_TOKEN)

;~         _TS_TaskRegister($oService, $sFolder, $sName, $oTaskDefinition, $sUserId = Default, $sPassword = Default, $iLogonType = Default, $iCreateFlag = Default)
_TS_Wrapper_TaskRegister($oService, "Test", "Test-DateTime-Daily", $oTaskDefinition, "Domain\User Name", "user password", $TASK_LOGON_SERVICE_ACCOUNT)

If @error Then Exit MsgBox($MB_ICONERROR, "_TS_Wrapper_TaskCreate", "_TS_Wrapper_TaskRegister returned @error=" & @error & ", @extended=" & @extended & @CRLF & @CRLF & _TS_ErrorText(@error))
MsgBox($MB_ICONINFORMATION, "_TS_Wrapper_TaskCreate", "DateTime-Daily task successfully created!")

 

image.png.3b4f83f1b9d2b78bc17b8e0283c27893.png

Edited by HighlanderSword
Posted
  On 10/17/2021 at 9:22 PM, mLipok said:

So finally I did small modification to my _TS_IsRunFromTaskScheduler()

Expand  

Does _WinAPI_GetParentProcess work on a remote computer as well? With _TS_Open you can connect to the local or a remote computer and run all commands on the connected computer.
I guess that _WinAPI_GetParentProcess only works on the local computer?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

@HighlanderSword can you set _TS_Wrapper_PrincipalSet to the same LogonType or drop the statement completely?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted (edited)
  On 10/18/2021 at 7:53 AM, water said:

Does _WinAPI_GetParentProcess work on a remote computer as well? With _TS_Open you can connect to the local or a remote computer and run all commands on the connected computer.
I guess that _WinAPI_GetParentProcess only works on the local computer?

Expand  

The main idea is to check if process (an exe file compiled by Au2exe) which is run by TaskScheduler (both locally).
So the exe which use this function should be run on the same machine on which TaskScheduler run the task.

As I understand you are asking if we can remontly check if desired remote process is run by remote TaskScheduler.
Yes it is possible but firstly you should deliver to local AutoIt EXE, information about remote AutoIt EXE PID and ParentPID.

Because:
_TS_RunningTaskList() as I understand it, always return list of task from TaskScheduler you are connected to.
If you are connected to Remote TaskScheduler  then _TS_RunningTaskList() returns Remote PID's
If you run your AutoIt process from local machine you then @AutoItPID and _WinAPI_GetParentProcess() will return to you information from local machine.
For these reason you should be able to transfer (somehow) 
 @AutoItPID and _WinAPI_GetParentProcess()  from Remote to Local program.

Edit:

I hope that I have described everything well and it is clear.
Because I still have problems to correctly convey complex thoughts in English.

@mLipok

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted

I understand what you mean.

On the other hand I'm a bit hesitant to add a 1500-lines UDF to the Task Scheduler UDF to implement a new (up to now rarely needed) function.
I searched the Web but couldn't find another way to determine if an Exe was started from the Task Scheduler. Most users suggested to pass a parameter to the Exe when started from Task Scheduler.
At the moment I also tend to this solution.
But I will do some more investigation.

My UDFs and Tutorials:

  Reveal hidden contents

 

  • 11 months later...
Posted

Hi all,

I'm having issues reading tasks from task scheduler. I have the script utilizing #RequireAdmin but it's missing 17+ tasks in "\" alone. I've tried calling _TS_Open(Default, "SYSTEM") to try to resolve the issue but that does not seem to fix it. What am I doing wrong?

TIA!

##RequireAdmin
#include <array.au3>

#include ".\Includes\TaskScheduler.au3"

Local $hTask 
Local $aArray

$hTask = _TS_Open()
; $hTask = _TS_Open(Default, "SYSTEM")
$aArray = _TS_TaskList($hTask)
If @error Then MsgBox(0, @error, @extended)
_ArrayDisplay($aArray)

 

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Posted

Please have a look at the Help file.
You have to set parameter $iShowHidden to get all hidden tasks.

My UDFs and Tutorials:

  Reveal hidden contents

 

  • 1 month later...
Posted (edited)

Here is my test script:

#include "TaskScheduler.au3"

Local $oService = _TS_Open()

if _TS_TaskExists($oService,"\Test\starttime") Then
    _TS_TaskDelete($oService,"\Test\starttime")
EndIf

Local $startTime = _DateAdd("n",1,_NowCalc())
$startTime = StringReplace($startTime,"/","-")
 $startTime = StringReplace($startTime," ","T")
Local $endTime = _DateAdd("n",2,_NowCalc())
$endTime = StringReplace($endTime,"/","-")
$endTime = StringReplace($endTime," ","T")

Local $oTaskDefinition = _TS_Wrapper_TaskCreate($oService, "", "")
if  $oTaskDefinition=0 then MsgBox(1,11,"bad")
Local $r = _TS_Wrapper_PrincipalSet($oTaskDefinition,$TASK_LOGON_INTERACTIVE_TOKEN)
if $r=0 then msgbox(1,13,"bad")
$r = _TS_Wrapper_TriggerDateTime($oTaskDefinition,$TASK_TRIGGER_TIME,0, 0, $startTime,$endTime)
if $r=0 then msgbox(1,15,"bad")
$r = _TS_Wrapper_ActionCreate($oTaskDefinition,"Notepad")
if $r=0 then msgbox(1,17,"bad")
if _TS_FolderExists($oService,"\Test")=0 Then
    _TS_FolderCreate($oService,"\Test")
EndIf
$r = _TS_Wrapper_TaskRegister($oService, "\Test","starttime",$oTaskDefinition, Default, Default,$TASK_LOGON_INTERACTIVE_TOKEN)
if $r=0 then msgbox(1,22,"bad")

Local $ar = ["Settings|DeleteExpiredTaskAfter|P20S"]
$r = _TS_TaskPropertiesSet($oTaskDefinition,$ar)
if $r=0 Then MsgBox(1,"DeleteExpiredTaskAfter",@error)
 MsgBox(1,30,"$startTime " & $startTime & " $endTime " & $endTime)
_TS_Close($oService)
SetError

It runs OK except the task is not deleted when it has run. Why not? e.g. \Test\starttime still shows in schtasks /query.

When I run schtasks /query /xml, for \Test\starttime the Settings do not show DeleteExpiredTaskAfter.

I have "Settings" not "SETTINGS" (despite the Description) because as I read the code I see "Settings". (I have also tried "SETTINGS")

I have just realized that P20S should be PT20S . Still no luck!

Edited by c.haslam
P20S => PT20S
  Reveal hidden contents

 

Posted

What are the boundaries of your task?
MS states: "the amount of time that the Task Scheduler will wait before deleting the task after it expires." and "A task expires after the end boundary has been exceeded for all triggers associated with the task. The end boundary for a trigger is specified by the EndBoundary property inherited by all trigger objects."

If I'm not wrong DeleteExpiredTaskAfter in your case should be "PT20S".

SETTINGS or Settings or SeTTiNgS are all the same as AutoIt is not case sensitive.

To check for errors I do not suggest to check the returncode. It is more save to check @error <> 0.

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

I have changed my code to:

#include "TaskScheduler.au3"

Local $oService = _TS_Open()

_TS_ErrorNotify(2)  ; to MsgBox

if _TS_TaskExists($oService,"\Test\starttime") Then
    _TS_TaskDelete($oService,"\Test\starttime")
EndIf

Local $startTime = _DateAdd("n",1,_NowCalc())
$startTime = StringReplace($startTime,"/","-")
 $startTime = StringReplace($startTime," ","T")
Local $endTime = _DateAdd("n",2,_NowCalc())
$endTime = StringReplace($endTime,"/","-")
$endTime = StringReplace($endTime," ","T")

Local $oTaskDefinition = _TS_Wrapper_TaskCreate($oService, "", "")
if  $oTaskDefinition=0 then MsgBox(1,11,"bad")
_TS_Wrapper_PrincipalSet($oTaskDefinition,$TASK_LOGON_INTERACTIVE_TOKEN)
if @error<>0 then msgbox(1,13,"bad")
_TS_Wrapper_TriggerDateTime($oTaskDefinition,$TASK_TRIGGER_TIME,0, 0, $startTime,$endTime)
if @error<>0 then msgbox(1,15,"bad")
_TS_Wrapper_ActionCreate($oTaskDefinition,"Notepad")
if @error<>0 then msgbox(1,17,"bad")
if _TS_FolderExists($oService,"\Test")=0 Then
    _TS_FolderCreate($oService,"\Test")
EndIf
_TS_Wrapper_TaskRegister($oService, "\Test","starttime",$oTaskDefinition, Default, Default,$TASK_LOGON_INTERACTIVE_TOKEN)
if @error<>0 then msgbox(1,22,"bad")

Local $ar = ["Settings|DeleteExpiredTaskAfter|PT20S"]
_TS_TaskPropertiesSet($oTaskDefinition,$ar)
if @error<>0 Then MsgBox(1,"DeleteExpiredTaskAfter",@error)
 MsgBox(1,30,"$startTime " & $startTime & " $endTime " & $endTime)

 Local $ar = _TS_TaskValidate($oService,"\Test\starttime")
_TS_Close($oService)

I see this:

image.png.65c18b582b218201cdf75813cb2ad2af.png

I see similar for lines 1198, 2017 and 2022. None of the msgBoxes show.

NotePad opens as expected. I then close it.

I do now have PT20S

  Reveal hidden contents

 

Posted

Its is at least 10 minutes since I ran the task. The endtime is set to 2 minutes after _NowCalc().

  Reveal hidden contents

 

Posted

This bug was easy to locate (hint!).
The sequence of commands was wrong. You first have to do all configuration of the new task and THEN you have to register the task. 
You did the settings AFTER registration - hence they were lost.

Tested with:

#include <TaskScheduler.au3>

Global $oService = _TS_Open()
ConsoleWrite("_TS_Open: @error=" & @error & ", @extended=" & @extended & @CRLF)

_TS_ErrorNotify(2)  ; to MsgBox

If _TS_TaskExists($oService, "\Test\starttime") Then
    _TS_TaskDelete($oService, "\Test\starttime")
    ConsoleWrite("_TS_TaskDelete: @error=" & @error & ", @extended=" & @extended & @CRLF)
EndIf
Global $sStartTime = _DateAdd("n", 1, _NowCalc())
$sStartTime = StringReplace($sStartTime, "/", "-")
$sStartTime = StringReplace($sStartTime, " ", "T")
Global $sEndTime = _DateAdd("n", 2, _NowCalc())
$sEndTime = StringReplace($sEndTime, "/", "-")
$sEndTime = StringReplace($sEndTime, " ", "T")

Global $oTaskDefinition = _TS_Wrapper_TaskCreate($oService, "", "")
ConsoleWrite("_TS_Wrapper_TaskCreate: @error=" & @error & ", @extended=" & @extended & @CRLF)
_TS_Wrapper_PrincipalSet($oTaskDefinition, $TASK_LOGON_INTERACTIVE_TOKEN)
ConsoleWrite("_TS_Wrapper_PrincipalSet: @error=" & @error & ", @extended=" & @extended & @CRLF)
_TS_Wrapper_TriggerDateTime($oTaskDefinition, $TASK_TRIGGER_TIME, 0, 0, $sStartTime, $sEndTime)
ConsoleWrite("_TS_Wrapper_TriggerDateTime: @error=" & @error & ", @extended=" & @extended & @CRLF)
_TS_Wrapper_ActionCreate($oTaskDefinition, "Notepad")
ConsoleWrite("_TS_Wrapper_ActionCreate: @error=" & @error & ", @extended=" & @extended & @CRLF)
If _TS_FolderExists($oService, "\Test") = 0 Then
    _TS_FolderCreate($oService, "\Test")
    ConsoleWrite("_TS_FolderCreate: @error=" & @error & ", @extended=" & @extended & @CRLF)
EndIf
Global $ar = ["Settings|DeleteExpiredTaskAfter|PT20S"]
_TS_TaskPropertiesSet($oTaskDefinition, $ar)
ConsoleWrite("_TS_TaskPropertiesSet: @error=" & @error & ", @extended=" & @extended & @CRLF)
_TS_Wrapper_TaskRegister($oService, "\Test", "starttime", $oTaskDefinition, Default, Default, $TASK_LOGON_INTERACTIVE_TOKEN)
ConsoleWrite("_TS_Wrapper_TaskRegister: @error=" & @error & ", @extended=" & @extended & @CRLF)

_TS_Close($oService)

 

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

I see my error: DeleteExpiredTaskAfter has to be before registering. Thanks.

  Reveal hidden contents

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...