For some reason, my C# program needs to restart with elevated privileges. I use the following code to achieve it:
private static void RestartForPermissionsFix()
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Assembly.GetExecutingAssembly().Location;
Process.Start(processInfo);
}
This works great.
After I "fix my privileges", I want to restart the program unelevated. I tried the same as above without the "runas", but it does not work. I assume the process being started from an elevated process automatically gets elevated. Any idea?
In order to launch a process at medium integrity from a high integrity process, I believe you would have to get the current process token using OpenProcessToken, duplicate it, remove the high integrity SID from the token using SetTokenInformation, and then use that token to create the new process using CreateProcessAsUser. This would be similar to this example, except rather than add the low integrity SID you'd have to remove the high integrity one. Note: I haven't tested this, so I'm not 100% sure it would work.
I suggest you leave the original unelevated process running, and have it wait for its elevated counterpart to finish (e.g. using Process.WaitForExit). Once that finishes, it can continue unelevated as before. This would be a lot easier and more foolproof.
I had the same problem with an application that I wanted to update automatically (The update program requires elevated privileges).
What I did was creating an external .exe that would start my updater program with elevated privileges, wait for it to exit, then restart my application with normal privileges.
I then embedded this .exe in my main application, and start this .exe just before leaving my application when I update it.
Related
I need your help again :)
What I want to do:
I have a c# program which runs with normal user permissions - those can't be raised - and I want to change the system date (not time) from that program.
[EDIT] To be a bit more specific: I do have administrator credentials which could be embedded to the program (yikes, I know), but I want to avoid an UAC prompt.
When I launch cmd from outside Visual Studio and try to change the date, it fails with "missing client permission" (roughly translated from German). When I launch cmd as administrator, confirm the UAC prompt the same command succeeds.
I am writing from home, so I cant provide running code at the moment. But all my tries did compile and run without error but the date wasn't changed.
What I've tried:
Created a Process instance, applied admin credentials to ProcessStartInfo, set the FileName to c:\windows\system32\cmd.exe and the argument to /C date {thedate}. I redirected StandardOutput and StandardError and after execution StandardError contains the same message as stated above: "missing client permission"
I've modified this example MSDN: WindowsIdentity.Impersonate using PInvoke with AdvAPI32.LogonUser to raise permissions and Kernel32.SetSystemTime to change the system time. AdvAPI32.LogonUser succeeds and WindowsIdentity.GetCurrent().Name returns the admin name, but calling Kernel32.SetSystemTime fails with "missing client permission".
I've tried opening the current process AdvApi32.OpenCurrentProcess and adjusting the permissions using AdvApi32.AdjustTokenPrivileges following this example StackOverflow: Change system time programmaticaly using datetimepeaker and the code runs totally fine but Kernel32.SetSystemTime fails...
[EDIT] Solution:
I ended up writing a small program with an embedded app.manifest that requests administrator privilegs. This app is called from the main program so this can still be run by a normal user.
It is not possible to change the privileges of the process, once it's started. The original process has to start another process with elevated privileges. This second process can actually be the same .exe file, but with a command parameter that tells the process to do some small stuff and exit immediately.
To start a process with elevated privileges use Process.Start, but with .Verb = "runas", as described in another question. This will of course cause UAC prompt to pop up, if it's enabled on the machine. At least one UAC prompt has to be shown, because UAC prompt is the whole point if this defense mechanism.
If you want to reduce many UAC prompts to just one then you can set the original app to be started as administrator (UAC prompt shows when original process starts) and have just one process. Or have some interprocess communication between original process and elevated process, so that elevated process is started only once and made to finish when original process ends. In the second case UAC prompt shows the first time it's needed.
Can I ask why you are needing to change the system time from an unprivileged application?
If it is to influence other applications then you will need admin privilege since date time is such a vital system function to many other applications. However if you are just needing to adjust the date in your application only then I would suggest creating your own date/time provider that can return the date offset to the date that you desire in your application.
For example.
public DateTime GetDateWithOffset(int daysToOffset)
{
return DateTime.UtcNow.AddDays(daysToOffset);
}
I need to start an application from another application. It looks like I have to use the shell to do it (since I need to be able to close the launcher), but I also would like to downgrade the rights given to the launching application.
Is this possible? The launcher must run as administrator, but I'd like to have the launching application run as user.
this is how I currently run the process:
Process process = new Process();
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = name;
process.Start();
Forgive me I forgot to add a couple of details:
I need to run it in .net 3.5 on mono
I'd prefer to not use native code
I need to run the launcher application in admin mode
This seems to be have discussed before, check this out: How do you de-elevate privileges for a child process
Looks like an UAC elevation is strictly one-way, so the solutions are a bit gnarly, i.e. code injection into explorer and stuff like that.
http://www.codeproject.com/Articles/18946/High-elevation-can-be-bad-for-your-application-How
Eventually I decided to create a bootstrapper that could run the launcher as administrator, but then the application as normal user. Once the launcher is done it goes back to the bootstrap executable which launches the application.
I am getting an exception on my server side code, which is serving up a silverlight app,
Win32Exception - No such interface supported
Our server side C# code starts up a separate process for a short task because of a third party dll not being thread safe. So the error above occurs in part of the code like this,
Process process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.CreateNoWindow = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
processStartInfo.FileName =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "PreviewGenerator.exe");
process.StartInfo = processStartInfo;
process.Start(); // THIS IS WHERE THE EXCEPTION OCCURS
process.WaitForExit();
The PreviewGenerator.exe process does not start when it is not working, the exception occurs where the comment is above.
UPDATE:
I have run process monitor on the IIS server when the issue occurs. This shows that the w3wp process does this,
Thread Create
Access the file PreviewGenerator.exe
Hive unloaded (this is the registry)
Thread Exit
And it does this before calling the other process. If I compare this with a the process monitor log when it is working it does this,
Thread Create
Access the file PreviewGenerator.exe
Process Start
Does heaps of stuff with PreviewGenerator.exe including reading / writing / registry, etc.
Process Exit
Hive unloaded
Thread Exit
But process monitor does not show any information as to why the first case doesn't work.
Is there a way I can see why the thread exits prematurely?
Also I think this problem relates to when my server is being loaded up more, and much more memory is being used. How can I prove this?
I had a similar issue, I used
processStartInfo.UseShellExecute = false;
and that fixed it for me.
http://www.progtown.com/topic31343-process-start-processstartinfo-startinfo.html
I found the best thing to do was to create a separate app pool for my application in IIS and set an upper limit for the amount of RAM it could use. Also I found it useful to turn on the 'Generate Recycle Event Log Entry' items under the app pool settings.
You can then go to the system event log and filter out the items with a source of 'WAS' to understand what is going on in the app pools, when they are restarting and when they stop from being idle etc.
I think the main problem in our case is that the IIS box was running out of memory. Tuning the app pools and adding some extra RAM seems to have solved it.
Processes launched via Process.Start seems to have around a 26-second delay when the spawned process (the "child") launches more new processes (the "grandchildren") - I'm trying to find a way to solve this issue. Specifically, this is occurring when the original process (the "parent") is an ASP.Net website or a Windows Service (tried both).
We're attempting to run a server-side command-line tool to gather information, make modifications in the file system, and continue with other processes when the "child" is finished. When creating the "child" directly via command-line, there is no delay, and with certain command-line parameters, the "child" does not spawn new processes, and there is no delay. However, with other parameters, the "child" spawns "grandchildren" (the same executable as itself, but we can't modify its code) and seems to have a 25-30 second (usually 26 seconds) delay before the first process is started, and then runs normally.
I've tried modifying the UseShellExecute property, the CreateNoWindow property, and the WindowStyle property, to no effect. ErrorDialog and the RedirectStandard* properties are false.
The code I'm using is as follows:
using (Process p = new Process())
{
p.StartInfo = new ProcessStartInfo(exePath, args)
{
WorkingDirectory = workingDirectory,
UseShellExecute = true,
CreateNoWindow = true,
};
p.Start();
p.WaitForExit();
}
Oh, I don't think it matters as I've seen the issue referenced elsewhere (but no solutions), but the exePath I'm using points to msysgit's git.exe.
I had this same exact problem executing a .bat file which in turn made a call to git.cmd using Process.Start from a windows service. The git command would execute immediately if the .bat file was ran directly from the command line, but would delay exactly 50 seconds any time it was called from the windows service.
It came down to a permissions issue. After configuring my windows service to run as a user (administrator in my case), the git process ran immediately. You can probably modify your service installer to run the service as "User", but you can just modify the service properties after it's installed to the same effect.
There may be ways to enable "Local Service" to get around the delay, but I wouldn't know how.
Hard to tell a reason why this might happen, you need to do further troubleshooting.
I would suggest that you use Process Explorer and Process Monitor to look for potential problems.
I would guess that the problem is not directly in your code but more related to the environment of the user. For example, the w3wp.exe process runs in a non-GUI session (session 0) and the user might not be configured to have web access (proxy configuration) so that you might see a timeout issue here.
Is it possible to start a program so that it is available to a user with a windows service? I have been working with the Process.Start() in C#. I can get the service to kickoff some sort of process that appears in the Task Manager list under processes. However, the program nevers appears on the screen. By default, it runs under the user name "SYSTEM". I have adjusted the "Log On" option in the service manager to match the person logged into the computer, but this does not cause a window to appear either.
I feel like I am either missing a simple setting, or need to take a different direction for this. Below is the code I have been working with to start up Firefox as a test app.
private void startRunDap()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "Firefox";
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.UseShellExecute = true;
Process.Start(startInfo);
//Process.Start("Firefox");
}
On Vista and Win7 Services run in their own session with a private desktop. You'll get Firefox started but it will never be visible. The account name is actually how this came about, LocalSystem is a highly privileged account, a giant security hole.
You will need an "agent" in the user session to get the process started. An otherwise invisible program that you start with the Run key or the Startup folder that talks to the service through, say, a named pipe or socket. It can start the program.
Put a tick at "Allow service to interact with user" at properties of service in Services
Here's a link to a blog post that describes how to do this in Windows Vista and later. You should note, though, that the first sentences in the article are:
The first thing you should do about it is that; don't do it. There are many limitations and bad implications and restrictions involved.
In case, you are in a state that you cannot avoid launching an interactive process from Windows Service then you might want to read this article.
Windows SDK blog