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

我正在使用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和密码放在代码中,我已经是管理员了?所以为什么?)

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

不知何故将它们添加到项目中等等……我在这里有点困惑。

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

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

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

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

    在MSDN或我的答案中找到有关如何完成此操作的信息。 基本上,您只想将以下行添加到清单中:

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

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

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

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

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

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

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

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

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

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

对于最终用户,应用程序的清单需要指示需要完全管理员权限。 以下是有关为UAC嵌入清单的文档

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

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

  

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

你可以创建一个清单;

  1. 右键单击您的项目,
  2. 要添加新内容
  3. 单击常规
  4. 单击Application Manifest File
  5. 单击添加
  6. 打开清单文件,找到并取消注释requireAdministrator

可能让你沮丧的更微妙的事情是在你的项目设置中勾选Prefer 32bit

这将意味着注册表无法获取它所需的访问掩码,并且它将在没有内部exception的情况下以静默方式失败,因为error handling程序需要相同的访问掩码,因此无法利用它。

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