Search code examples
c#.netwindowswindows-forms-designeruac

Windows Form Startup with Admin Permission


I have a windows form application that need of the admin permission for running, to make this, I use this code:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

The next step for complete the development is that this windows form application start up after windows restart, turn off and turn on again or user logon.

Here is my problem, this application need administrator permission and need startup after system startup, but I don't know to make this.

things did I do:

Put the application executable path on regedit

Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);

I Did create Windows Services project

https://learn.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer

These options do not work, can someone help me?

Thank you.


Solution

  • I find the answer for run a application with admin permission at startup.

    Basically I just created a task with run level Highest and your trigger is on Logon.

    I found the code in vb in this repository: https://bitbucket.org/trparky/start_program_at_startup_without_uac

    Sub addTask(taskName As String, taskDescription As String, taskEXEPath As String, taskParameters As String)
            taskName = taskName.Trim
            taskDescription = taskDescription.Trim
            taskEXEPath = taskEXEPath.Trim
            taskParameters = taskParameters.Trim
    
            If Not IO.File.Exists(taskEXEPath) Then
                MsgBox("Executable path not found.", MsgBoxStyle.Critical, Me.Text)
                Exit Sub
            End If
    
            Dim taskService As TaskService = New TaskService()
            Dim newTask As TaskDefinition = taskService.NewTask
    
            newTask.RegistrationInfo.Description = taskDescription
    
            If chkEnabled.Checked Then newTask.Triggers.Add(New LogonTrigger)
    
            Dim exeFileInfo As New FileInfo(taskEXEPath)
    
            newTask.Actions.Add(New ExecAction(Chr(34) & taskEXEPath & Chr(34), taskParameters, exeFileInfo.DirectoryName))
    
            newTask.Principal.RunLevel = TaskRunLevel.Highest
            newTask.Settings.Compatibility = TaskCompatibility.V2_1
            newTask.Settings.AllowDemandStart = True
            newTask.Settings.DisallowStartIfOnBatteries = False
            newTask.Settings.RunOnlyIfIdle = False
            newTask.Settings.StopIfGoingOnBatteries = False
            newTask.Settings.AllowHardTerminate = False
            newTask.Settings.UseUnifiedSchedulingEngine = True
            newTask.Settings.ExecutionTimeLimit = Nothing
            newTask.Settings.Priority = ProcessPriorityClass.Normal
            newTask.Principal.LogonType = TaskLogonType.InteractiveToken
    
            taskService.RootFolder.SubFolders(strTaskFolderName).RegisterTaskDefinition(taskName, newTask)
    
            newTask.Dispose()
            taskService.Dispose()
            newTask = Nothing
            taskService = Nothing
        End Sub
    

    So all I did was translated this code to c# and make tests

    using Microsoft.Win32.TaskScheduler;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CreateTaskTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                addTask();
                //deleteTask();
            }
    
            static void addTask()
            {
                // Get the service on the local machine
                using (TaskService ts = new TaskService())
                {
                    // Create a new task definition and assign properties
                    TaskDefinition newTask = ts.NewTask();
                    newTask.RegistrationInfo.Description = "Rondinelli Morais Create Task";
    
                    newTask.Triggers.Add(new LogonTrigger());
    
                    newTask.Actions.Add(new ExecAction("C:\\Windows\\regedit.exe"));
    
                    newTask.Principal.RunLevel = TaskRunLevel.Highest;
                    newTask.Principal.LogonType = TaskLogonType.InteractiveToken;
    
                    newTask.Settings.Compatibility = TaskCompatibility.V2_1;
                    newTask.Settings.AllowDemandStart = true;
                    newTask.Settings.DisallowStartIfOnBatteries = false;
                    newTask.Settings.RunOnlyIfIdle = false;
                    newTask.Settings.StopIfGoingOnBatteries = false;
                    newTask.Settings.AllowHardTerminate = false;
                    newTask.Settings.UseUnifiedSchedulingEngine = true;
                    newTask.Settings.Priority = System.Diagnostics.ProcessPriorityClass.Normal;
    
                    // Register the task in the root folder
                    ts.RootFolder.RegisterTaskDefinition(@"Test", newTask);
    
                    newTask.Dispose();
                    ts.Dispose();
                }
            }
    
            static void deleteTask()
            {
                using (TaskService ts = new TaskService())
                {
    
                    var tasks = ts.FindAllTasks(new System.Text.RegularExpressions.Regex(@"Test"));
    
                    foreach(var task in tasks){
                        ts.RootFolder.DeleteTask(task.Name);
                    }
                }
            }
        }
    }
    

    I'm using regedit.exe on exemple because this program required admin permission for run.

    Create the task, make logoff and login again and you will see the regedit open after logon.

    OBS: To create or delete task you have run visual studio as administrator, or put this code in the install process of your program

    Let me know if this worked for someone