如何检查是否允许用户读/写特定的注册表项?

时间:2023-02-07 13:02:08

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")?

有没有人知道如何以编程方式检查(使用C#)我的程序是否能够读/写特定的注册表项(具体为:“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 个解决方案

#1


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类管理reg键周围的安全权限。要检查您是否具有对权限的写入权限,请按以下方式使用它:

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 / catch中使用“Demand”方法,并在失败时返回(引发安全性异常)。成功后,您将继续并执行更新。虽然这不是您想要的,但在访问之前检查权限,这是确保您在操作密钥之前拥有所需权限的可接受方式。以完全结构化的方式,这相当于:

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:

编辑:考虑我在评论中提到的内容,这里是RegistryPermission类的权限检查的扩展方法:

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;
        }
    }
}

#2


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.

也就是说,对任何想要在初创公司运行的应用程序都说“嘘”。 YAGNI。

#3


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).

如果您正在编写某种旨在始终由管理员运行的管理工具,则应在清单中指明。这样你的应用程序将在启动时提升(通过UAC提示)。

#4


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;
}

#5


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.

我不确定如何使用C#,但使用Win32,您将使用RegGetKeySecurity()。也许有一个C#包装器?否则,请使用P / Invoke。

#6


Just try to open the registry key with WRITE permissions.

只是尝试使用WRITE权限打开注册表项。

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.

也就是说,其他人所说的是对的:除非你尝试,否则无法判断一项手术是否会成功。也许有人删除了Run键。也许注册表将超过分配的内存。也许磁盘失败了。

#1


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类管理reg键周围的安全权限。要检查您是否具有对权限的写入权限,请按以下方式使用它:

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 / catch中使用“Demand”方法,并在失败时返回(引发安全性异常)。成功后,您将继续并执行更新。虽然这不是您想要的,但在访问之前检查权限,这是确保您在操作密钥之前拥有所需权限的可接受方式。以完全结构化的方式,这相当于:

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:

编辑:考虑我在评论中提到的内容,这里是RegistryPermission类的权限检查的扩展方法:

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;
        }
    }
}

#2


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.

也就是说,对任何想要在初创公司运行的应用程序都说“嘘”。 YAGNI。

#3


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).

如果您正在编写某种旨在始终由管理员运行的管理工具,则应在清单中指明。这样你的应用程序将在启动时提升(通过UAC提示)。

#4


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;
}

#5


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.

我不确定如何使用C#,但使用Win32,您将使用RegGetKeySecurity()。也许有一个C#包装器?否则,请使用P / Invoke。

#6


Just try to open the registry key with WRITE permissions.

只是尝试使用WRITE权限打开注册表项。

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.

也就是说,其他人所说的是对的:除非你尝试,否则无法判断一项手术是否会成功。也许有人删除了Run键。也许注册表将超过分配的内存。也许磁盘失败了。