need help: "The requested operation requires elevation" [duplicate] - c#

I'm working on a WPF application targeting .NET 3.0. I need to call an exe which requires administrative privileges. I can get the UAC to prompt for permission by using something like:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
startInfo.FileName = "target.exe";
Process p = new Process();
p.StartInfo = startInfo;
p.Start();
My problem is I need to redirect standard output, and doing so with UseShellExecute = true results in an exception stating that:
The Process object must have the UseShellExecute property set to false
in order to redirect IO streams
However, setting it to false results in the UAC not prompting for permission and I get an exception stating:
The requested operation requires elevation
How can I redirect standard output and prompt for UAC?
I have seen this similar question, however the solution is to use the app.manifest to give my application administrative privileges. This is something I cannot do due to requirements.

UseShellExecute must be set to false to redirect IO, and to true to use the Verb property. So you can't.
But this article seems do the magic, although I haven't tested it.
It's written in C++, but a wrapper API can easily be created to be called from C# by using DllImport.
Note: If you want to pass data between the two programs and have access to the target program's source code, you can easily re-design you application to use Named Pipes instead of redirecting standard I/O.

There is another pretty simple solution:
If you want to run a child-executable elevated AND redirect the output (optionally including window hiding), then your main code must be running elevated too. This is a security requirement.
To accomplish this:
Manually edit your app.manifest in your project folder.
Find the comment regarding UAC Manifest Options, you will see the 3 examples of requestedExecutionLevel.
Under the comment, locate the tricky asInvoker which is currently enabled, and replace it with requireAdministrator.
Restart Visual Studio in order to take into effect, and after re-building your app it should have the typical UAC shield icon.
Now your code will run elevated, everything that it launches will be elevated too, and you can also capture output streams. Here is an example in VB.NET:
Dim startInfo As New ProcessStartInfo
startInfo.Verb = "runas"
startInfo.FileName = "subprocess-elevated.exe"
startInfo.Arguments = "arg1 arg2 arg3"
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.WindowStyle = ProcessWindowStyle.Hidden
startInfo.CreateNoWindow = True
Dim p As Process = New Process()
p.StartInfo = startInfo
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
p.StartInfo.RedirectStandardError = True
p.Start()
Console.WriteLine(p.StandardOutput.ReadToEnd)
Console.WriteLine(p.StandardError.ReadToEnd)
p.WaitForExit()

Related

C# Windows Service with Registry Access and rundll32.exe

I have a C# Windows Service running under the LocalSystem account.
I need access to the Windows registry in this service. I assume that this is only possible when running as LocalSystem? Or can I install the service as User context and have access to HKEY_CURRENT_USER?
The systems where the service is used is normally just used by one user. So there will be just "one" HKEY_CURRENT_USER. Another option is, to setup Remote Apps not for one user, but for all users. But I have no idea how to do that. Currently I know only the way listed below by running rundll32.exe.
As a second requirement I need to execute rundll32.exe to create RemoteApp Connection.
The following Code is not working properly:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "/C rundll32.exe tsworkspace,WorkspaceSilentSetup C:\\RemoteConfig.wcx";
using (Process process = Process.Start(startInfo))
{
process.WaitForExit();
}
What must the Service be like to access HKEY_CURRENT_USER?
How can I run rundll32.exe? just running it directly caused some trouble when testing it in a console application. But with help of cmd.exe it worked.

Process start but don't show the window

I'm trying to open an external executable. I can easily open external executables by using the Process class from System.Diagnostics:
Process p = new Process()
p.StartInfo.FileName = processName;
p.Start();
This works fine with most programs, like browsers and notepad, creating a process and showing its graphical interface. However, when I try to open my desired program, the process is started (can see it in the task manager, it even takes a whole CPU core for processing) but the GUI window doesn't show. What could possibly happen to a process from Process.Start to not show its GUI?
For reference, the program I want to execute is ADOM release 60, which runs 100% fine when I open it directly in the Explorer shell or in the Powershell. This is reproducible in both console and WindowsForms applications.
Here are some other settings that did not help:
p.StartInfo.CreateNoWindow = true; // or false
p.StartInfo.ErrorDialog = false;
p.StartInfo.WindowStyle = /* any of possible values */;
p.StartInfo.UseShellExecute = true; // or false
You need to set the WorkingDirectory to the root folder where the executable is located.
var executablePath = .....;
var p = new Process();
p.StartInfo = new ProcessStartInfo(executablePath);
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(executablePath);
p.Start();
The default value of WorkingDirectory is %SYSTEMROOT%\System32. Many legacy applications have hard coded relative paths that resolve to full paths with said directory and will fail miserably when trying to read (or create) files where they are not supposed to.

