views:

891

answers:

2

I am having issues with setting up a scheduled task with NSIS.

  1. I will not know all of the passwords for the users I am setting up tasks for therefore I need the Run Only if Logged On checkbox checked to get around that.
  2. I do not have access to install other pieces of software onto the computer other than setting up the task so I have to utilize the Windows Task Scheduler preferably.
  3. The task below sets up the task, checks the checkbox however does not run the task set up. It will not run the task until I go and browse to the same file again and then click OK. Now the task wil run just fine. I asked about this behavior in another forum about JT.exe because it does the same thing and was told "It doesn't set the Log on as a batch job User Right that is set by schtasks.exe or the GUI."
  4. I have attempted to create the task and then modify it via the command line. It still does not function.
  5. The goal is to create a Windows XP scheduled task using NSIS (or anything for that matter) that executes properly and checks the Run Only if Logged On checkbox in Task Scheduler 1.0.

Can someone please help?

Here is the current NSIS Script

; Adds a scheduled task running as a different user than the one
; running the installer. Modified from a script by brainsucker
; 
; (c) Justin Dearing <[email protected]>, 2006
; (c) brainsucker, 2002


Name "System Plugin Example"
OutFile "Sheduletask.exe"

; TASK_TRIGGER is the struct that sets when your task in run.
; Setting it via the NSIS System plugin is a healthy alternative to
; banging ones head against the wall.
;
; general TASK_TRIGGER structure arguments
; 1, 2 - skip
; 3,4,5 - BEGIN year, month, day
; 6,7,8 - END year, month, day (SHOULD be = 0, if 1 flag is skipped)
; 9, 10 - Start hour, minute
; 11, 12 - Duration and Interval of task in minutes. (duration - the whole 
;          time task will work, interval - time between runs. D = 120, 
;          I = 10: task will be runned every 10 minutes for 2 hours).
; 13 - flags (should be ored (|)):  
;          1 - task has end date (6,7,8 defined)
;          2 - task will be killed at Duration end
;          4 - task trigger disabled
; 14 - trigger type: there are 7 different types, every one with it own 
;          structure
;       0 = ONCE        task will be runned once
;       5 = On IDLE     task will run on system IDLE (ITask->SetIdleWait)
;       6 = At System Startup
;       7 = At Logon
; these types use the following structure (so 7 means trigger at Logon):
;    push "*(&l2, &i2 0, &i2 2003, &i2 9, &i2 4, &i2 0, &i2 0, &i2 0, &i2 14, &i2 20, i 0, i 0, i 0, i 7, i 0, &i2 0, i 0, &i2 0) i.s"     
;       1 = DAILY  - field 15 gives interval in days (here it 15)
;    push "*(&l2, &i2 0, &i2 2003, &i2 9, &i2 3, &i2 0, &i2 0, &i2 0, &i2 13, &i2 10, i 0, i 0, i 0, i 1, &i2 15, i 0, i 0, &i2 0) i.s"
;       2 = WEEKLY  - field 15 gives interval in weeks (here 17), 
;                  field 16 - shows which days to run (OR them with |): 
;                  Sunday-Saturday (0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40)
;                  in example monday and friday
;    push "*(&l2, &i2 0, &i2 2003, &i2 9, &i2 3, &i2 0, &i2 0, &i2 0, &i2 13, &i2 10, i 0, i 0, i 0, i 2, &i2 13, &i2 0x2|0x20, &i2 0, i 0, &i2 0) i.s"
;       3 = MONTHLYDATE  - field 15 bit field of days (OR them) to run 
;                          (0x1-0x40000000), 
;                  field 16 - bit field of month (OR them with |): 
;                  January-December (0x1-0x800)
;                  in example (3 and 5 days of February and June)
;    push "*(&l2, &i2 0, &i2 2003, &i2 9, &i2 3, &i2 0, &i2 0, &i2 0, &i2 13, &i2 10, i 0, i 0, i 0, i 3, i 0x4|0x20, &i2 0x2|0x20, i 0, &i2 0) i.s"
;       4 = MONTHLYDOW  - field 15 week of month to run (1-5)
;                  field 16 - shows which days to run (OR them with |): 
;                  Sunday-Saturday (0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40)
;                  field 17 - bit field of month (or them with |): 
;                  January-December (0x1-0x800)
;                  in example (first week, monday and friday of February and June)
;    push "*(&l2, &i2 0, &i2 2003, &i2 9, &i2 3, &i2 0, &i2 0, &i2 0, &i2 13, &i2 10, i 0, i 0, i 0, i 4, &i2 1, &i2 0x2|0x20, &i2 0x2|0x20, i 0, &i2 0) i.s"

