How do I start a process with administrator privileges without my WPF host also runs with admin rights in order to implement file drag & drop?
First, if you need to run just one operation which requires admin rights - that does not mean your whole application should run with admin rights. You need to evelate only for this particular operation. Easiest way to do this is setting UseShellExecute = true when starting your process - then Windows will show usual UAC prompt to user, so that he can confirm evelation. You can describe situation to user before that (in some dialog), or you can put usual UAC icon on button that performs that action (that shield icon).
If that is not an option for you (for example you need redirected output) - you can run another copy of your own application with certain arguments with admin rights (exactly as described above, but not wevtutil, but your own application). This evelated copy will only run wevtutil and exit, doing nothing more.
Is there is a way that program is not asking for Admin password?
when starting the program you can test if the program runs as administrator and if not restart it as administrator, whereby the user is asked for pressing ok only once.
void RestartIfNeeded() {
if (!IsAdmin() {
Process p= new Process {
StartInfo = new ProcessStartInfo {
FileName = Process.GetCurrentProcess().MainModule.FileName,
Arguments = //parameters here,
//Following two lines make process start as admin
Verb = "runas";
UseShellExecute = true;
}
}
p.Start();
p.WaitForExit();
p.Dispose();
Enviroment.Exit(p.ExitCode)
}
}
bool IsAdmin() {
try {
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (Exception) {
return false;
}
}
If your process should start at startup you can use the "Run with highest privileges" function of the windows task scheduler.
public static bool InitalizeScheduledTask() {
string TaskName=//TaskName here;
XNamespace taskNamespace =
XNamespace.Get("http://schemas.microsoft.com/windows/2004/02/mit/task");
XElement taskContents = new XElement(taskNamespace + "Task", new XAttribute("version", "1.4"),
new XElement(taskNamespace + "RegistrationInfo",
new XElement(taskNamespace + "Date", DateTimeToWin32Format(DateTime.Now)),
new XElement(taskNamespace + "Author", WindowsIdentity.GetCurrent().Name),
new XElement(taskNamespace + "Description",
"[Description here] "),
new XElement(taskNamespace + "URI", $"\\{TaskName}")),
new XElement(taskNamespace + "Triggers",
new XElement(taskNamespace + "LogonTrigger", new XElement(taskNamespace + "Enabled", true))),
new XElement(taskNamespace + "Principals",
new XElement(taskNamespace + "Principal", new XAttribute("id", "Author"),
new XElement(taskNamespace + "GroupId", "S-1-5-32-545"),
new XElement(taskNamespace + "RunLevel", "HighestAvailable"))),
new XElement(taskNamespace + "Settings",
new XElement(taskNamespace + "MultipleInstancesPolicy", "Parallel"),
new XElement(taskNamespace + "DisallowStartIfOnBatteries", false),
new XElement(taskNamespace + "StopIfGoingOnBatteries", false),
new XElement(taskNamespace + "AllowHardTerminate", false),
new XElement(taskNamespace + "StartWhenAvailable", false),
new XElement(taskNamespace + "RunOnlyIfNetworkAvailable", false),
new XElement(taskNamespace + "IdleSettings", new XElement(taskNamespace + "StopOnIdleEnd", true),
new XElement(taskNamespace + "RestartOnIdle", false)),
new XElement(taskNamespace + "AllowStartOnDemand", true),
new XElement(taskNamespace + "Enabled", true), new XElement(taskNamespace + "Hidden", false),
new XElement(taskNamespace + "RunOnlyIfIdle", false),
new XElement(taskNamespace + "DisallowStartOnRemoteAppSession", false),
new XElement(taskNamespace + "UseUnifiedSchedulingEngine", true),
new XElement(taskNamespace + "WakeToRun", false),
new XElement(taskNamespace + "ExecutionTimeLimit", "PT0S"),
new XElement(taskNamespace + "Priority", 7)),
new XElement(taskNamespace + "Actions", new XAttribute("Context", "Author"),
new XElement(taskNamespace + "Exec",
new XElement(taskNamespace + "Command", Process.GetCurrentProcess().MainModule.FileName),
new XElement(taskNamespace + "Arguments",//Arguments ))));
string taskString = new XDocument(new XDeclaration("1.0", "UTF-16", null),
taskContents).ToString();
string tempLocation = Path.Combine(Path.GetTempPath(),$"{TaskName}.xml");
File.WriteAllText(tempLocation, taskString);
/*Run Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "SCHTASKS.exe") with the arguments $"/Create /XML \"{tempLocation}\" /TN {TaskName} /RP * /RU {Environment.UserName}"
I have no time to add that now, in that window you will need to enter your password and you have to be admin*/}
public static string DateTimeToWin32Format(DateTime toConvert) =>
$"{toConvert.Year:0000}-{toConvert.Month:00}-{toConvert.Day:00}T{toConvert.Hour:00}:{toConvert.Minute:00}:{toConvert.Second:00}.{toConvert.Millisecond:000}0000";
Please use that function ONLY if your program runs from a protected installation directory.
Run process as administrator from a non-admin application
You must use ShellExecute
. ShellExecute is the only API that knows how to launch Consent.exe
in order to elevate.
Sample (.NET) Source Code
In C#, the way you call ShellExecute
is to use Process.Start
along with UseShellExecute = true
:
private void button1_Click(object sender, EventArgs e)
{
//Public domain; no attribution required.
ProcessStartInfo info = new ProcessStartInfo(@"C:\Windows\Notepad.exe");
info.UseShellExecute = true;
info.Verb = "runas";
Process.Start(info);
}
If you want to be a good developer, you can catch when the user clicked No:
private void button1_Click(object sender, EventArgs e)
{
//Public domain; no attribution required.
const int ERROR_CANCELLED = 1223; //The operation was canceled by the user.
ProcessStartInfo info = new ProcessStartInfo(@"C:\Windows\Notepad.exe");
info.UseShellExecute = true;
info.Verb = "runas";
try
{
Process.Start(info);
}
catch (Win32Exception ex)
{
if (ex.NativeErrorCode == ERROR_CANCELLED)
MessageBox.Show("Why you no select Yes?");
else
throw;
}
}
Bonus Watching
- UAC - What. How. Why.. The architecture of UAC, explaining that
CreateProcess
cannot do elevation, only create a process.ShellExecute
is the one who knows how to launch Consent.exe, and Consent.exe is the one who checks group policy options.
Related Topics
C# Console Receive Input with Pipe
Linq to SQL and a Running Total on Ordered Results
The Maximum Number of Characters a Textbox Can Display
What Is the Worst Gotcha in C# or .Net
How to Execute an Ssis Package from .Net
What Does |= (Single Pipe Equal) and &=(Single Ampersand Equal) Mean
Is There Any Simple Way to Convert .Xls File to .CSV File? (Excel)
Why Can't Yield Return Appear Inside a Try Block with a Catch
How to Run Unit Tests (Mstest) in Parallel
Excel to Datatable Using Epplus - Excel Locked for Editing
How to Hide a Column (Gridview) But Still Access Its Value
How to Export a Jqgrid Data to Excel Using C#
C# "Internal" Access Modifier When Doing Unit Testing
Why Are Private Fields Private to the Type, Not the Instance
Cannot Set Some Http Headers When Using System.Net.Webrequest