How do I check whether a user is allowed to read /

2019-02-08 08:55发布

Does anybody know how I can programmatically check (using C#) whether my program will be able to read / write a particular registry key (specifically: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run")?

I am asking because my program has the option to enable or disable the 'run at startup' behaviour. I want to disable this option if the current user is not allowed to make changes to the registry. Is this key always allowed to be written by the current user, or is there the possibility that it has been locked down? If the latter, how do I check this?

I have seen several conflicting ways of checking registry permissions - but basically I can't find a way to check a specific key before I try to read it. I would rather perform the check before accessing the key than trying to access it and receive an exception.

Any help is much appreciated.

Tom

6条回答
Bombasti
2楼-- · 2019-02-08 09:38

One thing you should know about permissions is that they are volatile. That means you could do your security check on the registry key, attempt to add your value only if the check passes, and then still fail with an insufficient access exception because the permissions changed in between when you made the check and when you acted on the results. This is possible even if they are consecutive statements in your program.

Granted security permissions tend to be relatively stable, but the chance still exists. This means that you must have code to handle the security exception, and if you have to do that anyway there's not really any point in making the check in the first place. Instead, put your time into making your exception handler a little bit better.

That said, "boo" to any app that wants to run something at start-up. YAGNI.

查看更多
疯言疯语
3楼-- · 2019-02-08 09:47

The RegistryPermission class governs the security permissions around reg keys. To check if you may have write access to a permission you use it in the following manner:

RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");

You would then use the "Demand" method in a try/catch and return on failure (the raising of a security exception). On success you'd carry on and perform your update. Although this isn't quite what you want, a check on permissions before access, it is the accepted way of ensuring you have the permissions you need before you operate on the keys. In a fully structured manner this would equate to:

try
{
    RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
    perm1.Demand();
}
catch (System.Security.SecurityException ex)
{
    return;
}

//Do your reg updates here

EDIT: Thinking on what I mentioned in the comment, here are extension methods to the RegistryPermission class for permission checks:

using System.Security.Permissions;
using System.Security;

public static class RegistryExtensions
{
    public static bool HavePermissionsOnKey(this RegistryPermission reg, RegistryPermissionAccess accessLevel, string key)
    {
        try
        {
            RegistryPermission r = new RegistryPermission(accessLevel, key);
            r.Demand();
            return true;
        }
        catch (SecurityException)
        {
            return false;
        }
    }

    public static bool CanWriteKey(this RegistryPermission reg, string key)
    {
        try
        {
            RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Write, key);
            r.Demand();
            return true;
        }
        catch (SecurityException)
        {
            return false;
        }
    }

    public static bool CanReadKey(this RegistryPermission reg, string key)
    {
        try
        {
            RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Read, key);
            r.Demand();
            return true;
        }
        catch (SecurityException)
        {
            return false;
        }
    }
}
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-02-08 09:56

I think you best bet is to just try to add your value to the key, and handle failure gracefully by informing the user they didn't have enough permissions to do that.

If you're writing some sort of administrative tool that is designed to always be run by an administrator, you should indicate that in the manifest. That way your app will elevate at startup (via UAC prompt).

查看更多
SAY GOODBYE
5楼-- · 2019-02-08 09:57

Just try to open the registry key with WRITE permissions.

That said, what others have said is right: There is no way to tell if an operation is going to succeed unless you try it. Maybe someon deleted the Run key. Maybe the registry will exceed allocated memory. Maybe the disk failed.

查看更多
疯言疯语
6楼-- · 2019-02-08 09:58

I'm not sure how to it with C#, but with Win32, you would use RegGetKeySecurity(). Maybe there's a C# wrapper? Otherwise, use P/Invoke.

查看更多
我只想做你的唯一
7楼-- · 2019-02-08 09:59

Simplest option is to try and open the key with write access and see if you get it. Remember to close the key afterwards.

bool fWriteAccess;
try {
    Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", True).Close();
    fWriteAccess = True;
} catch (SecurityException) {
    fWriteAccess = False;
}
查看更多
登录 后发表回答