UnauthorizedAccessException when creating a registry key - c#

I'm researching on how to add a shortcut in the windows context menu to my application. I came across this article and I tried it out. This is the code it uses to create a key in the registry.
private void btnAddMenu_Click(object sender, System.EventArgs e)
{
RegistryKey regmenu = null;
RegistryKey regcmd = null;
try
{
regmenu = Registry.ClassesRoot.CreateSubKey(MenuName);
if(regmenu != null)
regmenu.SetValue("",this.txtName.Text);
regcmd = Registry.ClassesRoot.CreateSubKey(Command);
if(regcmd != null)
regcmd.SetValue("",this.txtPath.Text);
}
catch(Exception ex)
{
MessageBox.Show(this,ex.ToString());
}
finally
{
if(regmenu != null)
regmenu.Close();
if(regcmd != null)
regcmd.Close();
}
}
The problem is if I run it through my Administrator account, it works fine. But when I do it through a different account which doesn't have admin privileges, it throws this exception.
system.unauthorizedaccessexception access to the registry key is denied
Now if I were to use this code in one of my own applications to create a shortcut in the context menu, I can't be sure every user would run it as the Administrator, right?
Is there any way in C# to escalate the user privileges when creating the registry key?
If you know any other way to add an item to the windows context menu, I'd be interested in them too.
Thank you.

You cannot escalate permissions as such (at least I'd like to know about it, but doesn't seem possible as yet), but you need to run / start your app (embed into manifest) elevated.
Please take a look at these entries...
How do I force my .NET application to run as administrator?
Elevating process privilege programatically?
I'd suggest what comments said, running that from the setup. Or let your app run as admin from the start, or possibly jump start an elevated process from your app - when needed (e.g. running another exe of yours that has its manifest properly).

You could escalate your permissions much the same way installers do it. It will require user interaction, as that's the way the OS is designed (and rightly so) - you can't go around it.

Related

Find out if another application is running as admin

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
}

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Forced the application to have the administrator privileges

I need to give my application administrator rights, knowing that it will be run from a user session and not admin account.
I've looked on other sites, but can't find anything that helps.
I tried editing the manifest among other things and there have inserted the line:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
This gave me an error when trying to publish using ClickOnce, but not when I debug.
Can you help me?
first of all - indeed, it's not allowed by design, to install and ClickOnce app as admin: http://msdn.microsoft.com/en-us/library/142dbbz4(v=vs.90).aspx
take a look at this post: http://antscode.blogspot.ca/2011/02/running-clickonce-application-as.html -
it explains how to run ClickOnce app as admin. BUT - it have to say that I have walked this path - and I did not have much luck with it. I had numerous troubles with this approach (trying to run ClickOnce app with admin privileges). As far as I recall, the biggest problem was auto-update was not working properly. Not to mention that non-admin users might need to enter admin credentials all the time.
So my advise would be to rethink your logic, and encapsulate the piece you need to be done as admin in a separate EXE file - and make it very clear for a user that when he clicks THAT button, UAC prompt will show up (probably by addin "shield" icon to the button). And in that button_click event do something like this:
// 2. Run Photoshop action on this image (and wait for the task to complete)
if (string.IsNullOrWhiteSpace(this.PhotoshopEnhanceActionAbsPath) == false)
{
var pi = new ProcessStartInfo(this.PhotoshopEnhanceActionAbsPath, "\"" + imgPhotoshopActionAbsPath + "\"");
pi.UseShellExecute = true;
pi.Verb = "runas";
var photoshopAction = Process.Start(pi);
var success = photoshopAction.WaitForExit();
if (success == false)
{
// do something here
}
}
this approach worked very well for me. The key here is this:
pi.UseShellExecute = true;
pi.Verb = "runas";
it runs your EXE with admin right - so UAC prompt will be displayed at that moment. Another nice consequence here is that users might not run this particular piece of logic each time they are using the app - and therefore they won't be annoyed by the prompt when they do not need it.
I'm pretty sure that this behaviour is by design.
ClickOnce apps are designed to be installable without Administrator privileges. It's not possible to elevate them at runtime as this means that effectively a user with no admin rights could install then run the app as admin; this would be a security risk.

security exception accessing registry when the program runs as scheduled task

the following small line throws a System.Security.SecurityException: Requested registry access is not allowed:
RegistryKey _key = HKLM.OpenSubKey("path\\to\\my settings", false);
Now.. what's the point some would ask? The point is that this runs ONLY when I am logged on. The exception is thrown if the program runs as scheduled task and nobody is logged on.
the user who runs that task is local administrator
the program does not run from a network share, it is located on the local disk
I even tried setting Code Access Security
the user has the rights to log on as a batch job
I have XP SP3 with all patches applied. The program is written in C# .Net 2.0 (tested 3.5 too)
Does anyone know whats the point here?
Torsten
EDIT: see http://gist.github.com/638576
Mhhhh...it seems related to Authorization problem too. Have you tried to use the API: OpenSubKey(...., RegistryKeyPermissionCheck) to see if something change? I guess it could be related to parent key and its authorization.
Try to see: http://msdn.microsoft.com/it-it/library/microsoft.win32.registrykeypermissioncheck.aspx (in your language). I hope it could help you...
Can you adapt this
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
string isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator) ? "Yes" : "No";
to check that the process really is successfully impersonating when there's no current user?
It seems that this is a problem of this specific computer. I tested it on another workstation and it works even without administrator privileges.
I assumed this - the program did run for years without any problems... Anyway, thanks to all!

Disabling Task manager using c# in OS Hardened machine

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

Categories