Redirect standard output and prompt for UAC with ProcessStartInfo

I'm working on a WPF application targeting .NET 3.0. I need to call an exe which requires administrative privileges. I can get the UAC to prompt for permission by using something like:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
startInfo.FileName = "target.exe";
Process p = new Process();
p.StartInfo = startInfo;
p.Start();
My problem is I need to redirect standard output, and doing so with UseShellExecute = true results in an exception stating that:
The Process object must have the UseShellExecute property set to false
in order to redirect IO streams
However, setting it to false results in the UAC not prompting for permission and I get an exception stating:
The requested operation requires elevation
How can I redirect standard output and prompt for UAC?
I have seen this similar question, however the solution is to use the app.manifest to give my application administrative privileges. This is something I cannot do due to requirements.
UseShellExecute must be set to false to redirect IO, and to true to use the Verb property. So you can't.
But this article seems do the magic, although I haven't tested it.
It's written in C++, but a wrapper API can easily be created to be called from C# by using DllImport.
Note: If you want to pass data between the two programs and have access to the target program's source code, you can easily re-design you application to use Named Pipes instead of redirecting standard I/O.
There is another pretty simple solution:
If you want to run a child-executable elevated AND redirect the output (optionally including window hiding), then your main code must be running elevated too. This is a security requirement.
To accomplish this:
Manually edit your app.manifest in your project folder.
Find the comment regarding UAC Manifest Options, you will see the 3 examples of requestedExecutionLevel.
Under the comment, locate the tricky asInvoker which is currently enabled, and replace it with requireAdministrator.
Restart Visual Studio in order to take into effect, and after re-building your app it should have the typical UAC shield icon.
Now your code will run elevated, everything that it launches will be elevated too, and you can also capture output streams. Here is an example in VB.NET:
Dim startInfo As New ProcessStartInfo
startInfo.Verb = "runas"
startInfo.FileName = "subprocess-elevated.exe"
startInfo.Arguments = "arg1 arg2 arg3"
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.WindowStyle = ProcessWindowStyle.Hidden
startInfo.CreateNoWindow = True
Dim p As Process = New Process()
p.StartInfo = startInfo
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
p.StartInfo.RedirectStandardError = True
p.Start()
Console.WriteLine(p.StandardOutput.ReadToEnd)
Console.WriteLine(p.StandardError.ReadToEnd)
p.WaitForExit()

Run process under current user

There is "Setup project" in VS. During installation I launch another process:
System.Diagnostics.Process process = new System.Diagnostics.Process();
//fill StartInfo and run call Start()
process.Start();
If I run installer under Windows 7 and install for "Everyone", process start under the SYSTEM. If I install "Just for me", process start under Current user. How do I always start process under Current user?
I have found very simple solution. All that you need it just create a new class and copy text from this link.
To launch the process call ProcessAsUser.Launch("program name");
I had a similar problem: My setup extension (custom action) needed Admin privileges which brought up an elevation box. After I start my application at the end of "Just for Me" the process had settings that were made for the admin context. For example my user account likes to see all extensions of files in Windows Explorer but the admin account was configured to hide them. So in every file open box I couldn't see the extensions. To cure this this piece of code worked:
ProcessStartInfo startInfo = new ProcessStartInfo(ShortcutTarget);
startInfo.LoadUserProfile = true;
startInfo.UseShellExecute = false;
Process.Start(startInfo);
It works only in "Just for Me" mode, in "Everyone" the admin's settings are used. But this is ok for me.
Use ProcessStartInfo class and its property UserName, then use it as argument for Process.Start static method.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
Process.Start(startInfo);

How do you call an exe from code and get around possible UAC action against this?

I'm using system.diagnostics.process to start an msi file in quiet mode. I'm getting an exit code 1625, and I suspect its because UAC is preventing it from running. I've turned off the UAC prompts but no dice...
How can I make sure that I'm properly elevating the privileges of the msiexec so it actually runs?
Thanks,
Isaac
UAC Elevation in Managed Code: Starting Elevated Processes
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = "/i " + "\""+Directory.GetCurrentDirectory()+"\\"+msiPath +"\"" +" /q";
startInfo.FileName = "msiexec.exe";
startInfo.Verb = "runas";
Process installProcess = Process.Start(startInfo);
Well, this is what I did, and it works.
Try running your process with the admin privileges and see if the problem persists

Categories

Resources