Llaunching an un-elevated application from an elevated process

Topics: Errors
Jul 13, 2016 at 5:48 PM
I have a WPF client application that checks against its server to ensure it is up to date. If it's not, an elevated process launches to perform the update and the client application closes. The updater re-launches the WPF client application after the update is complete, but it is launched with elevated privileges. I am trying to use the TaskService to get around that by having it launch the WPF client application with the leastpriviledges after the update is complete. I am seeing that it launches as a background task and is invisible to the user. I have checked Hidden = false on the task definition but it is still hidden. I have tried launching cmd.exe instead with the WPF client application as the arguments with the same result.
                var arguments = string.Format("/C \"{0}\"", Executable);

                using (var ts = new TaskService())
                {
                    var taskName = "RelaunchApp";

                    var td = ts.NewTask();
                    td.RegistrationInfo.Description = string.Format("Relaunch application {0}", Executable);

                    td.Actions.Add(new ExecAction("cmd.exe", arguments));

                    td.Settings.Priority = ProcessPriorityClass.Normal;
                    td.Settings.Hidden = false;
                    td.Principal.RunLevel = TaskRunLevel.LUA;
                    td.Principal.LogonType = TaskLogonType.InteractiveToken;
                    td.Settings.AllowDemandStart = true;
                    td.Settings.DisallowStartIfOnBatteries = false;
                    td.Settings.StopIfGoingOnBatteries = false;

                    var ret = ts.RootFolder.RegisterTaskDefinition(taskName, td);

                    var clientTask = ts.FindTask(taskName);
                    if (null != clientTask)
                    {
                        if (clientTask.Enabled)
                        {
                            clientTask.Run(arguments);
                        }
                    }
                    else
                    {
                        TraceLine("Task not found.");
                    }

                    td.Dispose();

                    ts.RootFolder.DeleteTask(taskName);
                }
I have also tried launching the WPF client app directly:
                using (var ts = new TaskService())
                {
                    var taskName = "RelaunchApp";

                    var td = ts.NewTask();
                    td.RegistrationInfo.Description = string.Format("Relaunch application {0}", Executable);

                    td.Actions.Add(new ExecAction(Executable));

                    td.Settings.Priority = ProcessPriorityClass.Normal;
                    td.Settings.Hidden = false;
                    td.Principal.RunLevel = TaskRunLevel.LUA;
                    td.Settings.AllowDemandStart = true;
                    td.Settings.DisallowStartIfOnBatteries = false;
                    td.Settings.StopIfGoingOnBatteries = false;
                    var ret = ts.RootFolder.RegisterTaskDefinition(taskName, td);

                    var clientTask = ts.FindTask(taskName);
                    if (null != clientTask)
                    {
                        if (clientTask.Enabled)
                        {
                            clientTask.Run();
                        }
                    }
                    else
                    {
                        TraceLine("Task not found.");
                    }

                    td.Dispose();

                    ts.RootFolder.DeleteTask(taskName);
                }
What do I need to do to make the application visible?

Thank you!
Coordinator
Jul 15, 2016 at 8:22 PM
The TaskService constructor with parameters will run in the user context of the current process. When you register tasks, they also will then run in that same user's context. Elevation will only change the rights of the context's token. If the current context is the user process, then your first code snippet using InteractiveToken should allow the process to be visible. If the context in which TaskService is constructed is not the user's context, then you need to construct it with parameters that specify the user's account.
Marked as answer by dahall on 7/20/2016 at 11:11 AM