C# Windows Service with Registry Access and rundll32.exe - c#

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.

Related

Start Azure Storage Emulator for non-Admin users on Startup

At work we use Azure functions for simple tasks.
To debug or run the function you need a running Azure Storage Emulator.
The problem is that our developer accounts don't have admin privileges so we can't start the emulator ourselves.
For now we solve this by asking an admin to start it for us, but that works only until you restart/turn off the machine.
We tried many things for the emulator to start for each user( as if it was run by the admin) but nothing worked.
Here is one of the methods we tried. A simple program that runs at startup and starts the emulator. If you start it manually as admin it does the job and the emulator starts without problems.
But when scheduled to start(with the admin account) at startup or at logon it starts it but only for the admin account and not the current user.
Code for the program we run at startup:
internal class Program
{
private static void Main(string[] args)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = #"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe";
startInfo.Arguments = "start";
process.StartInfo = startInfo;
process.Start();
}
}
Do you have any idea or suggestions how to solve the above problem ?
P.S:I have searched the related topics posted on StackOverflow for issues of the same kind but they ware not much help or the use-case was different.
:)
As per this link: the first time you run your emulator, the emulator environment will need to configure itself: it will create a database in LocalDB and it will register some HTTP ports. In order for the configuration process to succeed, you need administrator privilege.
The next time you'll run the storage emulator, you will no longer need administrator privilege.
So there is a tricky way, just for your reference.
you can use administrator to start the emulator, then wait for a few seconds(it finishes the inialization), stop emulator.
Then you can use normal user account to start it, it would be run for you.
Code like below:
with admin account:
private static void Main(string[] args)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = #"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe";
startInfo.Arguments = "start";
process.StartInfo = startInfo;
process.Start();
//Wait for finished initialization
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
//After initialization, close the Emulator
Process[] processes = Process.GetProcessesByName("AzureStorageEmulator");
foreach (var p in processes)
{
p.Kill();
}
}
Then you can start Emulator again using your developer account, the code is similar to the above.
It maybe a not good choice, you can also submit an question on here.

What is reliable way to start external program for c# application

From my C# application I want to start another application that requires admin privilleges and has manifest that ensures it.
My part of code:
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(#"MyLauncher.exe");
startInfo.Arguments = "/a";
startInfo.UseShellExecute = true;
startInfo.Verb = "runas";
System.Diagnostics.Process p = System.Diagnostics.Process.Start(startInfo);
Thread.Sleep(5000);
Current.Shutdown();
Unfortunatelly sometimes application start smoothly but from time to time only UAC dialog appears but the application does not start.
I tried different startup settings but no luck.

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

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()

How to run an elevated command as impersonated user within a domain

We have a lot of clients within our domain that are not constant connected with our network. Our users are working on small (sometimes disconnected) local networks with different types of network printers (usually provided by us). Within this small network there are also people NOT enlisted in our domain (partners, employers,..) that need these printers. Some of these users are local administrators but most are not.
My goal is to (dynamically) create an installer for each printer so the user may run this installer either from our network, usb, cd,.. so the local tcp/ip port is created, the printerdriver gets installed and the printer gets added.
My problem lies in obtaining sufficient rights to perform the installation.
(1) IF (and only IF!) the local user is an administrator, the installer should launch an elevated app to handel the installation.
(2) IF the user is a member of our domain but he is NOT a local administrator, the installer should use a local administrator account that was added by our policies.
I know how to run an elevated process which brings up the UAC for confirmation and i know how to impersonate another user..
But when trying to Elevate a command while impersonating i never get to see an elevation confirmation.. Which is logical and normal.
Any tips or tricks? Anyone?
What'ya know.. it seems to be possible after all. I first used an impersonation that fired the elevation prompt which didn't work. It's actually even more easy.
Here are the stripped down basics:
[FirstApp]
var str = "%My Administrator Password%";
var pwd = new System.Security.SecureString();
foreach(char c in str) pwd.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false;
psi.WorkingDirectory = #"C:\path";
psi.FileName = #"C:\path\SecondApp.exe";
psi.UserName = "%My Administrator UserName%";
psi.Domain = "%My Administrator Domain%";
psi.Password = pwd;
psi.Verb = "runas";
var proc = new Process();
proc.StartInfo = psi;
proc.Start();
[SecondApp.exe]
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = true;
psi.WorkingDirectory = #"C:\path";
psi.FileName = #"C:\path\ElevatedApp.exe";
psi.Verb = "runas";
var proc = new Process();
proc.StartInfo = psi;
proc.Start();
Works for me. The simple user that fires FirstApp.exe see's the elevation prompt that get's executed as an elevated administrator.
Credit go to J. Robbins : http://www.wintellect.com/blogs/jrobbins/elevate-a-process-at-the-command-line-in-vista

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()

Categories

Resources