Function CreateTask
  !define GUIDTask "{148BD520-A2AB-11CE-B11F-00AA00530503}"
  !define GUIDITask "{148BD524-A2AB-11CE-B11F-00AA00530503}"
  !define GUIDTaskScheduler "{148BD52A-A2AB-11CE-B11F-00AA00530503}"
  !define GUIDITaskScheduler "{148BD527-A2AB-11CE-B11F-00AA00530503}"
  !define GUIDITaskTrigger  "{148BD52B-A2AB-11CE-B11F-00AA00530503}"
  !define GUIDIPersistFile "{0000010b-0000-0000-C000-000000000046}"

  SetPluginUnload  alwaysoff

  ; store registers and pop params
  System::Store "S r8r7r5r4r3r2r1r0"

  StrCpy $R0 "error" ; result 

  System::Call "ole32::CoCreateInstance(g '${GUIDTaskScheduler}', i 0, i 11, g '${GUIDITaskScheduler}', *i .R1) i.R9"
  IntCmp $R9 0 0 End

  ; ITaskScheduler->NewWorkItem()
  System::Call '$R1->8(w r0, g "${GUIDTask}", g "${GUIDITask}", *i .R2) i.R9' 

  ; IUnknown->Release()    
  System::Call '$R1->2() i'                    ; release Task Scheduler object
  IntCmp $R9 0 0 End

  ; ITask->SetComment()
  System::Call '$R2->18(w r1)'

  ; ITask->SetApplicationName()
  System::Call '$R2->32(w r2)'

  ; ITask->SetWorkingDir()
  System::Call '$R2->36(w r3)'

  ; ITask->SetParameters()
  System::Call '$R2->34(w r4)'

  ; ITask->CreateTrigger(trindex, ITaskTrigger)
  System::Call '$R2->3(*i .R4, *i .R5)'

  ; ITask->SetFlags()
    System::Call '$R2->28(i 0x2000)'

  ; allocate TASK_TRIGGER structure
  System::Call '$5'
  Pop $R6

  ; ITaskTrigger->SetTrigger
  System::Call '$R5->3(i R6)'     
  ; ITaskTrigger->Release
  System::Call '$R5->2()'     

  ; free TASK_TRIGGER structure
  System::Free $R6

  ; ITask->SetAccountInformation
  System::Call '$R2->30(w r7, w r8)'

  ; IUnknown->QueryInterface
  System::Call '$R2->0(g "${GUIDIPersistFile}", *i .R3) i.R9'     ; QueryInterface

  ; IUnknown->Release()    
  System::Call '$R2->2() i'                    ; release Task  object
  IntCmp $R9 0 0 End

  ; IPersistFile->Save
  System::Call '$R3->6(i 0, i 1) i.R9'         

  ; release IPersistFile
  System::Call '$R3->2() i'                    

  IntCmp $R9 0 0 End
  StrCpy $R0 "ok"     

End:
  ; restore registers and push result
  System::Store "P0 l"

  ; last plugin call must not have /NOUNLOAD so NSIS will be able to delete the temporary DLL
  SetPluginUnload manual
  ; do nothing
  System::Free 0

FunctionEnd


Section "SiteSecureBackup"
  SetOutPath $TEMP
  push "Test Task"
  push "Testing the Task"
  push "C:\file.exe"
  push "C:\"
  push ""
  push \
    "*(&l2, &i2 0, \
   &i2 2006, &i2 1, &i2 1, \
    &i2 0, &i2 0, &i2 0, \
    &i2 0, &i2 0, \
    i 0, i 0, \
    i 0, \
    i 1, \
    &i2 1, &i2 00, &i2 0, i 0, &i2 0) i.s"
  push "Username"
  push "Userpassword"
  Call CreateTask
  Pop $0
  ;MessageBox MB_OK "Scheduled task creation result: $0"
SectionEnd

; eof
A: 

WinXP Log on as a batch job documentation says "In Windows 2000 Server, Windows 2000 Professional, and Windows XP Professional, the Task Scheduler automatically grants this right as necessary"

After skimming the docs, the only thing that jumps out at me is "If you set the TASK_FLAG_RUN_ONLY_IF_LOGGED_ON flag, you may also set pwszPassword to NULL for local or domain user accounts. Use the IScheduledWorkItem::SetFlags method to set the flag" (This makes sense, if the user is logged on, there is no need for a password)

Anders
A: 

Doesn't the

; ITask->SetFlags()
System::Call '$R2->28(i 0x2000)'

does the job? the 28 is the SetFlags index and 0x2000 is the TASK_FLAG_RUN_ONLY_IF_LOGGED_ON.

Vargas