NSIS: Task Scheduler: Run only if logged on checkbox - nsis
I am having issues with setting up a scheduled task with NSIS.
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.
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.
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."
I have attempted to create the task and then modify it via the command line. It still does not function.
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 <zippy1981#gmail.com>, 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
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)
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.
Related
NSIS not displaying new control after change ui
I took ui.cpp and default.rc from the svn, compiled it, used changeui ---> works! I can't display new controls. This is a section from the new default.rc IDD_LICENSE DIALOGEX 0, 0, 266, 130 STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN ICON IDR_MAINFRAME,IDR_MAINFRAME,0,0,22,20 LTEXT "pppppppppppppppppppppp",507,25,0,241,23 LTEXT "email user",508, 172, 106, 233, 31 CONTROL "",IDC_EDIT1,RICHEDIT_CLASS,WS_BORDER | WS_VSCROLL | WS_TABSTOP | 0x804,0,24,266,105 END In the nsh script, on create function of a page I tried: GetDlgItem $MyHandle $HWNDPARENT507 MessageBox MB_OK $MyHandle //this is always 0 no matter what I tried in the previous line!!! EnableWindow $MyHandle 1 I also tried editing the original defalt.exe with resource hacker but nsis wouldn't display new text/control. How can I display the new text and control???
The NSIS GUI is actually one dialog window with another dialog window inside it. You first need to find the inner dialog before you can find the controls in it: FindWindow $0 "#32770" "" $HWNDPARENT ; Find the inner dialog (See attached picture) GetDlgItem $MyHandle $0 507 ; Find the control Complete example: !define ResHacker "$%localappdata%\Programs\ResHacker.exe" ; TODO: Adjust this path !define myui "${__FILE__}\..\mytempui.exe" !tempfile res !tempfile rc !delfile "${rc}" !delfile "${res}" !define /redef rc "${res}.rc" !define /redef res "${res}.res" !appendfile "${rc}" '#define IDD_LICENSE 102$\r$\n' !appendfile "${rc}" '#define IDC_EDIT1 1000$\r$\n' !appendfile "${rc}" '#define RICHEDIT_CLASS "RichEdit20W"$\r$\n' !appendfile "${rc}" 'LANGUAGE 0x09, 0x01$\r$\n' !appendfile "${rc}" 'IDD_LICENSE DIALOGEX 0, 0, 266, 130$\r$\n STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD$\r$\n' !appendfile "${rc}" 'FONT 8, "MS Shell Dlg", 0, 0, 0x1$\r$\n' !appendfile "${rc}" 'BEGIN$\r$\n' !appendfile "${rc}" ' LTEXT "pppppppppppppppppppppp",507,25,0,241,23,SS_LEFT|WS_VISIBLE$\r$\n' !appendfile "${rc}" ' LTEXT "email user",508, 172, 106, 233, 31,SS_LEFT|WS_VISIBLE$\r$\n' !appendfile "${rc}" ' CONTROL "",IDC_EDIT1,RICHEDIT_CLASS,WS_BORDER | WS_VSCROLL | WS_TABSTOP|WS_VISIBLE | 0x804,0,24,266,55$\r$\n' !appendfile "${rc}" 'END$\r$\n' !system '"${ResHacker}" -open "${rc}" -save "${res}" -action compile -log CON' = 0 !delfile "${rc}" !system '"${ResHacker}" -open "${NSISDIR}\Contrib\UIs\default.exe" -save "${myui}" -action addoverwrite -res "${res}" -mask DIALOG,102,1033 -log CON' = 0 !delfile "${res}" ChangeUI IDD_LICENSE "${myui}" Page License "" MyLicShow Page InstFiles !include WinMessages.nsh Var MyHandle Function MyLicShow FindWindow $0 "#32770" "" $HWNDPARENT ; Find the inner dialog (See attached picture) GetDlgItem $MyHandle $0 507 ; Find the control SendMessage $MyHandle ${WM_SETTEXT} "" "STR:New control text" SetCtlColors $MyHandle ff0000 transparent FunctionEnd
How to limit the number of text box characters in NSIS
I want to limit the number of characters in each text box to 4 digits. It can be implemented in C # Winform, but it is not familiar with how to use it in NSIS. Attempted action: I put the label and I am guiding the input to four digits. But that's not good. I tried to find information through the NSIS forum, but I could not find it. Attach text box image : text box NSIS code: Function Test !insertmacro MUI_INSTALLOPTIONS_READ $0 "pageInputLicenseInfo.ini" "Settings" "State" ${If} $0 == 9 # btton !insertmacro MUI_INSTALLOPTIONS_READ $R0 "pageInputLicenseInfo.ini" "Field 1" "State" !insertmacro MUI_INSTALLOPTIONS_READ $R1 "pageInputLicenseInfo.ini" "Field 2" "State" !insertmacro MUI_INSTALLOPTIONS_READ $R2 "pageInputLicenseInfo.ini" "Field 3" "State" !insertmacro MUI_INSTALLOPTIONS_READ $R3 "pageInputLicenseInfo.ini" "Field 4" "State" !insertmacro MUI_INSTALLOPTIONS_READ $R4 "pageInputLicenseInfo.ini" "Field 5" "State" !insertmacro MUI_INSTALLOPTIONS_READ $R5 "pageInputLicenseInfo.ini" "Field 6" "State" nsExec::ExecToStack '$INSTDIR\ParamterTestConsole.exe ${PRODUCT_NAME} $R0 $R1$R2$R3$R4$R5' Pop $2 ; Exit code Pop $3 ; console OUTPUT Blah blah.......... FunctionEnd NSIS INI File: ; Ini file generated by the HM NIS Edit IO designer. [Settings] NumFields=14 Title=test [Field 1] Type=Text Text=1 Left=29 Right=275 Top=46 Bottom=57 [Field 2] Type=Text Text=123 Left=30 Right=60 Top=67 Bottom=78 [Field 3] Type=Text Text=123 Left=74 Right=103 Top=67 Bottom=78 [Field 4] Type=Text Text=123 Left=121 Right=149 Top=67 Bottom=78 [Field 5] Type=Text Text=123 Left=164 Right=193 Top=67 Bottom=78 [Field 6] Type=Text Text=123 Left=206 Right=236 Top=67 Bottom=78 [Field 7] Type=Label Text=IP Left=1 Right=15 Top=48 Bottom=56 [Field 8] Type=Label Text=Key Left=1 Right=20 Top=70 Bottom=78 [Field 9] Type=Button Text=enter Flags=NOTIFY Left=225 Right=275 Top=92 Bottom=105 [Field 10] Type=Label Text=※ Enter four digits. Left=0 Right=152 Top=26 Bottom=43 [Field 11] Type=Label Text=- Left=154 Right=160 Top=68 Bottom=80 [Field 12] Type=Label Text=- Left=199 Right=205 Top=68 Bottom=76 [Field 13] Type=Label Text=- Left=110 Right=116 Top=68 Bottom=76 [Field 14] Type=Label Text=- Left=64 Right=70 Top=68 Bottom=76 Please help me.
As mentioned in the documentation, you can make use of the MaxLen option. Example: [Field 1] Type=Text Text=1 Left=29 Right=275 Top=46 Bottom=57 MaxLen=4
Why does strace believe this memory is uninitialized when attaching to a process?
I have an extremely simple program that does nothing more than call recvfrom() in a loop. According to its manpage, one of the arguments is a pointer to the length of the address. This address is initialized in the .data section to the integer value 16. I noticed some strange behavior when I attach to the already-running process to trace it which is not present when I trace the process directly (when I start it traced). Scroll to the end of the lines: # strace -x -s 10 -e trace=recvfrom ./test recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(42134), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32 recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(49442), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32 recvfrom(3, ^Cstrace: Process 18909 detached <detached ...> # ./test & # strace -x -s 10 -e trace=recvfrom -p $! strace: Process 18916 attached recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(50906), sin_addr=inet_addr("127.0.0.1")}, [1999040176->16]) = 32 recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(52956), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32 recvfrom(3, ^Cstrace: Process 18916 detached <detached ...> When I trace it directly, the address length argument shows as [16], which makes sense. After all, the address is a pointer to an int of the value 16. However, when I attach to the process and trace it, the very first call shows that it is not initialized, e.g. [1999040176->16]. This happens for the first syscall every time I attach, but all subsequent calls it shows it correctly as [16]. If I detach from the process and re-attach, the first call will show it as having uninitialized memory. To be brief: When I run it under strace, the last argument shows [16] for every recvfrom(). When I attach to it when it is already running, the last argument shows things like [1999040176->16] in the first call to recvfrom(), and [16] in all subsequent ones. If I detach from it and attach again, the first call to recvfrom() again displays this odd behavior, and all subsequent calls display the expected [16]. The program itself is correct. Here is the program (written in MIPS assembly): .section .text .global __start __start: # socket li $v0,4183 li $a0,2 li $a1,1 li $a2,0 syscall sw $v0,sockfd # bind li $v0,4169 lw $a0,sockfd la $a1,sockaddr_b li $a2,16 syscall loop: # recvfrom li $v0,4176 lw $a0,sockfd la $a1,buffer li $a2,32 li $a3,0 la $t0,sockaddr_a sw $t0,16($sp) la $t0,addrlen sw $t0,20($sp) syscall j loop .section .bss sockaddr_a: .space 16 buffer: .space 32 sockfd: .space 4 .section .data addrlen: .int 16 .section .rodata sockaddr_b: .hword 2,1234,0,0
Virtual key-press to function-key of a gaming keyboard
How to virtually activate special function keys of a "MadCatz Strike 7" keyboard? Sending its key code should have MadCatz7 software act as if registering a physical key press. Are there key codes for these function keys (or is there a better way)? I am working on an AutoIt script that should let MadCatz software do the rest by activating corresponding special function keys.
Try to figure out the key with this code. Normally your specail function keys have a alternative hotkey as ctrl+alt+F10 or something. Opt('GUICloseOnESC', 0) Global $tState = DllStructCreate('byte[256]') GUICreate('MyGUI', 200, 200) $Label = GUICtrlCreateLabel('', 20, 72, 160, 52, 0x01) GUICtrlSetFont(-1, 32, 800, 0, 'Tahoma') GUISetState() $Prev = -1 While 1 Sleep(10) If GUIGetMsg() = -3 Then ExitLoop EndIf $Key = 0 $Ret = DllCall('user32.dll', 'int', 'GetKeyboardState', 'ptr', DllStructGetPtr($tState)) For $i = 0x08 To 0xFF Switch $i Case 0x0A, 0x0B, 0x0E To 0x0F, 0x16, 0x1A, 0x1C To 0x1F, 0x3A To 0x40, 0x5E, 0x88 To 0x8F, 0x97 To 0x9F, 0xB8 To 0xB9, 0xC1 To 0xDA, 0xE0, 0xE8 ContinueLoop Case Else If BitAND(DllStructGetData($tState, 1, $i + 1), 0xF0) Then $Key = $i ExitLoop EndIf EndSwitch Next If $Key <> $Prev Then GUICtrlSetData($Label, '0x' & Hex($Key, 2)) $Prev = $Key EndIf WEnd
There is no way to do that without telling the MadCatz software directly that the special key was pressed, so that the software would launch the programmed template. I solved the problem using an AutoIt Script and will post the code when it's done.
Ways to update progress bar
I want to control progressbar in my nsis installer. Actually I'm using ThreadTimer plugin but I've got big problem with it. ThreadTimer runs function every 10 seconds to update progress bar (increace progress bar value by 1%). The problem is that it crashes stack (as I can see ThreadTimer is using the same stack as NSIS). Crashes stack means that when I want to get value from the stack the value is wrong because of ThreadTimer function action. Any ideas? Maybe there are some other ways to update progress bar? Those are functions/macros which should update progress bar. Macro StartProgressBarIntervalUpdate starts updating progress bar, macro StopProgressBarIntervalUpdate stops doping it. Var /GLOBAL ProgressBarPosition Var /GLOBAL ProgressBarParentWindow Var /GLOBAL ProgressBarItem Function InitProgressBar StrCpy $ProgressBarPosition "0" FindWindow $ProgressBarParentWindow "#32770" "" $HWNDPARENT GetDlgItem $ProgressBarItem $ProgressBarParentWindow 1004 FunctionEnd Function UpdateProgressBarTimer ${If} $ProgressBarPosition >= 30000 ; 100% * 300 StrCpy $ProgressBarPosition "0" ${Endif} IntOp $ProgressBarPosition $ProgressBarPosition + 300 SendMessage $ProgressBarItem ${PBM_SETPOS} $ProgressBarPosition 0 FunctionEnd !define StartProgressBarIntervalUpdate "!insertmacro StartProgressBarIntervalUpdate" !macro StartProgressBarIntervalUpdate Call InitProgressBar GetFunctionAddress $UpdateProgressBarTimerFunctionAddress UpdateProgressBarTimer ThreadTimer::Start /NOUNLOAD 20 -1 $UpdateProgressBarTimerFunctionAddress Sleep 1000 !macroend !define StopProgressBarIntervalUpdate "!insertmacro StopProgressBarIntervalUpdate" !macro StopProgressBarIntervalUpdate ThreadTimer::Stop $UpdateProgressBarTimerFunctionAddress Sleep 15000 !macroend Here are sections which uses progressbar Var /GLOBAL UpdateProgressBarTimerFunctionAddress Section BeforeMoveData SEC01 ${StartProgressBarIntervalUpdate} Call core.UnpackExeData SectionEnd Section OnMoveData SEC02 Call InstallFiles Call InstallRegistry Call InstallShortcuts ${StopProgressBarIntervalUpdate} ... SectionEnd