-2

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.

  • 1
    _These options do not work_ perhaps you should explain what problems do you have with these options – Steve Dec 27 '17 at 13:45
  • 1
    Why are you using a WinForms app for a Windows service? Services don't have a GUI, and don't interact with the user at all. They're controlled via the control panel or by command line using sc.exe. – Ken White Dec 27 '17 at 13:48
  • 2
    You cannot have a program prompt for UAC elevation at startup. That is intentionally disabled in the OS, the user can't reliably tell what he gives consent to. Consider creating a small program that does not require elevation, simply a prompt to the user to click a button. Whose Click event handler starts the real program. Do make sure your uninstaller is flawless. Avoid it being the most popular feature of your product by splitting the job. A service that does the elevated stuff, a separate GUI that shows what is going on. – Hans Passant Dec 27 '17 at 14:19
  • @Steve in the first option "Put the application executable path on regedit" nothing happens, the system cannot launch application, nothing error is shown. – Rondinelli Morais Dec 27 '17 at 19:30
  • @Steve in the second option "I Did create Windows Services project" because services don't have a GUI, and don't interact with the user at all. – Rondinelli Morais Dec 27 '17 at 19:32
  • @KenWhite exactly! But I discovered this after try – Rondinelli Morais Dec 27 '17 at 20:15
  • Basically my application use dll of http://openhardwaremonitor.org for read temperature of hardwares. This dll requires UAC elevation to read the data. Answering the question of the @HansPassant, this is a reason where I can't the small program – Rondinelli Morais Dec 27 '17 at 20:20
  • If you require UAC permission, then you cannot run your app at startup without re-writing it as a proper Windows service, and then run it as a service using the SYSTEM account at startup. You can't have it both ways. UAC involves a user (that's the **U** in UAC), and there is no user at startup, because the OS hasn't started up yet to ask a user for anything. – Ken White Dec 27 '17 at 22:28
  • in this case how should I do it? when the user closes the form, I just hide the window and create an IconNotify, I thought I could initialize it with the system with the hidden form – Rondinelli Morais Dec 27 '17 at 23:18

1 Answers1

0

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