This project has moved and is read-only. For the latest updates, please go here.

Adding an interactive task on startup

Jul 12, 2011 at 12:53 PM
Edited Jul 12, 2011 at 12:53 PM

Before telling me to look at it, i already looked at the thread:
I've posted there, but than thought this might e a differnent error, and irrelevant to a two years old post..

I did exactly as written, and an exception was thrown:
COMException: (18,8):LogonType:
   in  Microsoft.Win32.TaskScheduler.V2Interop.ITaskFolder.RegisterTaskDefinition(String Path, ITaskDefinition pDefinition, Int32 flags, Object UserId, Object password, TaskLogonType LogonType, Object sddl)
   in  Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String Path, TaskDefinition definition, TaskCreation createType, String UserId, String password, TaskLogonType LogonType, String sddl)

I'm running Windows 7 x64 Ultimate, and writing my code in VS2005 (.net 2 SP1).

My code is this:

TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Source = "Installer";
td.RegistrationInfo.Description = "Setup required operation.";
td.Principal.LogonType = TaskLogonType.InteractiveToken;
td.Principal.UserId = "NT AUTHORITY\\SYSTEM";
td.Principal.RunLevel = TaskRunLevel.Highest;
if (ts.HighestSupportedVersion.Minor <= 1)
   td.Settings.RunOnlyIfLoggedOn = true;

td.Settings.RunOnlyIfIdle = false;
td.Settings.IdleSettings.StopOnIdleEnd = false;
td.Settings.IdleSettings.RestartOnIdle = false;
td.Settings.RunOnlyIfNetworkAvailable = false;
td.Settings.StartWhenAvailable = true;

td.Triggers.Add(new BootTrigger());

td.Actions.Add(new ExecAction(ProcessPath, arguments, Environment.CurrentDirectory));
Microsoft.Win32.TaskScheduler.Task task = folder.RegisterTaskDefinition(ProcessName, td, TaskCreation.Create, null, null, TaskLogonType.ServiceAccount, null); 

What I want to do is to give my installer the ability to run on startup in case it requires reboot (As in installing Microsoft .Net Framework 4), and thus continue its operation from before.
Therefore, I need it to run as an administrator, regardless of the user logged in, and in interactive mode.

Is there a way to achieve this?

Thanks in advance,

Jul 12, 2011 at 4:16 PM

I think what you desire can be accomplished with this code: 

TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Source = "Installer";
td.RegistrationInfo.Description = "Setup required operation.";
td.Triggers.Add(new LogonTrigger());
td.Actions.Add(new ExecAction(ProcessPath, arguments, Environment.CurrentDirectory));
Task task = folder.RegisterTaskDefinition(ProcessName, td, TaskCreation.Create, "SYSTEM", null, TaskLogonType.ServiceAccount, null);
Jul 13, 2011 at 2:23 PM

I've tried what you have suggested. and the task is running under SYSTEM but is not interactive.

Can it be interactive with another user when running under SYSTEM?

Jul 13, 2011 at 6:32 PM

The only way to run a task interactively is with the current user or with an account and password that has Administrator privileges for the machine.

On an non-library note, could use just utilize the registry setting for running things once (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce) or put the executable in the AllUsers\Startup folder?

Jul 14, 2011 at 2:39 PM

The other way you are talking about is impossible on windows Vista and above though it doesn't allow programs to run on startup with administrator privilieges, and I need such privilieges in order to continue installation.

The only way aroumd this that I know of is through task scheduling. Maybe you have another idea?

Regardless, if I declare one should continue installing after startup with the same user he started it with, will not entering password on the RegisterTaskDefinition work?

Jul 15, 2011 at 8:58 PM

If the current user has admin privileges to run the installation in the first place, that user's account can be used just through the registry entry to run the remainder on next logon. If you do want to use a task on Vista and above, you could register the task as the current user with the TaskLogonType.InteractiveTokenOrPassword and use the LogonTrigger setting the UserId to the 'domain\username' of the current user.