The other day, I came across an application that when you run it, it comes up with the UAC screen and requests to be run with administrator privileges. Clicking 'Yes' on the UAC screen runs the application like normal. The interesting thing is that if you click 'No', the application, instead of exiting, still runs, but runs in a limited user account (with less functionality, of course).
My question is, how can I configure my C# application to do this? I know my application can have an application manifest to run in elevated privileges, but how do I duplicate the kind of behavior I just explained above?
To do this with a different elevated application you can use a "launcher" (or the launcher is the "normal" app).
If you wanted three applications you might have a WinForms launcher something like:
[STAThread]
static void Main()
{
const int ERROR_CANCELLED = 1223;
try
{
Process.Start("el.exe");
// ran el in elevated node...
}
catch (Win32Exception ex)
{
if (ex.NativeErrorCode == ERROR_CANCELLED)
{
Process.Start("normal.exe");
}
}
}
If you were doing two applications, you could do something like:
[STAThread]
static void Main()
{
const int ERROR_CANCELLED = 1223;
try
{
Process.Start("el.exe");
// ran el in elevated node...
}
catch (Win32Exception ex)
{
if (ex.NativeErrorCode == ERROR_CANCELLED)
{
// "continue" as un-elevated app.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
You can keep all the code in one application. The application manifest does not request the application to be run elevated, it uses asInvoker level.
When the application is started, it tries to re-start itself elevated. I mean it starts another process with runas verb. If it succeeds, then the first instance just exists.
If elevation was not successful, then it continues to run with limited functionality.
But think about the user experience:
Not everyone in the world works as administrator. For them, elevation would not look as clicking Continue button, the UAC will ask them to provide user name and password of an administrator.
From this point of view, Microsoft recommended approach works great: run as regular user until you really need to elevate. All elevation points should be clearly marked in the UI. You can still use the same exe file to run non-elevated and elevated instances, yet you must implement a communication mechanism so the non-elevated instance can provide all the data to perform the operation requested by the user. Once you started elevated instance, you can keep it running and exit the non-elevated one, so that other operations could be performed without elevation.
Thus it means more effort, but a much better user experience.
Related
(There is a very similar topic that never got solved:here)
Here is my code
for (int i = 0; i < 5; i++)
{
Thread.Sleep(10000);
Console.WriteLine("Hi");
Process.Start("shutdown", "/s /t 0");
}
If I locked my system the shutdown process is not working otherwise it's working fine. When I unlock my system after 2 min it's showing only hi (5 times).
I think the shutdown command requires elevated privilege, so whether you call it your way or use an API, I would expect a UAC prompt to be required. You don't specify which version of Windows you're on but I think it's safe to assume UAC is present.
When the system is locked, a UAC prompt can't be shown and it times out after a while. So without an interactive user's express permission your shutdown can't proceed.
I think, to achieve your aim, you'd need to create a windows service that runs with high privilege, and have it call the correct API to shut the machine down. Then you can have a normal process communicate with your service and tell it to do the shutdown.
I hope somebody else can come up with a simpler solution for you.
Did you try other parameters of shutdown.exe like /p and/or /f?
I'm trying to determine if another application is running as an administrator. There are 100's of SO questions about finding if your application is or not, but not for another application.
If I do var processes = Process.GetProcesses(); and loop through them, they don't appear to have any "Elevated" or "IsAdministrator" properties on them. I also found a function on here to get the Owner but they all come back as "My-Laptop\Me" so that's not working for me the way I hoped it would.
Is there a way to find this? I'm on Win 8.1 and would prefer something that works for 7 as well, but if it only works for 8.1+ that's totally fine.
Thanks!
EDIT:
My application has to run as an administrator.
You can use the technique from this answer, just replace Process.GetCurrentProcess().Handle with the Process.Handle of the other process.
If you look at the code (there's quite a bit of code there) it get the process "user token" (the permissions the process is running under) and checks if this token has the administrator role or not,
Assuming your process is not running as administrator, trying to get information about a process that is elevated via UAC (such as its MainWindowTitle) will throw an AccessDenied exception, where a non-elevated process will permit you access to that information. This assumes you also verify the owner of the process to check that it's you.
try
{
var foo = process.MainWindowTitle;
return false; //Process is not elevated
}
catch (Win32Exception ex)
{
return true; //Process is elevated if ex error code is AccessDenied
}
I am developing a simple application where in we have predefined quotas on usage for each user on the system..
and if the quota is up..the system should logoff of the user account..
this will happen if the application is allowed to run..
but if the user is closing the application on his own ..the app should automaticaly logoff the account..
i did exactly that in writing forced logoff code in form-closing event..
but if we are closing the app/process using the taskmanager..
the form closing event is not being called.
and so the user is able to continue even if his quota of time is up..
can anybody helpme out with this..
This is nice question.
Maybe you can make an applicaton to watch task manager and user status. I am not sure about that could help you but I gonna write
for ex
Process[] myApp = Process.GetProcesses("My Application");
if (myApp.Length == 0)
{
// App closed, and check the user status
// If user is still up, make it logoff,
// Also you can track processes with ProcessId too GetProcessesById(5415)
}
else
{
// App is running, there is no problem
}
I am using the below code to disable the task manager for a kiosk application which works perfectly
public void DisableTaskManager()
{
RegistryKey regkey;
string keyValueInt = "1";
string subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
try
{
regkey = Registry.CurrentUser.CreateSubKey(subKey);
regkey.SetValue("DisableTaskMgr", keyValueInt);
regkey.Close();
}
catch (Exception ex)
{
MessageBox.Show("DisableTaskManager" + ex.ToString());
}
}
But when i run this in OS hardened machine i get the following error,
DisableTaskManagerSystem.UnauthorizedAccessException:
Access to the registry key 'HKey_Current_User\Software\Mictrosoft\Windows\CurrentVersion\Policies\System' is denied.
at Microsoft.win32.RegistryKey.win32Error(int32 errorcode, String str)
How can i overcome this ? I need to do this for a Kiosk application.
take a look at this, im not yet a good enough C# Developer to comment but i know that during my work with other developers they came accross the UAC In windows 7, If thats what were talking about here.
http://www.aneef.net/2009/06/29/request-uac-elevation-for-net-application-managed-code/
Well the guy that set up that machine basically asked the reverse... "How do I prevent a non-administrator from messing with group policy". So rather engaging in a group policy arms race, you can either do it at install time when running as an admin, or just skip that part of the code when not running as a user that has permission to do so.
Don't have your application disable task manager but instead use a windows service or scheduled task. Your application is going to run in the context of the current user and won't have rights to the registry key. Instead you can create either a windows service or a scheduled task which can run as a user with higher privileges and can write to the registry.
With a windows service you can communicate it through any IPC mechanism such as custom service messages, Sockets, .NET Remoting, WCF, or whatever, to tell it to turn task manager on/off.
the code requires an elevated privilege to access registry. However there is just a fragment of code that requires these extra permission. To handle such scenarios impersonation is used i.e. you will execute this application as normal user only but that particular piece of code will be executed as if you were an Administrator.
http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx
Is there a way to request elevated privileges from the os, for "just a part" of a c# program?
I'm writing a bunch of integrationtests using NUnit. One of the things I'm testing is if the application under test correctly connects to port 843. The test opens a listening socket at port 843, and then throws all sorts of responses to the application under test, and verifies if the application behaves correctly.
Opening a listening socket on port 843 requires admin privileges however.
I'd like to find the least intrusive way to be able to run this test. I could run the entire NUnit suite as root/admin, but that would make a lot of stuff run as root, that really doesn't need to be ran as root, which I'd like to prevent.
If required below code would help you to find out if the current logged in user is admin or not:
using System;
using System.Security.Principal;
class Test
{
public static void Main()
{
if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
{
Console.WriteLine("I am an admin.");
}
}
}
Nope. Elevation is all or nothing. Typically if elevation is required, the app bootstraps itself into an elevated state.
Yes, you could take a look at the LogonUser function. Here's a sample.
A process has to be started with elevated privileges to have elevated rights. You cannot change your elevated status "in process".
A way to work around this is to do as Task Manager. If you run that "unelevated" and click on "Show processes for all users", it basically kills of the old task manager process and starts a new one with elevated privileges in order to do the job.