How to elevate privileges only when required? - c#

This question applies to Windows Vista!
I have an application which normally works without administrative privileges. There is one activity which does need administrative privilege but I don't want to start the application itself with higher privileges when I know most of time user wont even be using that feature.
I am thinking about certain method by which I can elevate the privileges of application on some event (such as press of a button). Example:
If user clicks this button then he is prompted with UAC dialog or consent. How can I do this?

I don't believe that it is possible to elevate the currently running process. It is built into Windows Vista that administrator privileges are given to a process upon startup, as I understand. If you look at various programs that utilise UAC, you should see that they actually launch a separate process each time an administrative action needs to be performed (Task Manager is one, Paint.NET is another, the latter being a .NET application in fact).
The typical solution to this problem is to specify command line arguments when launching an elevated process (abatishchev's suggestion is one way to do this), so that the launched process knows only to display a certain dialog box, and then quit after this action has been completed. Thus it should hardly be noticeable to the user that a new process has been launched and then exited, and would rather appear as if a new dialog box within the same app has been opened (especially if you some hackery to make the main window of the elevated process a child of the parent process). If you don't need UI for the elevated access, even better.
For a full discussion of UAC on Vista, I recommend you see this very through article on the subject (code examples are in C++, but I suspect you'll need to use the WinAPI and P/Invoke to do most of the things in C# anyway). Hopefully you now at least see the right approach to take, though designing a UAC compliant program is far from trivial...

As it was said there:
Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";
will run the process as admin to do whatever you need with the registry, but return to your app with the normal privileges.

The following MSDN KB article 981778 describes how to 'self-elevate' an application:
http://support.microsoft.com/kb/981778
It contains downloadable samples in Visual C++, Visual C#, Visual Basic.NET.
This approach gets around the need to start a separate process, but in fact it is the original application that is restarted, running as an elevated user. Nevertheless this may still be very useful in some contexts where it is not practical to duplicate code in a separate executable.
To remove the elevation, you need to quit the application.

You need a UAC moniker and the code to run elevated as a COM object.
See this question.
Documentation on MSDN.

Perhaps someone comes in handy this simple example:
using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
internal static class Program
{
private class Form1 : Form
{
internal Form1()
{
var button = new Button{ Dock = DockStyle.Fill };
button.Click += (sender, args) => RunAsAdmin();
Controls.Add(button);
ElevatedAction();
}
}
[STAThread]
internal static void Main(string[] arguments)
{
if (arguments?.Contains("/run_elevated_action") == true)
{
ElevatedAction();
return;
}
Application.Run(new Form1());
}
private static void RunAsAdmin()
{
var path = Assembly.GetExecutingAssembly().Location;
using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
{
Verb = "runas"
}))
{
process?.WaitForExit();
}
}
private static void ElevatedAction()
{
MessageBox.Show($#"IsElevated: {IsElevated()}");
}
private static bool IsElevated()
{
using (var identity = WindowsIdentity.GetCurrent())
{
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
}
}

I know this is an old post, but this is in response to anyone else who comes across MarcP's suggestion. The msdn post he referenced indeed does restart the applications in all of the code examples. The code samples use the runas verb proposed already in other suggestions.
I downloaded the code to make sure, but this is from the original msdn article:
4. Click Yes to approve the elevation. Then, the original application
restarts, running as an elevated administrator.
5. Close the application.

Related

How to display application normally

I am creating a complex service on Windows 7, which starts off by loading an .exe application. The only way to achieve this was to enable to "Interactive Services Detection" service in services.msc.
As a test application, I added the following code which simply opens the system calculator. It works, however not as intended. I first get the following message when starting the service:
When clicking "View this message", it loads the calculator as it is supposed to, but opens a blue full screen mode, and contains the calculator within it.
My question is basically the following: How can I make the application display automatically, and not have to prompt the user to "view the message", and more importantly, how can I get the application to display normally, rather than in this "interactive services detection" sandbox?
This is the code of my sample service:
public partial class OpenCalculator : ServiceBase
{
public Process process;
public OpenCalculator()
{
this.ServiceName = "Open Calculator";
InitializeComponent();
}
protected override void OnStart(string[] args)
{
start_calc();
}
protected override void OnStop()
{
process.Kill();
}
protected void start_calc()
{
try
{
process = new Process();
process.StartInfo.FileName = #"C:\Windows\system32\calc.exe";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.Start();
using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
{
writer.WriteLine(process);
}
}
catch (Exception ex)
{
using (StreamWriter writer = File.AppendText("C:\\Users\\scaruana\\Desktop\\test.txt"))
{
writer.WriteLine(ex.Message);
}
}
}
}
Services run in session 0, whose desktop you cannot see. Interactive desktops are hosted in other sessions. So, for instance, the first interactive logon runs in session 1. This means that services cannot directly show UI on an interactive desktop.
In older versions of Windows (XP and earlier), the first interactive logon shared session 0 with services. And so when you enabled the allow service to interact with desktop option in the service control manager, the service could show UI on an interactive desktop. However, all that ended with Vista because it was a security risk.
So, you need to start a new process and specifically force it onto the desktop of an logged in interactive user. That is not easy to do. This MSDN blog article covers your options: Launching an interactive process from Windows Service in Windows Vista and later.
Now, that's how you go about starting a new process from a service, and putting the new process onto an interactive desktop. But that is almost certainly the wrong way to solve your problem. As you can see by reading the linked article, doing it that way is complex. The standard solution to your problem is to run an interactive process on the logged in user's desktop. This remains hidden until your service needs to show UI. The service then communicates with the desktop app using your preferred IPC mechanism, and then the desktop app shows the UI.
This question has been the cause of great frustration, and I have finally solved my problem. Yes, I have managed to make a service load a GUI application, even though everyone says that it is impossible. There is a warning though - the "fix" can be considered as exploiting a loophole in Windows, as the code which I used basically passes the Vista and Windows 7 UAC. Essentially, the application is always executed with full rights and bypasses the UAC.
If anyone has this same problem, what you need to do is iterate through a list of logged in users on the PC, and choose to open the UI application in this session (which has the user's desktop), rather than in session 0 where the service is supposed to be running (and which does not have a desktop).
For some people, this might not be a solution as it is not secure. But in my case, security is not a main concern, and I just needed it to work (had to be a service by force).
Hope this helps anyone who has the same problem that I had.

issue with starting and a killing a process in windows 7

i am trying to start a browser instance as a process from a c# code. then i want to kill the same instance of the browser. I tried finding the same instance with process id . But the process ids are different in task manager and the initial id which i got when i started the process.
what's the solution? why is this happening? Development enviorment is windows 7.
int ID= 0;
void Start()
{
ProcessStartInfo startInfo = new ProcessStartInfo("iexplore.exe");
startInfo.Arguments = "http://www.google.com";
Process ieProcess = Process.Start(startInfo);
ID= ieProcess.Id;
}
void Stop()
{
foreach (Process p in System.Diagnostics.Process.GetProcessesByName("iexplore"))
{
if ((p.Id == ID))
{
p.Kill();
}
}
This code will not work if IE is already launched. Close all IE browsers and then try to run the code. If it works then you may have to look for solution suggested in following link
similar post-
Process.kill() denied in Windows 7 32bits even with Administrator privileges
Why don't you add your code to the question? It'll make life easy for the people who are interested in helping you. If you get different PIDs, most probably there's something wrong with your code! (I'm just guessing without seeing what you have tried.)
Have a look at these questions as well.
1) Getting PID of process started by Process.start()
2) Programmatically kill a process in vista/windows 7 in C#
3) Process.kill() denied in Windows 7 32bits even with Administrator privileges
Adding the code makes it much easier to understand what the problem is and here's your problem.
IE creates more than one process for one instance of the program. (more details about it) That's why you get different PIDs (for the different processes).
What your code does is killing only one process of it (by the usage of if condition in the Stop() method!). So the remaining process may generate InvalidOperationException when you try to execute Start() again(starting the same process)!
So what your code should do is kill all the active iexplore processes. This can be done by simply removing the if condition of Stop() method.
foreach(Process p in Process.GetProcessesByName("iexplore"))
{
p.Kill();
}
Let me know whether this worked.
I have a similar issue, only I dont want to kill the IE process that I started, I want to bring it into focus.
I have one app that starts 5 IE windows.(not tabs, but unique windows)
I store the PIDs that I start each of the IE windows with.
At particular times, I want to be able to:
select a PID,
find the IE window related to that PID
bring it into focus (minimizing the others)
This worked using XP and IE6 (required for the environment)
Now when I am using Win 7 and IE 8, the PID that I stored is not found,
and thus I no longer have the ability to change the window in focus.

