Task Scheduler - Com.Object Add State Change Trigger

Welcome Forums General PowerShell Q&A Task Scheduler - Com.Object Add State Change Trigger

Viewing 6 reply threads
  • Author
    Posts
    • #188026
      Participant
      Topics: 2
      Replies: 11
      Points: 40
      Rank: Member

      Hello!

      I want to add a new trigger to an existing task for when a user unlocks their workstation.

      I know i need to use the COM interface to do this, and i know it is state trigger 11 with state change 8.

      I have successfully created the trigger object, but i do not seem to be able to save the task once the new trigger is added. I am fairly sure this is just a syntax issue i am not getting, but i need some fresh eyes!

      $scheduler = New-Object -ComObject Schedule.Service
      $scheduler.connect("Localhost")
      $taskFolder = $scheduler.Getfolder("\")
      $taskDefinition = $taskFolder.getTasks(1)
      $taskDefinition = $taskDefinition | Where-Object { $_.Name -eq "Random Task Name" }
      $regInfo = $TaskDefinition.Definition.RegistrationInfo
      $settings = $taskDefinition.Definition.Settings
      $Triggers = $TaskDefinition.Definition.Triggers
      $Trigger = $Triggers.Create(11)
      $trigger.StateChange = 8
      $trigger.Enabled = $true
      $trigger.ID = 2
      

      So at this point, you can see b0th triggers present in $triggers, but then how do i commit that?

    • #188125
      Participant
      Topics: 10
      Replies: 1284
      Points: 1,084
      Helping Hand
      Rank: Community Hero

      What version of Powershell is the workstation running? If Workstations are running Powershell 4.0, then there are cmdlets you can use rather than messing with an old COM object:

      How to Automate PowerShell Scripts with Task Scheduler

    • #188137
      Participant
      Topics: 2
      Replies: 11
      Points: 40
      Rank: Member

      Windows 10, 5.1

      which cmdlet?

       

      New-schduledtasktrigger doesn't seem to support state change triggers.

    • #188140
      Participant
      Topics: 10
      Replies: 1284
      Points: 1,084
      Helping Hand
      Rank: Community Hero

      The trigger 8 is 'On Startup', so a comparable start would be:

      New-ScheduledTaskTrigger -AtLogOn ...
      
    • #188146
      Participant
      Topics: 2
      Replies: 11
      Points: 40
      Rank: Member
    • #188203
      Participant
      Topics: 2
      Replies: 11
      Points: 40
      Rank: Member

      OK i have decided to just work around the issue.

      In the script, i have an object containing the task definitions i want to create, currently only one has the 'on unlock' requirement.

      $scheduledtasks = @(
                  [pscustomobject]@{
                      Path      = "\"
                      Name      = "My Task"
                      Program   = "C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe"
                      Arguments = "-noLogo -windowStyle hidden -command C:\users\public\logonscript.ps1 -randomswitch"
                      Trigger  = @(
                          [pscustomobject]@{
                              TriggerType = 9
                          }
                          [pscustomobject]@{
                              TriggerType = 11
                              StateChange = 8
                          }
                      )
                      Principal = "BUILTIN\Users"
                      LogonType = 4
                      Repeat    = ""
                      UseCom = 1
                  }
                  [pscustomobject]@{
                      Path      = "\"
                      Name      = "Different Task 2
                      Program   = "C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe"
                      Arguments = "-noLogo -windowStyle hidden -command C:\users\public\othertask.ps1"
                      Trigger   = New-ScheduledTaskTrigger -AtLogon -RandomDelay (New-TimeSpan -hours 1)
                      Principal = New-ScheduledTaskPrincipal -GroupID  Users -runlevel Limited -id Author
                  }
      }
      Then after that a foreach loop to check for, and create if required each task in $scheduledTasks.
      So as above i have just added some additional fields to the object, UseCom = 1 and Triggers.
      foreach ($schTask in $scheduledtasks) {
                  if (!(Get-ScheduledTask $schTask.Name -ErrorAction SilentlyContinue)) {
                      if (($schtask.UseCom) -eq 1) {
                          # Create Task Using Com Object
                          $scheduler = New-Object -ComObject Schedule.Service
                          $scheduler.connect("Localhost")
                          $newTask = $scheduler.NewTask(0)
                          $ri = $newTask.RegistrationInfo
                          $ri.Description = $schTask.Name
                          $ri.Author = "Me"
                          $principal = $newTask.principal
                          $principal.LogonType = $schTask.LogonType
                          $principal.GroupID = $schTask.Principal
                          $principal.RunLevel = 0
                          foreach ($trigger in $schTask.Trigger) {
                              $trigger = $newtask.Triggers.Create($trigger.TriggerType)
                              if ($trigger.StateChange) {
                                  $trigger.StateChange = 8
                              }
                              $trigger.Enabled = $true
                          }
                          $action = $newTask.Actions.Create(0)
                          $action.Path = $schTask.Program
                          $action.Arguments = $schTask.Arguments
                          $taskFolder = $scheduler.Getfolder("\")
                          try {
                              $taskFolder.RegisterTaskDefinition($schTask.Name, $newTask, 6, "", "", 3, $null)
                          }
                          catch {
                              Write-Warning "Error creating task"
                          }
                      }
                      else {
                          # Create Task Using PowerShell
                          $taskPath = $schTask.Path
                          $taskName = $schTask.Name
                          $program = $schTask.Program
                          $arguments = $schTask.Arguments
                          Write-Output "Creating Scheduled Task : $taskName"
                          $a = New-ScheduledTaskAction -Execute $program -Argument $arguments
                          $t = $schTask.Trigger
                          $p = $schTask.Principal
                          $s = New-ScheduledTaskSettingsSet
                          $d = New-ScheduledTask -Action $A -Principal $p -Trigger $T -Settings $S
                          try {
                              $task = Register-ScheduledTask -InputObject $d -TaskPath $taskPath -TaskName $taskName -ErrorAction Stop
                              if ($schTask.Repeat) {
                                  $task.Triggers.Repetition.Interval = $schTask.Repeat
                                  $task | Set-ScheduledTask | Out-Null
                              }
                          }
                          catch {
                              Write-Warning "Error Registering Scheduled Task : $taskName"
                          }
                      }
                  }
              }
      Not ideal, but gets the job done.
    • #188332
      Participant
      Topics: 0
      Replies: 1
      Points: 6
      Rank: Member

      Here are all 8 of the SessionState triggers:

      Value Meaning
      TASK_CONSOLE_CONNECT
      1
      Terminal Server console connection state change. For example, when you connect to a user session on the local computer by switching users on the computer.
      TASK_CONSOLE_DISCONNECT
      2
      Terminal Server console disconnection state change. For example, when you disconnect to a user session on the local computer by switching users on the computer.
      TASK_REMOTE_CONNECT
      3
      Terminal Server remote connection state change. For example, when a user connects to a user session by using the Remote Desktop Connection program from a remote computer.
      TASK_REMOTE_DISCONNECT
      4
      Terminal Server remote disconnection state change. For example, when a user disconnects from a user session while using the Remote Desktop Connection program from a remote computer.
      TASK_SESSION_LOCK
      7
      Terminal Server session locked state change. For example, this state change causes the task to run when the computer is locked.
      TASK_SESSION_UNLOCK
      8
      Terminal Server session unlocked state change. For example, this state change causes the task to run when the computer is unlocked.

      Source: https://docs.microsoft.com/en-us/windows/win32/taskschd/sessionstatechangetrigger-statechange

Viewing 6 reply threads
  • You must be logged in to reply to this topic.