即使用户具有管理权限,App也无法写入注册表

时间:2013-03-31 12:52:03

标签: c# .net registry .net-2.0 uac

我正在使用Visual Studio 2010,我正在编写一个需要在HKLM\Software\myapp

下设置(和读取)新注册表值的程序

该程序基于.NET 2.0,目前它在Windows 7 64位上运行。这是我的ocde:

RegistryKey softwareKey = Registry.LocalMachine.OpenSubKey("Software", true);
RegistryKey MyKey = softwareKey.CreateSubKey("MyApp");
RegistryKey  = MyKey.CreateSubKey("MyKey");
selfPlacingWindowKey.SetValue("instaldateperson", datestr + usrname);     

我在运行Visual Studio 2010时遇到的问题是,它将运行应用程序,但以我身份登录,我是本地管理员组的用户和成员..但是我无法创建密钥(尽管我是本地管理员组,有权这样做)。我也不知道如何将其作为登录(但它也不是我想要的,因为那时我会将Adminuser和密码放在代码中,我已经是管理员了 - 所以为什么?)

如果根本不可能,是否有创建注册表项的选项?

以某种方式将它们添加到项目中等等......我在这里有点困惑。

6 个答案:

答案 0 :(得分:9)

仅仅因为您以管理员身份运行(或使用具有管理权限的帐户)并不意味着这些管理权限始终有效。这是一项安全措施,可防止恶意软件利用贪婪地使用其计算机并始终具有管理权限的用户。

要获得管理权限,您需要提升该流程。有两种方法可以做到这一点:

  1. 使用表明您的应用程序需要管理权限的清单,从而在启动时要求提升。

    这意味着您的应用程序将始终运行提升,并且只应在您的应用程序需要时使用。例如,Windows注册表编辑器(RegEdit)执行此操作,因为没有管理权限,您几乎无法执行此操作。

    查找有关如何完成此here on MSDNmy answer here的信息。基本上,您只想在清单中添加以下行:

    <requestedExecutionLevel level="requireAdministrator" />
    
  2. 如果您只需要某些任务的管理权限(即将特定设置保存到注册表)并且应用程序的其余部分不需要它,则应启动新的提升过程来执行此操作。暂时无法提升当前流程,因此您实际上需要剥离新流程。

    此方法的优点是您的应用程序不必一直以管理权限运行(这会增加安全性),并且没有管理权限的用户仍然可以运行您的应用程序来执行其他所有操作(即除了需要提升的一个或两个任务之外的所有任务)。

    您分离出一个单独的进程,该进程仅包含使用Process类写入注册表所需的逻辑,并使用runas动词请求提升此进程。有关更多信息,请参阅this question。我还写了an answer,它提供了如何从C#完成此操作的完整描述,包括示例代码。

  3. 当然,正如其他答案所提到的,应用程序的设计更有可能是错误的。 Windows安全模型的整个逻辑是常规应用程序不需要管理权限。他们不需要写入注册表或做其他可能危及机器的事情。如果您需要保留设置,我可以建议其他两种可能的方法:

    1. 认识到Windows确实是一个多用户操作系统,只为当前用户编写设置。无论如何,这很有道理,因为不同的用户通常具有不同的设置和偏好。您需要使用HKEY_LOCAL_MACHINE,而不是注册表的HKEY_CURRENT_USER分支(需要管理员权限才能访问)。将您的第一行代码更改为:

       RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
      
    2. 通过使用.NET内置的逻辑来保留应用程序的设置,完全消除了写入注册表的所有麻烦和复杂性。开始阅读the answers herehereMSDN,了解如何操作。我会说这是你最好的选择。不要自己编写复杂的代码来执行您使用的框架已经内置支持轻松完成的操作。

答案 1 :(得分:3)

您的应用程序的设计可能是错误的。标准桌面应用不应写入HKEY_LOCAL_MACHINE。由于UAC,您需要拥有管理员权限,并且必须在提升的流程中运行才能写入HKLM

如果您的应用程序确实需要对HKLM进行更改,请考虑在安装时执行此操作,因为安装程序将被提升。

如果桌面应用程序确实需要写入HKLM,那么它应该考虑将需要运行的应用程序的那些部分分离到一个单独的进程中。否则,用户将非常厌倦了必须通过UAC对话框才能运行您的应用程序。即使他们没有使用写入HKLM的应用程序部分。如果您强制整个应用程序需要提升,那么标准用户根本无法运行它。

答案 2 :(得分:2)

运行Visual Studio时无法在HKEY_LOCAL_MACHINE下创建密钥的原因是因为Visual Studio未作为提升的进程运行。

对于最终用户,应用程序的清单需要指示需要完全管理员权限。以下是embedding a manifest for UAC

的文档

如果注册表项不需要在机器上是全局的,请考虑写入HKEY_CURRENT_USER。

答案 3 :(得分:1)

您应该授予在方法中键入密钥后添加真实值的可写权限。

Registry.LocalMachine.CreateSubKey(@"YOURKEY", true);
Registry.LocalMachine.OpenSubKey(@"YOURKEY", true);

此外,您还需要高级权限才能执行此操作,然后可以创建一个.manifest文件,并在requireAdministrator中设置级别,如下所示:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

注意: 在您的代码中:

RegistryKey softwareKey = Registry.LocalMachine.OpenSubKey("Software", true);
RegistryKey MyKey = softwareKey.CreateSubKey("MyApp");
RegistryKey  = MyKey.CreateSubKey("MyKey");
selfPlacingWindowKey.SetValue("instaldateperson", datestr + usrname);

检查对象标签是否正确,是否使用标签softwareKeyMyKey创建对象,但使用另一个标签selfPlacingWindowKey设置值。

答案 4 :(得分:0)

恢复。在项目中创建.manifest文件。为它指定与可执行文件相同的名称。 &#34; name_of_executable.exe.manifest&#34;最后更改或创建标记:

<requestedExecutionLevel level = "requireAdministrator" uiAccess = "false" />

答案 5 :(得分:0)

之前的答案提到您需要在清单中指定您需要管理员权限才能使用HKLM

您可以通过;

创建清单
  1. 右键点击您的项目,
  2. 要添加新
  3. 点击常规
  4. 单击Application Manifest File
  5. 点击添加
  6. 打开您的清单文件,找到并取消评论requireAdministrator
  7. 在您的项目设置中勾选Prefer 32bit时,可能会让您感到沮丧的更微妙的事情。

    这意味着注册表无法获取所需的访问掩码,并且它将在没有内部异常的情况下静默失败,因为错误处理程序需要相同的访问掩码,因此无法利用它。

    除非您绝对需要在用户之间保留设置,否则应避免将内容存储在注册表的这一部分中。注册表也不应用于存储密码或其他敏感信息,因为即使使用ACL也无法可靠地控制访问。