Restart program unelevated

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.

Windows Network Information Manipulation

I am working as a trainee engineer in a networking firm and am getting annoyed by having to change the IP information from time to time.
I am in need of building a software to help me change these details easily. I have managed to set the IP information. But I still have problems.
I need to run the program as Administrator [right click], is there a way to program to prompt for it at startup?
How can I change adapter to DHCP?
The code is quite long, and I hope not to fill bore you with it. But I have been using Management
Management Class
Management Base Object
Management Object Collection in my development.
I'd prefer to make my own program to develop my programming skills. But if there is an application to do it, I don't mind knowing.
I hope this answer gives you some insisght and direction to go.
Okay, the network adapter one isn't that straight forward, but I believe you can achieve it with WMI, specially this WMI object here. The MSDN documentation tells you all the properties, methods (which there are for setting DHCP etc) and the datatypes and values it takes. This may be one approach as using WMI through C# is pretty easy. I wish I could provide you an example, but I've never used that specific WMI class before. You can also access the above WMI class through the Visual Studio Server Explorer, which you can see here. ..and it has your "EnableDHCP" method you are probably looking for.
As far as asking for your program to run with administrative priviledges, here is the code from my setup project in my framework. What this does is before it runs any sort of form or logic, requests the "runas" verb which invokes UAC (if Windows has its Vista/7, and requests admin priviledges from the user)
namespace Setup {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Setup.Forms;
using System.Security.Principal;
using System.Diagnostics;
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool administrativeMode = principal.IsInRole(WindowsBuiltInRole.Administrator);
if (!administrativeMode) {
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.FileName = Application.ExecutablePath;
try {
Process.Start(startInfo);
}
catch {
return;
}
return;
}
Application.Run(new ShellForm());
}
}
}
As far as a program to do it, Windows Network Connection Manager? I know its cumbersome because of all the dialogs, but.. its already there.
I once had to write a very similar program. I used some of the source code from these two projects to help me get started: Chameleon Project and Configuring TCP/IP Settings using WMI and C#
The Chameleon Project is a C# project to help change network settings of a particular adapter. The other project is a tutorial on how to use C# to change network settings using WMI and C#. You can look at the source code and learn from it to help you make your own software that does what you need.

How do you program a windows service in C# to start an application for a user?

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

Categories

Resources